1 |
+ |
#____________________________________________________________________ |
2 |
+ |
# File: SCRAMGrapher.pm |
3 |
+ |
#____________________________________________________________________ |
4 |
+ |
# |
5 |
+ |
# Author: Shaun Ashby <Shaun.Ashby@cern.ch> |
6 |
+ |
# Update: 2004-06-30 11:01:02+0200 |
7 |
+ |
# Revision: $Id$ |
8 |
+ |
# |
9 |
+ |
# Copyright: 2004 (C) Shaun Ashby |
10 |
+ |
# |
11 |
+ |
#-------------------------------------------------------------------- |
12 |
+ |
package BuildSystem::SCRAMGrapher; |
13 |
+ |
require 5.004; |
14 |
+ |
use Exporter; |
15 |
+ |
|
16 |
+ |
@ISA=qw(Exporter); |
17 |
+ |
@EXPORT_OK=qw(); |
18 |
+ |
|
19 |
+ |
sub new() |
20 |
+ |
############################################################### |
21 |
+ |
# new # |
22 |
+ |
############################################################### |
23 |
+ |
# modified : Wed Jun 30 11:01:31 2004 / SFA # |
24 |
+ |
# params : # |
25 |
+ |
# : # |
26 |
+ |
# function : # |
27 |
+ |
# : # |
28 |
+ |
############################################################### |
29 |
+ |
{ |
30 |
+ |
my $proto=shift; |
31 |
+ |
my $class=ref($proto) || $proto; |
32 |
+ |
my ($depdata)=@_; |
33 |
+ |
my $self={}; |
34 |
+ |
bless $self,$class; |
35 |
+ |
# The dependencies will either be collected via methods in this object or |
36 |
+ |
# as input: |
37 |
+ |
$self->{DEPENDENCIES} = $depdata; |
38 |
+ |
$self->{DEPENDENCIES} ||= {}; |
39 |
+ |
return $self; |
40 |
+ |
} |
41 |
+ |
|
42 |
+ |
sub vertex() |
43 |
+ |
{ |
44 |
+ |
my $self=shift; |
45 |
+ |
my ($start) = @_; |
46 |
+ |
$self->{DEPENDENCIES}->{$start} = {}; |
47 |
+ |
return $self; |
48 |
+ |
} |
49 |
+ |
|
50 |
+ |
sub edge() |
51 |
+ |
{ |
52 |
+ |
my $self=shift; |
53 |
+ |
my ($start,$end)=@_; |
54 |
+ |
# $start is a VERTEX. Add package $end to the hash of deps in |
55 |
+ |
# the DEPENDENCIES hash: |
56 |
+ |
$self->{DEPENDENCIES}->{$start}->{$end} = 1; |
57 |
+ |
} |
58 |
+ |
|
59 |
+ |
sub _graph_init() |
60 |
+ |
{ |
61 |
+ |
my $self=shift; |
62 |
+ |
# If a graph object already exists (e.g. when SCRAMGrapher has |
63 |
+ |
# been cloned), add new vertices/edges. Otherwise, start with |
64 |
+ |
# a new Graph object: |
65 |
+ |
if (exists ($self->{GRAPH})) |
66 |
+ |
{ |
67 |
+ |
my $vertices = [ keys %{$self->{DEPENDENCIES}} ]; |
68 |
+ |
|
69 |
+ |
# Loop over vertices: |
70 |
+ |
foreach my $package (@$vertices) |
71 |
+ |
{ |
72 |
+ |
# Add this vertex: |
73 |
+ |
$self->{GRAPH}->add_vertex($package); |
74 |
+ |
# For each edge from this vertex, add an edge: |
75 |
+ |
foreach my $dep (keys %{$self->{DEPENDENCIES}->{$package}}) |
76 |
+ |
{ |
77 |
+ |
$self->{GRAPH}->add_edge($package,$dep); |
78 |
+ |
} |
79 |
+ |
} |
80 |
+ |
} |
81 |
+ |
else |
82 |
+ |
{ |
83 |
+ |
# Init the graph with the array of vertices: |
84 |
+ |
my $vertices = [ keys %{$self->{DEPENDENCIES}} ]; |
85 |
+ |
use Graph::Graph; |
86 |
+ |
# Init a Graph object passing the list of vertices (this saves |
87 |
+ |
# N_vertex calls to add_vertex()): |
88 |
+ |
my $g = Graph->new(@$vertices); |
89 |
+ |
|
90 |
+ |
# Loop over vertices: |
91 |
+ |
foreach my $package (@$vertices) |
92 |
+ |
{ |
93 |
+ |
# For each edge from this vertex, add an edge: |
94 |
+ |
foreach my $dep (keys %{$self->{DEPENDENCIES}->{$package}}) |
95 |
+ |
{ |
96 |
+ |
$g->add_edge($package,$dep); |
97 |
+ |
} |
98 |
+ |
} |
99 |
+ |
# Store the Graph object: |
100 |
+ |
$self->{GRAPH} = $g; |
101 |
+ |
} |
102 |
+ |
} |
103 |
+ |
|
104 |
+ |
sub sort() |
105 |
+ |
{ |
106 |
+ |
my $self=shift; |
107 |
+ |
# Get a graph object: |
108 |
+ |
$self->_graph_init(); |
109 |
+ |
# Perform topological (depth-first) sort and return: |
110 |
+ |
$self->{SORTED} = [ $self->{GRAPH}->toposort() ]; |
111 |
+ |
return $self->{SORTED}; |
112 |
+ |
} |
113 |
+ |
|
114 |
+ |
sub graph_write() |
115 |
+ |
{ |
116 |
+ |
my $self=shift; |
117 |
+ |
my ($data,$name)=@_; |
118 |
+ |
my $dir = $ENV{LOCALTOP}.'/'.$ENV{SCRAM_INTwork}; |
119 |
+ |
|
120 |
+ |
use Graph::Writer::SCRAMDot; |
121 |
+ |
my $writer = Graph::Writer::SCRAMDot->new(); |
122 |
+ |
|
123 |
+ |
$name =~ s|/|_|g; |
124 |
+ |
# Filename (without the .dot): |
125 |
+ |
$filename = $dir.'/'.$name; |
126 |
+ |
# Set attributes where there's data available from |
127 |
+ |
# a DataCollector (in local graphing only) |
128 |
+ |
# In globale graphing we set a default colour, shape etc. |
129 |
+ |
# in the SCRAMDot::write_graph() routine: |
130 |
+ |
$writer->attribute_data($data); |
131 |
+ |
$writer->write_graph($self->{DEPENDENCIES}, $filename); |
132 |
+ |
|
133 |
+ |
return $self; |
134 |
+ |
} |
135 |
+ |
|
136 |
+ |
sub copy() |
137 |
+ |
{ |
138 |
+ |
my $self=shift; |
139 |
+ |
# First, we need to translate the DEPENDENCIES into a Graph object which |
140 |
+ |
# will be stored in $self->{GRAPH}: |
141 |
+ |
$self->_graph_init(); |
142 |
+ |
# Need to return new SCRAMGrapher object with copy of G: |
143 |
+ |
my $sgcopy = ref($self)->new(); |
144 |
+ |
# Make a copy of the graph and set G to point to this: |
145 |
+ |
$sgcopy->{GRAPH} = $self->{GRAPH}->copy(); |
146 |
+ |
# Reset the DEPENDENCIES store (we already have the copied vertices/edges stored): |
147 |
+ |
$sgcopy->{DEPENDENCIES} = {}; |
148 |
+ |
# Return the new SCRAMGrapher object: |
149 |
+ |
return $sgcopy; |
150 |
+ |
} |
151 |
+ |
|
152 |
+ |
1; |