ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/MP.pm
(Generate patch)

Comparing AnyEvent-MP/MP.pm (file contents):
Revision 1.38 by root, Fri Aug 7 22:55:18 2009 UTC vs.
Revision 1.49 by root, Thu Aug 13 15:29:58 2009 UTC

9 $NODE # contains this node's noderef 9 $NODE # contains this node's noderef
10 NODE # returns this node's noderef 10 NODE # returns this node's noderef
11 NODE $port # returns the noderef of the port 11 NODE $port # returns the noderef of the port
12 12
13 $SELF # receiving/own port id in rcv callbacks 13 $SELF # receiving/own port id in rcv callbacks
14
15 # initialise the node so it can send/receive messages
16 initialise_node; # -OR-
17 initialise_node "localhost:4040"; # -OR-
18 initialise_node "slave/", "localhost:4040"
14 19
15 # ports are message endpoints 20 # ports are message endpoints
16 21
17 # sending messages 22 # sending messages
18 snd $port, type => data...; 23 snd $port, type => data...;
19 snd $port, @msg; 24 snd $port, @msg;
20 snd @msg_with_first_element_being_a_port; 25 snd @msg_with_first_element_being_a_port;
21 26
22 # miniports 27 # creating/using miniports
23 my $miniport = port { my @msg = @_; 0 }; 28 my $miniport = port { my @msg = @_; 0 };
24 29
25 # full ports 30 # creating/using full ports
26 my $port = port; 31 my $port = port;
27 rcv $port, smartmatch => $cb->(@msg); 32 rcv $port, smartmatch => $cb->(@msg);
28 rcv $port, ping => sub { snd $_[0], "pong"; 0 }; 33 rcv $port, ping => sub { snd $_[0], "pong"; 0 };
29 rcv $port, pong => sub { warn "pong received\n"; 0 }; 34 rcv $port, pong => sub { warn "pong received\n"; 0 };
30 35
31 # remote ports
32 my $port = spawn $node, $initfunc, @initdata;
33
34 # more, smarter, matches (_any_ is exported by this module) 36 # more, smarter, matches (_any_ is exported by this module)
35 rcv $port, [child_died => $pid] => sub { ... 37 rcv $port, [child_died => $pid] => sub { ...
36 rcv $port, [_any_, _any_, 3] => sub { .. $_[2] is 3 38 rcv $port, [_any_, _any_, 3] => sub { .. $_[2] is 3
39
40 # create a port on another node
41 my $port = spawn $node, $initfunc, @initdata;
37 42
38 # monitoring 43 # monitoring
39 mon $port, $cb->(@msg) # callback is invoked on death 44 mon $port, $cb->(@msg) # callback is invoked on death
40 mon $port, $otherport # kill otherport on abnormal death 45 mon $port, $otherport # kill otherport on abnormal death
41 mon $port, $otherport, @msg # send message on death 46 mon $port, $otherport, @msg # send message on death
42 47
48=head1 CURRENT STATUS
49
50 AnyEvent::MP - stable API, should work
51 AnyEvent::MP::Intro - outdated
52 AnyEvent::MP::Kernel - WIP
53 AnyEvent::MP::Transport - mostly stable
54
55 stay tuned.
56
43=head1 DESCRIPTION 57=head1 DESCRIPTION
44 58
45This module (-family) implements a simple message passing framework. 59This module (-family) implements a simple message passing framework.
46 60
47Despite its simplicity, you can securely message other processes running 61Despite its simplicity, you can securely message other processes running
50For an introduction to this module family, see the L<AnyEvent::MP::Intro> 64For an introduction to this module family, see the L<AnyEvent::MP::Intro>
51manual page. 65manual page.
52 66
53At the moment, this module family is severly broken and underdocumented, 67At the moment, this module family is severly broken and underdocumented,
54so do not use. This was uploaded mainly to reserve the CPAN namespace - 68so do not use. This was uploaded mainly to reserve the CPAN namespace -
55stay tuned! The basic API should be finished, however. 69stay tuned!
56 70
57=head1 CONCEPTS 71=head1 CONCEPTS
58 72
59=over 4 73=over 4
60 74
105 119
106=cut 120=cut
107 121
108package AnyEvent::MP; 122package AnyEvent::MP;
109 123
110use AnyEvent::MP::Base; 124use AnyEvent::MP::Kernel;
111 125
112use common::sense; 126use common::sense;
113 127
114use Carp (); 128use Carp ();
115 129
116use AE (); 130use AE ();
117 131
118use base "Exporter"; 132use base "Exporter";
119 133
120our $VERSION = '0.1'; 134our $VERSION = $AnyEvent::MP::Kernel::VERSION;
135
121our @EXPORT = qw( 136our @EXPORT = qw(
122 NODE $NODE *SELF node_of _any_ 137 NODE $NODE *SELF node_of _any_
123 resolve_node initialise_node 138 resolve_node initialise_node
124 snd rcv mon kil reg psub spawn 139 snd rcv mon kil reg psub spawn
125 port 140 port
153it should know the noderefs of some other nodes in the network. 168it should know the noderefs of some other nodes in the network.
154 169
155This function initialises a node - it must be called exactly once (or 170This function initialises a node - it must be called exactly once (or
156never) before calling other AnyEvent::MP functions. 171never) before calling other AnyEvent::MP functions.
157 172
158All arguments are noderefs, which can be either resolved or unresolved. 173All arguments (optionally except for the first) are noderefs, which can be
174either resolved or unresolved.
175
176The first argument will be looked up in the configuration database first
177(if it is C<undef> then the current nodename will be used instead) to find
178the relevant configuration profile (see L<aemp>). If none is found then
179the default configuration is used. The configuration supplies additional
180seed/master nodes and can override the actual noderef.
159 181
160There are two types of networked nodes, public nodes and slave nodes: 182There are two types of networked nodes, public nodes and slave nodes:
161 183
162=over 4 184=over 4
163 185
164=item public nodes 186=item public nodes
165 187
166For public nodes, C<$noderef> must either be a (possibly unresolved) 188For public nodes, C<$noderef> (supplied either directly to
167noderef, in which case it will be resolved, or C<undef> (or missing), in 189C<initialise_node> or indirectly via a profile or the nodename) must be a
168which case the noderef will be guessed. 190noderef (possibly unresolved, in which case it will be resolved).
169 191
170Afterwards, the node will bind itself on all endpoints and try to connect 192After resolving, the node will bind itself on all endpoints and try to
171to all additional C<$seednodes> that are specified. Seednodes are optional 193connect to all additional C<$seednodes> that are specified. Seednodes are
172and can be used to quickly bootstrap the node into an existing network. 194optional and can be used to quickly bootstrap the node into an existing
195network.
173 196
174=item slave nodes 197=item slave nodes
175 198
176When the C<$noderef> is the special string C<slave/>, then the node will 199When the C<$noderef> (either as given or overriden by the config file)
200is the special string C<slave/>, then the node will become a slave
177become a slave node. Slave nodes cannot be contacted from outside and will 201node. Slave nodes cannot be contacted from outside and will route most of
178route most of their traffic to the master node that they attach to. 202their traffic to the master node that they attach to.
179 203
180At least one additional noderef is required: The node will try to connect 204At least one additional noderef is required (either by specifying it
181to all of them and will become a slave attached to the first node it can 205directly or because it is part of the configuration profile): The node
182successfully connect to. 206will try to connect to all of them and will become a slave attached to the
207first node it can successfully connect to.
183 208
184=back 209=back
185 210
186This function will block until all nodes have been resolved and, for slave 211This function will block until all nodes have been resolved and, for slave
187nodes, until it has successfully established a connection to a master 212nodes, until it has successfully established a connection to a master
188server. 213server.
189 214
190Example: become a public node listening on the default node. 215Example: become a public node listening on the guessed noderef, or the one
216specified via C<aemp> for the current node. This should be the most common
217form of invocation for "daemon"-type nodes.
191 218
192 initialise_node; 219 initialise_node;
220
221Example: become a slave node to any of the the seednodes specified via
222C<aemp>. This form is often used for commandline clients.
223
224 initialise_node "slave/";
225
226Example: become a slave node to any of the specified master servers. This
227form is also often used for commandline clients.
228
229 initialise_node "slave/", "master1", "192.168.13.17", "mp.example.net";
193 230
194Example: become a public node, and try to contact some well-known master 231Example: become a public node, and try to contact some well-known master
195servers to become part of the network. 232servers to become part of the network.
196 233
197 initialise_node undef, "master1", "master2"; 234 initialise_node undef, "master1", "master2";
200 237
201 initialise_node 4041; 238 initialise_node 4041;
202 239
203Example: become a public node, only visible on localhost port 4044. 240Example: become a public node, only visible on localhost port 4044.
204 241
205 initialise_node "locahost:4044"; 242 initialise_node "localhost:4044";
206
207Example: become a slave node to any of the specified master servers.
208
209 initialise_node "slave/", "master1", "192.168.13.17", "mp.example.net";
210 243
211=item $cv = resolve_node $noderef 244=item $cv = resolve_node $noderef
212 245
213Takes an unresolved node reference that may contain hostnames and 246Takes an unresolved node reference that may contain hostnames and
214abbreviated IDs, resolves all of them and returns a resolved node 247abbreviated IDs, resolves all of them and returns a resolved node
501 534
502=item $guard = mon $port 535=item $guard = mon $port
503 536
504=item $guard = mon $port, $rcvport, @msg 537=item $guard = mon $port, $rcvport, @msg
505 538
506Monitor the given port and do something when the port is killed, and 539Monitor the given port and do something when the port is killed or
507optionally return a guard that can be used to stop monitoring again. 540messages to it were lost, and optionally return a guard that can be used
541to stop monitoring again.
542
543C<mon> effectively guarantees that, in the absence of hardware failures,
544that after starting the monitor, either all messages sent to the port
545will arrive, or the monitoring action will be invoked after possible
546message loss has been detected. No messages will be lost "in between"
547(after the first lost message no further messages will be received by the
548port). After the monitoring action was invoked, further messages might get
549delivered again.
508 550
509In the first form (callback), the callback is simply called with any 551In the first form (callback), the callback is simply called with any
510number of C<@reason> elements (no @reason means that the port was deleted 552number of C<@reason> elements (no @reason means that the port was deleted
511"normally"). Note also that I<< the callback B<must> never die >>, so use 553"normally"). Note also that I<< the callback B<must> never die >>, so use
512C<eval> if unsure. 554C<eval> if unsure.
513 555
514In the second form (another port given), the other port (C<$rcvport) 556In the second form (another port given), the other port (C<$rcvport>)
515will be C<kil>'ed with C<@reason>, iff a @reason was specified, i.e. on 557will be C<kil>'ed with C<@reason>, iff a @reason was specified, i.e. on
516"normal" kils nothing happens, while under all other conditions, the other 558"normal" kils nothing happens, while under all other conditions, the other
517port is killed with the same reason. 559port is killed with the same reason.
518 560
519The third form (kill self) is the same as the second form, except that 561The third form (kill self) is the same as the second form, except that
546sub mon { 588sub mon {
547 my ($noderef, $port) = split /#/, shift, 2; 589 my ($noderef, $port) = split /#/, shift, 2;
548 590
549 my $node = $NODE{$noderef} || add_node $noderef; 591 my $node = $NODE{$noderef} || add_node $noderef;
550 592
551 my $cb = @_ ? $_[0] : $SELF || Carp::croak 'mon: called with one argument only, but $SELF not set,'; 593 my $cb = @_ ? shift : $SELF || Carp::croak 'mon: called with one argument only, but $SELF not set,';
552 594
553 unless (ref $cb) { 595 unless (ref $cb) {
554 if (@_) { 596 if (@_) {
555 # send a kill info message 597 # send a kill info message
556 my (@msg) = @_; 598 my (@msg) = ($cb, @_);
557 $cb = sub { snd @msg, @_ }; 599 $cb = sub { snd @msg, @_ };
558 } else { 600 } else {
559 # simply kill other port 601 # simply kill other port
560 my $port = $cb; 602 my $port = $cb;
561 $cb = sub { kil $port, @_ if @_ }; 603 $cb = sub { kil $port, @_ if @_ };
619 661
620The port ID of the newly created port is return immediately, and it is 662The port ID of the newly created port is return immediately, and it is
621permissible to immediately start sending messages or monitor the port. 663permissible to immediately start sending messages or monitor the port.
622 664
623After the port has been created, the init function is 665After the port has been created, the init function is
624called. This fucntion must be a fully-qualified function name 666called. This function must be a fully-qualified function name
625(e.g. C<MyApp::Chat::Server::init>). 667(e.g. C<MyApp::Chat::Server::init>). To specify a function in the main
668program, use C<::name>.
626 669
627If the function doesn't exist, then the node tries to C<require> 670If the function doesn't exist, then the node tries to C<require>
628the package, then the package above the package and so on (e.g. 671the package, then the package above the package and so on (e.g.
629C<MyApp::Chat::Server>, C<MyApp::Chat>, C<MyApp>) until the function 672C<MyApp::Chat::Server>, C<MyApp::Chat>, C<MyApp>) until the function
630exists or it runs out of package names. 673exists or it runs out of package names.
669sub spawn(@) { 712sub spawn(@) {
670 my ($noderef, undef) = split /#/, shift, 2; 713 my ($noderef, undef) = split /#/, shift, 2;
671 714
672 my $id = "$RUNIQ." . $ID++; 715 my $id = "$RUNIQ." . $ID++;
673 716
717 $_[0] =~ /::/
718 or Carp::croak "spawn init function must be a fully-qualified name, caught";
719
674 ($NODE{$noderef} || add_node $noderef) 720 ($NODE{$noderef} || add_node $noderef)
675 ->send (["", "AnyEvent::MP::_spawn" => $id, @_]); 721 ->send (["", "AnyEvent::MP::_spawn" => $id, @_]);
676 722
677 "$noderef#$id" 723 "$noderef#$id"
678} 724}
832This also saves round-trips and avoids sending messages to the wrong port 878This also saves round-trips and avoids sending messages to the wrong port
833(hard to do in Erlang). 879(hard to do in Erlang).
834 880
835=back 881=back
836 882
883=head1 RATIONALE
884
885=over 4
886
887=item Why strings for ports and noderefs, why not objects?
888
889We considered "objects", but found that the actual number of methods
890thatc an be called are very low. Since port IDs and noderefs travel over
891the network frequently, the serialising/deserialising would add lots of
892overhead, as well as having to keep a proxy object.
893
894Strings can easily be printed, easily serialised etc. and need no special
895procedures to be "valid".
896
897And a a miniport consists of a single closure stored in a global hash - it
898can't become much cheaper.
899
900=item Why favour JSON, why not real serialising format such as Storable?
901
902In fact, any AnyEvent::MP node will happily accept Storable as framing
903format, but currently there is no way to make a node use Storable by
904default.
905
906The default framing protocol is JSON because a) JSON::XS is many times
907faster for small messages and b) most importantly, after years of
908experience we found that object serialisation is causing more problems
909than it gains: Just like function calls, objects simply do not travel
910easily over the network, mostly because they will always be a copy, so you
911always have to re-think your design.
912
913Keeping your messages simple, concentrating on data structures rather than
914objects, will keep your messages clean, tidy and efficient.
915
916=back
917
837=head1 SEE ALSO 918=head1 SEE ALSO
838 919
839L<AnyEvent>. 920L<AnyEvent>.
840 921
841=head1 AUTHOR 922=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines