AnyEvent-MP
view release on metacpan or search on metacpan
MP/Global.pm view on Meta::CPAN
push @del_global, $k if exists $GLOBAL_SLAVE{$node};
}
}
# family could be empty now
delete $GLOBAL_DB {$family} unless %$gdb;
delete $LOCAL_DBS{$node}{$family} unless %$ldb;
# tell other global nodes any changes in our database
g_broadcast g_upd => $family, $set, \@del_global
if exists $GLOBAL_SLAVE{$node} && (%$set || @del_global);
# tell subscribers we have changed the family
if (%$set || %local_set || @del_local) {
@$set{keys %local_set} = values %local_set;
snd $_ => g_chg2 => $family, $set, \@del_local
for keys %{ $GLOBAL_MON{$family} };
}
}
# set the whole (node-local) database - previous value must be empty
sub g_set($$) {
my ($node, $db) = @_;
while (my ($f, $k) = each %$db) {
g_upd $node, $f, $k;
}
}
# delete all keys from a database
sub g_clr($) {
my ($node) = @_;
my $db = $LOCAL_DBS{$node};
while (my ($f, $k) = each %$db) {
g_upd $node, $f, undef, [keys %$k];
}
delete $LOCAL_DBS{$node};
}
# gather node databases from slaves
# other node wants to make us the master and sends us their db
$NODE_REQ{g_slave} = sub {
my ($db) = @_
or return; # empty g_slave is used to start global service
my $node = $SRCNODE;
undef $GLOBAL_SLAVE{$node};
g_set $node, $db;
};
# other global node sends us their database
$NODE_REQ{g_set} = sub {
my ($db) = @_;
# need to get it here, because g_set destroys it
my $binds = $db->{"'l"}{$SRCNODE};
g_set $SRCNODE, $db;
# a remote node always has to provide their listeners. for global
# nodes, we mirror their 'l locally, just as we also set 'g.
# that's not very efficient, but ensures that global nodes
# find each other.
db_set "'l" => $SRCNODE => $binds;
};
# other node (global and slave) sends us a family update
$NODE_REQ{g_upd} = sub {
&g_upd ($SRCNODE, @_);
};
# slave node wants to know the listeners of a node
$NODE_REQ{g_find} = sub {
my ($node) = @_;
snd $SRCNODE, g_found => $node, $GLOBAL_DB{"'l"}{$node};
};
$NODE_REQ{g_db_family} = sub {
my ($family, $id) = @_;
snd $SRCNODE, g_reply => $id, $GLOBAL_DB{$family} || {};
};
$NODE_REQ{g_db_keys} = sub {
my ($family, $id) = @_;
snd $SRCNODE, g_reply => $id, [keys %{ $GLOBAL_DB{$family} } ];
};
$NODE_REQ{g_db_values} = sub {
my ($family, $id) = @_;
snd $SRCNODE, g_reply => $id, [values %{ $GLOBAL_DB{$family} } ];
};
# monitoring
sub g_disconnect($) {
my ($node) = @_;
delete $GLOBAL_NODE{$node}; # also done in Kernel.pm, but doing it here avoids overhead
db_del "'g" => $node;
db_del "'l" => $node;
g_clr $node;
if (my $mon = delete $GLOBAL_SLAVE{$node}) {
while (my ($f, $fv) = each %$mon) {
delete $GLOBAL_MON{$f}{$_}
for keys %$fv;
delete $GLOBAL_MON{$f}
unless %{ $GLOBAL_MON{$f} };
}
}
}
# g_mon0 family - stop monitoring
$NODE_REQ{g_mon0} = sub {
delete $GLOBAL_MON{$_[0]}{$SRCNODE};
delete $GLOBAL_MON{$_[0]} unless %{ $GLOBAL_MON{$_[0]} };
delete $GLOBAL_SLAVE{$SRCNODE}{$_[0]};
};
# g_mon1 family key - start monitoring
( run in 0.550 second using v1.01-cache-2.11-cpan-2398b32b56e )