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.22 by root, Tue Aug 4 18:33:30 2009 UTC vs.
Revision 1.31 by root, Wed Aug 5 19:55:58 2009 UTC

30This module (-family) implements a simple message passing framework. 30This module (-family) implements a simple message passing framework.
31 31
32Despite its simplicity, you can securely message other processes running 32Despite its simplicity, you can securely message other processes running
33on the same or other hosts. 33on the same or other hosts.
34 34
35For an introduction to this module family, see the L<AnyEvent::MP::Intro>
36manual page.
37
35At the moment, this module family is severly brokena nd underdocumented, 38At the moment, this module family is severly broken and underdocumented,
36so do not use. This was uploaded mainly to reserve the CPAN namespace - 39so do not use. This was uploaded mainly to reserve the CPAN namespace -
37stay tuned! 40stay tuned! The basic API should be finished, however.
38 41
39=head1 CONCEPTS 42=head1 CONCEPTS
40 43
41=over 4 44=over 4
42 45
43=item port 46=item port
44 47
45A port is something you can send messages to with the C<snd> function, and 48A port is something you can send messages to (with the C<snd> function).
46you can register C<rcv> handlers with. All C<rcv> handlers will receive 49
47messages they match, messages will not be queued. 50Some ports allow you to register C<rcv> handlers that can match specific
51messages. All C<rcv> handlers will receive messages they match, messages
52will not be queued.
48 53
49=item port id - C<noderef#portname> 54=item port id - C<noderef#portname>
50 55
51A port id is always the noderef, a hash-mark (C<#>) as separator, followed 56A port id is normaly the concatenation of a noderef, a hash-mark (C<#>) as
52by a port name (a printable string of unspecified format). 57separator, and a port name (a printable string of unspecified format). An
58exception is the the node port, whose ID is identical to its node
59reference.
53 60
54=item node 61=item node
55 62
56A node is a single process containing at least one port - the node 63A node is a single process containing at least one port - the node
57port. You can send messages to node ports to let them create new ports, 64port. You can send messages to node ports to find existing ports or to
58among other things. 65create new ports, among other things.
59 66
60Initially, nodes are either private (single-process only) or hidden 67Nodes are either private (single-process only), slaves (connected to a
61(connected to a master node only). Only when they epxlicitly "become 68master node only) or public nodes (connectable from unrelated nodes).
62public" can you send them messages from unrelated other nodes.
63 69
64=item noderef - C<host:port,host:port...>, C<id@noderef>, C<id> 70=item noderef - C<host:port,host:port...>, C<id@noderef>, C<id>
65 71
66A noderef is a string that either uniquely identifies a given node (for 72A node reference is a string that either simply identifies the node (for
67private and hidden nodes), or contains a recipe on how to reach a given 73private and slave nodes), or contains a recipe on how to reach a given
68node (for public nodes). 74node (for public nodes).
69 75
76This recipe is simply a comma-separated list of C<address:port> pairs (for
77TCP/IP, other protocols might look different).
78
79Node references come in two flavours: resolved (containing only numerical
80addresses) or unresolved (where hostnames are used instead of addresses).
81
82Before using an unresolved node reference in a message you first have to
83resolve it.
84
70=back 85=back
71 86
72=head1 VARIABLES/FUNCTIONS 87=head1 VARIABLES/FUNCTIONS
73 88
74=over 4 89=over 4
85 100
86use AE (); 101use AE ();
87 102
88use base "Exporter"; 103use base "Exporter";
89 104
90our $VERSION = '0.02'; 105our $VERSION = '0.1';
91our @EXPORT = qw( 106our @EXPORT = qw(
92 NODE $NODE *SELF node_of _any_ 107 NODE $NODE *SELF node_of _any_
93 become_slave become_public 108 resolve_node initialise_node
94 snd rcv mon kil reg psub 109 snd rcv mon kil reg psub
95 port 110 port
96); 111);
97 112
98our $SELF; 113our $SELF;
112 127
113=item $noderef = node_of $portid 128=item $noderef = node_of $portid
114 129
115Extracts and returns the noderef from a portid or a noderef. 130Extracts and returns the noderef from a portid or a noderef.
116 131
132=item $cv = resolve_node $noderef
133
134Takes an unresolved node reference that may contain hostnames and
135abbreviated IDs, resolves all of them and returns a resolved node
136reference.
137
138In addition to C<address:port> pairs allowed in resolved noderefs, the
139following forms are supported:
140
141=over 4
142
143=item the empty string
144
145An empty-string component gets resolved as if the default port (4040) was
146specified.
147
148=item naked port numbers (e.g. C<1234>)
149
150These are resolved by prepending the local nodename and a colon, to be
151further resolved.
152
153=item hostnames (e.g. C<localhost:1234>, C<localhost>)
154
155These are resolved by using AnyEvent::DNS to resolve them, optionally
156looking up SRV records for the C<aemp=4040> port, if no port was
157specified.
158
159=back
160
117=item $SELF 161=item $SELF
118 162
119Contains the current port id while executing C<rcv> callbacks or C<psub> 163Contains the current port id while executing C<rcv> callbacks or C<psub>
120blocks. 164blocks.
121 165
195 mon $port, $self => "restart"; 239 mon $port, $self => "restart";
196 240
197=cut 241=cut
198 242
199sub mon { 243sub mon {
200 my ($noderef, $port, $cb) = ((split /#/, shift, 2), shift); 244 my ($noderef, $port) = split /#/, shift, 2;
201 245
202 my $node = $NODE{$noderef} || add_node $noderef; 246 my $node = $NODE{$noderef} || add_node $noderef;
203 247
204 #TODO: ports must not be references 248 my $cb = shift;
205 if (!ref $cb or "AnyEvent::MP::Port" eq ref $cb) { 249
250 unless (ref $cb) {
206 if (@_) { 251 if (@_) {
207 # send a kill info message 252 # send a kill info message
208 my (@msg) = ($cb, @_); 253 my (@msg) = ($cb, @_);
209 $cb = sub { snd @msg, @_ }; 254 $cb = sub { snd @msg, @_ };
210 } else { 255 } else {
242 my ($port, @refs) = @_; 287 my ($port, @refs) = @_;
243 288
244 mon $port, sub { 0 && @refs } 289 mon $port, sub { 0 && @refs }
245} 290}
246 291
292=item lnk $port1, $port2
293
294Link two ports. This is simply a shorthand for:
295
296 mon $port1, $port2;
297 mon $port2, $port1;
298
299It means that if either one is killed abnormally, the other one gets
300killed as well.
301
247=item $local_port = port 302=item $local_port = port
248 303
249Create a new local port object that supports message matching. 304Create a new local port object that can be used either as a pattern
305matching port ("full port") or a single-callback port ("miniport"),
306depending on how C<rcv> callbacks are bound to the object.
250 307
251=item $portid = port { my @msg = @_; $finished } 308=item $portid = port { my @msg = @_; $finished }
252 309
253Creates a "mini port", that is, a very lightweight port without any 310Creates a "mini port", that is, a very lightweight port without any
254pattern matching behind it, and returns its ID. 311pattern matching behind it, and returns its ID.
260The message will be passed as-is, no extra argument (i.e. no port id) will 317The message will be passed as-is, no extra argument (i.e. no port id) will
261be passed to the callback. 318be passed to the callback.
262 319
263If you need the local port id in the callback, this works nicely: 320If you need the local port id in the callback, this works nicely:
264 321
265 my $port; $port = miniport { 322 my $port; $port = port {
266 snd $otherport, reply => $port; 323 snd $otherport, reply => $port;
267 }; 324 };
268 325
269=cut 326=cut
270 327
331 my ($portid, $name) = @_; 388 my ($portid, $name) = @_;
332 389
333 $REG{$name} = $portid; 390 $REG{$name} = $portid;
334} 391}
335 392
393=item rcv $portid, $callback->(@msg)
394
395Replaces the callback on the specified miniport (or newly created port
396object, see C<port>). Full ports are configured with the following calls:
397
336=item rcv $portid, tagstring => $callback->(@msg), ... 398=item rcv $portid, tagstring => $callback->(@msg), ...
337 399
338=item rcv $portid, $smartmatch => $callback->(@msg), ... 400=item rcv $portid, $smartmatch => $callback->(@msg), ...
339 401
340=item rcv $portid, [$smartmatch...] => $callback->(@msg), ... 402=item rcv $portid, [$smartmatch...] => $callback->(@msg), ...
363also the most efficient match (by far). 425also the most efficient match (by far).
364 426
365=cut 427=cut
366 428
367sub rcv($@) { 429sub rcv($@) {
430 my $portid = shift;
368 my ($noderef, $port) = split /#/, shift, 2; 431 my ($noderef, $port) = split /#/, $port, 2;
369 432
370 ($NODE{$noderef} || add_node $noderef) == $NODE{""} 433 ($NODE{$noderef} || add_node $noderef) == $NODE{""}
371 or Carp::croak "$noderef#$port: rcv can only be called on local ports, caught"; 434 or Carp::croak "$noderef#$port: rcv can only be called on local ports, caught";
372 435
373 my $self = $PORT_DATA{$port} 436 my $self = $PORT_DATA{$port}
388 : push @{ $self->{rc0}{$match->[0]} }, [$cb]; 451 : push @{ $self->{rc0}{$match->[0]} }, [$cb];
389 } else { 452 } else {
390 push @{ $self->{any} }, [$cb, $match]; 453 push @{ $self->{any} }, [$cb, $match];
391 } 454 }
392 } 455 }
456
457 $portid
393} 458}
394 459
395=item $closure = psub { BLOCK } 460=item $closure = psub { BLOCK }
396 461
397Remembers C<$SELF> and creates a closure out of the BLOCK. When the 462Remembers C<$SELF> and creates a closure out of the BLOCK. When the
434 499
435=head1 FUNCTIONS FOR NODES 500=head1 FUNCTIONS FOR NODES
436 501
437=over 4 502=over 4
438 503
439=item become_public endpoint... 504=item become_public $noderef
440 505
441Tells the node to become a public node, i.e. reachable from other nodes. 506Tells the node to become a public node, i.e. reachable from other nodes.
442 507
443If no arguments are given, or the first argument is C<undef>, then 508The first argument is the (unresolved) node reference of the local node
444AnyEvent::MP tries to bind on port C<4040> on all IP addresses that the 509(if missing then the empty string is used).
445local nodename resolves to.
446 510
447Otherwise the first argument must be an array-reference with transport 511It is quite common to not specify anything, in which case the local node
448endpoints ("ip:port", "hostname:port") or port numbers (in which case the 512tries to listen on the default port, or to only specify a port number, in
449local nodename is used as hostname). The endpoints are all resolved and 513which case AnyEvent::MP tries to guess the local addresses.
450will become the node reference.
451 514
452=cut 515=cut
453 516
454=back 517=back
455 518
458Nodes understand the following messages sent to them. Many of them take 521Nodes understand the following messages sent to them. Many of them take
459arguments called C<@reply>, which will simply be used to compose a reply 522arguments called C<@reply>, which will simply be used to compose a reply
460message - C<$reply[0]> is the port to reply to, C<$reply[1]> the type and 523message - C<$reply[0]> is the port to reply to, C<$reply[1]> the type and
461the remaining arguments are simply the message data. 524the remaining arguments are simply the message data.
462 525
526While other messages exist, they are not public and subject to change.
527
463=over 4 528=over 4
464 529
465=cut 530=cut
466 531
467=item lookup => $name, @reply 532=item lookup => $name, @reply
495 snd $NODE, time => $myport, timereply => 1, 2; 560 snd $NODE, time => $myport, timereply => 1, 2;
496 # => snd $myport, timereply => 1, 2, <time> 561 # => snd $myport, timereply => 1, 2, <time>
497 562
498=back 563=back
499 564
565=head1 AnyEvent::MP vs. Distributed Erlang
566
567AnyEvent::MP got lots of its ideas from distributed erlang (erlang node
568== aemp node, erlang process == aemp port), so many of the documents and
569programming techniques employed by erlang apply to AnyEvent::MP. Here is a
570sample:
571
572 http://www.erlang.se/doc/programming_rules.shtml
573 http://erlang.org/doc/getting_started/part_frame.html # chapters 3 and 4
574 http://erlang.org/download/erlang-book-part1.pdf # chapters 5 and 6
575 http://erlang.org/download/armstrong_thesis_2003.pdf # chapters 4 and 5
576
577Despite the similarities, there are also some important differences:
578
579=over 4
580
581=item * Node references contain the recipe on how to contact them.
582
583Erlang relies on special naming and DNS to work everywhere in the
584same way. AEMP relies on each node knowing it's own address(es), with
585convenience functionality.
586
587This means that AEMP requires a less tightly controlled environment at the
588cost of longer node references and a slightly higher management overhead.
589
590=item * Erlang uses processes and a mailbox, AEMP does not queue.
591
592Erlang uses processes that selctively receive messages, and therefore
593needs a queue. AEMP is event based, queuing messages would serve no useful
594purpose.
595
596(But see L<Coro::MP> for a more erlang-like process model on top of AEMP).
597
598=item * Erlang sends are synchronous, AEMP sends are asynchronous.
599
600Sending messages in erlang is synchronous and blocks the process. AEMP
601sends are immediate, connection establishment is handled in the
602background.
603
604=item * Erlang can silently lose messages, AEMP cannot.
605
606Erlang makes few guarantees on messages delivery - messages can get lost
607without any of the processes realising it (i.e. you send messages a, b,
608and c, and the other side only receives messages a and c).
609
610AEMP guarantees correct ordering, and the guarantee that there are no
611holes in the message sequence.
612
613=item * In erlang, processes can be declared dead and later be found to be
614alive.
615
616In erlang it can happen that a monitored process is declared dead and
617linked processes get killed, but later it turns out that the process is
618still alive - and can receive messages.
619
620In AEMP, when port monitoring detects a port as dead, then that port will
621eventually be killed - it cannot happen that a node detects a port as dead
622and then later sends messages to it, finding it is still alive.
623
624=item * Erlang can send messages to the wrong port, AEMP does not.
625
626In erlang it is quite possible that a node that restarts reuses a process
627ID known to other nodes for a completely different process, causing
628messages destined for that process to end up in an unrelated process.
629
630AEMP never reuses port IDs, so old messages or old port IDs floating
631around in the network will not be sent to an unrelated port.
632
633=item * Erlang uses unprotected connections, AEMP uses secure
634authentication and can use TLS.
635
636AEMP can use a proven protocol - SSL/TLS - to protect connections and
637securely authenticate nodes.
638
639=item * The AEMP protocol is optimised for both text-based and binary
640communications.
641
642The AEMP protocol, unlike the erlang protocol, supports both
643language-independent text-only protocols (good for debugging) and binary,
644language-specific serialisers (e.g. Storable).
645
646It has also been carefully designed to be implementable in other languages
647with a minimum of work while gracefully degrading fucntionality to make the
648protocol simple.
649
650=back
651
500=head1 SEE ALSO 652=head1 SEE ALSO
501 653
502L<AnyEvent>. 654L<AnyEvent>.
503 655
504=head1 AUTHOR 656=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines