my ($semaphore, $dependent_node_name) = @_;
my $semaphore_id = $semaphore->dbID;
my $semaphore_pipeline_name = $semaphore->hive_pipeline->hive_pipeline_name;
my $semaphore_node_name = 'semaphore_'.$semaphore_id.'__'.$semaphore_pipeline_name;
my $semaphore_blockers = $semaphore->local_jobs_counter + $semaphore->remote_jobs_counter;
my $semaphore_is_blocked = $semaphore_blockers > 0;
my $meta_shape = $self->{'show_accu_keys'}
? ['house', 'invhouse' ] # house shape hints that accu data will be shown if present
: ['triangle', 'invtriangle']; # triangle shape hints that no accu data will be shown even if present
my $columns_in_table = $self->{'show_accu_values'} ? 3 : 2;
my ($semaphore_shape, $semaphore_bgcolour, $semaphore_fgcolour, $dependent_blocking_arrow_colour, $dependent_blocking_arrow_shape ) = $semaphore_is_blocked
? ($meta_shape->[0], 'grey', 'brown', 'red', 'tee')
: ($meta_shape->[1], 'darkgreen', 'white', 'darkgreen', 'none');
my @semaphore_label_parts = ();
if($semaphore_is_blocked) {
if(my $local=$semaphore->local_jobs_counter) { push @semaphore_label_parts, "local: $local" }
if(my $remote=$semaphore->remote_jobs_counter) { push @semaphore_label_parts, "remote: $remote" }
} else {
push @semaphore_label_parts, "open";
}
my $semaphore_label = join(', ', @semaphore_label_parts);
my $accusem_label = qq{<<table border="0" cellborder="0" cellspacing="0" cellpadding="1">};
$accusem_label .= qq{<tr><td colspan="$columns_in_table"><font color="$semaphore_fgcolour"><b><i>$semaphore_label</i></b></font></td></tr>};
my %accu_ptrs = ();
if($self->{'show_accu_keys'}) {
my $raw_accu_data = $semaphore->fetch_my_raw_accu_data;
if(@$raw_accu_data) {
$accusem_label .= qq{<tr><td colspan="$columns_in_table"> </td></tr>}; # skip one table row between semaphore attributes and accu data
my %struct_name_2_key_signature_and_value = ();
foreach my $accu_rowhash (@$raw_accu_data) {
push @{ $struct_name_2_key_signature_and_value{ $accu_rowhash->{'struct_name'} } },
[ $accu_rowhash->{'key_signature'}, $accu_rowhash->{'value'}, $accu_rowhash->{'sending_job_id'} ];
}
my $sending_job_pipeline_name = $semaphore->hive_pipeline->hive_pipeline_name; # assuming cross-database links are currently not stored
foreach my $struct_name (sort keys %struct_name_2_key_signature_and_value) {
$accusem_label .= $self->{'show_accu_values'}
? qq{<tr><td></td><td><b><u>$struct_name</u></b></td><td></td></tr>}
: qq{<tr> <td><b><u>$struct_name</u></b></td><td></td></tr>};
my @sorted_values = sort {(($a->[2]
foreach my $accu_vector ( @sorted_values ) {
my ($key_signature, $value, $sending_job_id) = @$accu_vector;
$sending_job_id
my $protected_value = $self->{'graph'}->protect_string_for_display($value);
my $port_label = "${semaphore_node_name}_${struct_name}_${sending_job_id}";
my $port_attribute = $sending_job_id ? qq{port="$port_label"} : '';
if(my $sending_job_node_name = 'job_'.$sending_job_id.'__'.$sending_job_pipeline_name) {
push @{ $accu_ptrs{$sending_job_node_name} }, $port_label;
}
$accusem_label .= $self->{'show_accu_values'}
? qq{<tr><td $port_attribute>$key_signature</td><td> <b>--></b> </td><td>$protected_value</td></tr>}
: qq{<tr><td $port_attribute></td><td>$key_signature</td></tr>};
}
}
}
}
$accusem_label .= "</table>>";
$self->{'graph'}->add_node( $semaphore_node_name,
shape => $semaphore_shape, # 'note',
margin => '0,0',
style => 'filled',
fillcolor => $semaphore_bgcolour,
label => $accusem_label,
);
if($dependent_node_name) {
$self->{'graph'}->add_edge( $semaphore_node_name => $dependent_node_name,
color => $dependent_blocking_arrow_colour,
style => 'dashed',
arrowhead => $dependent_blocking_arrow_shape,
tailport => 's',
headport => 'n',
);
}
if($self->{'show_accu_pointers'}) {
foreach my $sending_job_node_name (keys %accu_ptrs) {
foreach my $receiving_port (@{ $accu_ptrs{$sending_job_node_name} }) {
$self->{'graph'}->add_edge( $sending_job_node_name => $semaphore_node_name,
headport => $receiving_port.':w',
color => 'black',
style => 'dotted',
);
}
}
}
return $semaphore_node_name;
}