=head1 NAME AnyEvent::MP::Global - some network-global services =head1 SYNOPSIS use AnyEvent::MP::Global; =head1 DESCRIPTION This module maintains a fully-meshed network between global nodes and tries to have connections with all nodes in the network. It also manages named port groups - ports can register themselves in any number of groups that will be available network-wide, which is great for discovering services. Running it on one node will automatically run it on all nodes, although, at the moment, the global service is started by default anyways. =head1 GLOBALS AND FUNCTIONS =over 4 =cut package AnyEvent::MP::Global; use common::sense; use Carp (); use AnyEvent (); use AnyEvent::Util (); use AnyEvent::MP; use AnyEvent::MP::Kernel; use AnyEvent::MP::Transport (); use base "Exporter"; our @EXPORT = qw( grp_reg grp_get grp_mon ); $AnyEvent::MP::Kernel::WARN->(7, "starting global service."); ############################################################################# # node protocol parts for global nodes { package AnyEvent::MP::Kernel; # TODO: this is ugly, maybe this should go into MP::Kernel or a separate module #d# our $GLOBAL; our $NODE_ADDR; our $GLOBAL_ADDR; our $NODE; our %GLOBAL_SLAVE; our $GLOBAL_MON; our $LISTENER; # switch to global mode $GLOBAL = 1; $MASTER = $NODE; undef $GLOBAL_MON; $GLOBAL_ADDR->{$NODE} = $LISTENER; $GLOBAL_MON = mon_nodes sub { return if $_[1]; delete $NODE_ADDR->{$_[0]}; if (delete $GLOBAL_ADDR->{$_[0]}) { # if the node is global, tell our slaves our %GLOBAL_SLAVE; # ugh, will be in AnyEvent::MP::Global snd $_, g_del => $_[0] for keys %GLOBAL_SLAVE; } }; # tell everybody who connects that we are a global node push @AnyEvent::MP::Transport::HOOK_GREET, sub { $_[0]{local_greeting}{global} = 1; }; # tell every global node that connects that we are global too push @AnyEvent::MP::Transport::HOOK_CONNECT, sub { snd $_[0], g_add => $NODE, $LISTENER if $_[0]{remote_greeting}{global}; }; # tell everybody else that we are global now snd $_ => g_add => $NODE, $LISTENER for up_nodes; } =item $guard = grp_reg $group, $port Register the given (local!) port in the named global group C<$group>. The port will be unregistered automatically when the port is destroyed. When not called in void context, then a guard object will be returned that will also cause the name to be unregistered when destroyed. =cut # register local port sub grp_reg($$) { my ($group, $port) = @_; port_is_local $port or Carp::croak "AnyEvent::MP::Global::grp_reg can only be called for local ports, caught"; defined wantarray && AnyEvent::Util::guard { unregister ($port, $group) } } =item $ports = grp_get $group Returns all the ports currently registered to the given group (as read-only(!) array reference). When the group has no registered members, return C. =cut sub grp_get($) { } =item $guard = grp_mon $group, $callback->($ports, $add, $del) Installs a monitor on the given group. Each time there is a change it will be called with the current group members as an arrayref as the first argument. The second argument only contains ports added, the third argument only ports removed. Unlike C, all three arguments will always be array-refs, even if the array is empty. None of the arrays must be modified in any way. The first invocation will be with the first two arguments set to the current members, as if all of them were just added, but only when the group is actually non-empty. Optionally returns a guard object that uninstalls the watcher when it is destroyed. =cut sub grp_mon($$) { my ($grp, $cb) = @_; } =back =head1 SEE ALSO L. =head1 AUTHOR Marc Lehmann http://home.schmorp.de/ =cut 1