--- AnyEvent-MP/MP.pm 2012/03/04 14:28:44 1.128 +++ AnyEvent-MP/MP.pm 2012/03/21 15:22:16 1.136 @@ -37,9 +37,9 @@ kil $port, my_error => "everything is broken"; # error kill # monitoring - mon $localport, $cb->(@msg) # callback is invoked on death - mon $localport, $otherport # kill otherport on abnormal death - mon $localport, $otherport, @msg # send message on death + mon $port, $cb->(@msg) # callback is invoked on death + mon $port, $localport # kill localport on abnormal death + mon $port, $localport, @msg # send message on death # temporarily execute code in port context peval $port, sub { die "kill the port!" }; @@ -249,12 +249,17 @@ precedence over any values configured via the rc file. The default is for the rc file to override any options specified in the program. -=item secure => $pass->($nodeid) +=item secure => $pass->(@msg) In addition to specifying a boolean, you can specify a code reference that -is called for every remote execution attempt - the execution request is +is called for every code execution attempt - the execution request is granted iff the callback returns a true value. +Most of the time the callback should look only at +C<$AnyEvent::MP::Kernel::SRCNODE> to make a decision, and not at the +actual message (which can be about anything, and is mostly provided for +diagnostic purposes). + See F for more info. =back @@ -400,15 +405,16 @@ sub rcv($@); -sub _kilme { - die "received message on port without callback"; -} +my $KILME = sub { + (my $tag = substr $_[0], 0, 30) =~ s/([\x20-\x7e])/./g; + kil $SELF, unhandled_message => "no callback found for message '$tag'"; +}; sub port(;&) { my $id = $UNIQ . ++$ID; my $port = "$NODE#$id"; - rcv $port, shift || \&_kilme; + rcv $port, shift || $KILME; $port } @@ -423,7 +429,7 @@ executing the callback. Runtime errors during callback execution will result in the port being Ced. -The default callback received all messages not matched by a more specific +The default callback receives all messages not matched by a more specific C match. =item rcv $local_port, tag => $callback->(@msg_without_tag), ... @@ -734,7 +740,17 @@ Transport/communication errors are reported as C<< transport_error => $message >>. -=cut +Common idioms: + + # silently remove yourself, do not kill linked ports + kil $SELF; + + # report a failure in some detail + kil $SELF, failure_mode_1 => "it failed with too high temperature"; + + # do not waste much time with killing, just die when something goes wrong + open my $fh, " with the @@ -894,11 +912,16 @@ =head1 DISTRIBUTED DATABASE AnyEvent::MP comes with a simple distributed database. The database will -be mirrored asynchronously at all global nodes. Other nodes bind to one of -the global nodes for their needs. +be mirrored asynchronously on all global nodes. Other nodes bind to one +of the global nodes for their needs. Every node has a "local database" +which contains all the values that are set locally. All local databases +are merged together to form the global database, which can be queried. + +The database structure is that of a two-level hash - the database hash +contains hashes which contain values, similarly to a perl hash of hashes, +i.e.: -The database consists of a two-level hash - a hash contains a hash which -contains values. + $DATABASE{$family}{$subkey} = $value The top level hash key is called "family", and the second-level hash key is called "subkey" or simply "key". @@ -913,7 +936,7 @@ The subkeys must be non-empty strings, with no further restrictions. The values should preferably be strings, but other perl scalars should -work as well (such as undef, arrays and hashes). +work as well (such as C, arrays and hashes). Every database entry is owned by one node - adding the same family/subkey combination on multiple nodes will not cause discomfort for AnyEvent::MP, @@ -927,10 +950,24 @@ db_set my_image_scalers => $port; And clients looking for an image scaler will want to get the -C keys: +C keys from time to time: + + db_keys my_image_scalers => sub { + @ports = @{ $_[0] }; + }; + +Or better yet, they want to monitor the database family, so they always +have a reasonable up-to-date copy: + + db_mon my_image_scalers => sub { + @ports = keys %{ $_[0] }; + }; + +In general, you can set or delete single subkeys, but query and monitor +whole families only. - db_keys "my_image_scalers" => 60 => sub { - #d##TODO# +If you feel the need to monitor or query a single subkey, try giving it +it's own family. =over @@ -939,9 +976,9 @@ Sets (or replaces) a key to the database - if C<$value> is omitted, C is used instead. -=item db_del $family => $subkey +=item db_del $family => $subkey... -Deletes a key from the database. +Deletes one or more subkeys from the database family. =item $guard = db_reg $family => $subkey [=> $value] @@ -949,18 +986,40 @@ destroyed, the key is deleted from the database. If C<$value> is missing, then C is used. -=item $guard = db_mon $family => $cb->($familyhash, \@subkeys...) +=item db_family $family => $cb->(\%familyhash) + +Queries the named database C<$family> and call the callback with the +family represented as a hash. You can keep and freely modify the hash. + +=item db_keys $family => $cb->(\@keys) + +Same as C, except it only queries the family I and passes +them as array reference to the callback. + +=item db_values $family => $cb->(\@values) -Creates a monitor on the given database family. Each time a key is set or -or is deleted the callback is called with a hash containing the database -family and an arrayref with subkeys that have changed. - -Specifically, if one of the passed subkeys exists in the $familyhash, then -it is currently set to the value in the $familyhash. Otherwise, it has -been deleted. +Same as C, except it only queries the family I and passes them +as array reference to the callback. -The first call will be with the current contents of the family and all -keys, as if they were just added. +=item $guard = db_mon $family => $cb->($familyhash, \@added, \@changed, \@deleted) + +Creates a monitor on the given database family. Each time a key is set +or or is deleted the callback is called with a hash containing the +database family and three lists of added, changed and deleted subkeys, +respectively. If no keys have changed then the array reference might be +C or even missing. + +If not called in void context, a guard object is returned that, when +destroyed, stops the monitor. + +The family hash reference and the key arrays belong to AnyEvent::MP and +B by the callback. When in doubt, make a +copy. + +As soon as possible after the monitoring starts, the callback will be +called with the intiial contents of the family, even if it is empty, +i.e. there will always be a timely call to the callback with the current +contents. It is possible that the callback is called with a change event even though the subkey is already present and the value has not changed. @@ -970,14 +1029,14 @@ Example: on every change to the family "mygroup", print out all keys. my $guard = db_mon mygroup => sub { - my ($family, $keys) = @_; + my ($family, $a, $c, $d) = @_; print "mygroup members: ", (join " ", keys %$family), "\n"; }; Exmaple: wait until the family "My::Module::workers" is non-empty. my $guard; $guard = db_mon My::Module::workers => sub { - my ($family, $keys) = @_; + my ($family, $a, $c, $d) = @_; return unless %$family; undef $guard; print "My::Module::workers now nonempty\n"; @@ -986,15 +1045,11 @@ Example: print all changes to the family "AnyRvent::Fantasy::Module". my $guard = db_mon AnyRvent::Fantasy::Module => sub { - my ($family, $keys) = @_; + my ($family, $a, $c, $d) = @_; - for (@$keys) { - print "$_: ", - (exists $family->{$_} - ? $family->{$_} - : "(deleted)"), - "\n"; - } + print "+$_=$family->{$_}\n" for @$a; + print "*$_=$family->{$_}\n" for @$c; + print "-$_=$family->{$_}\n" for @$d; }; =cut