--- AnyEvent-MP/MP.pm 2009/08/16 02:55:16 1.58 +++ AnyEvent-MP/MP.pm 2009/08/28 00:58:44 1.64 @@ -13,9 +13,7 @@ $SELF # receiving/own port id in rcv callbacks # initialise the node so it can send/receive messages - initialise_node; # -OR- - initialise_node "localhost:4040"; # -OR- - initialise_node "slave/", "localhost:4040" + initialise_node; # ports are message endpoints @@ -72,9 +70,10 @@ A port is something you can send messages to (with the C function). Ports allow you to register C handlers that can match all or just -some messages. Messages will not be queued. +some messages. Messages send to ports will not be queued, regardless of +anything was listening for them or not. -=item port id - C +=item port ID - C A port ID is the concatenation of a noderef, a hash-mark (C<#>) as separator, and a port name (a printable string of unspecified format). An @@ -87,23 +86,35 @@ which provides nodes to manage each other remotely, and to create new ports. -Nodes are either private (single-process only), slaves (connected to a -master node only) or public nodes (connectable from unrelated nodes). - -=item noderef - C, C, C - -A node reference is a string that either simply identifies the node (for -private and slave nodes), or contains a recipe on how to reach a given -node (for public nodes). - -This recipe is simply a comma-separated list of C pairs (for -TCP/IP, other protocols might look different). - -Node references come in two flavours: resolved (containing only numerical -addresses) or unresolved (where hostnames are used instead of addresses). - -Before using an unresolved node reference in a message you first have to -resolve it. +Nodes are either private (single-process only), slaves (can only talk to +public nodes, but do not need an open port) or public nodes (connectable +from any other node). + +=item node ID - C<[a-za-Z0-9_\-.:]+> + +A node ID is a string that uniquely identifies the node within a +network. Depending on the configuration used, node IDs can look like a +hostname, a hostname and a port, or a random string. AnyEvent::MP itself +doesn't interpret node IDs in any way. + +=item binds - C + +Nodes can only talk to each other by creating some kind of connection to +each other. To do this, nodes should listen on one or more local transport +endpoints - binds. Currently, only standard C specifications can +be used, which specify TCP ports to listen on. + +=item seeds - C + +When a node starts, it knows nothing about the network. To teach the node +about the network it first has to contact some other node within the +network. This node is called a seed. + +Seeds are transport endpoint(s) of as many nodes as one wants. Those nodes +are expected to be long-running, and at least one of those should always +be available. When nodes run out of connections (e.g. due to a network +error), they try to re-establish connections to some seednodes again to +join the network. =back @@ -128,9 +139,9 @@ our $VERSION = $AnyEvent::MP::Kernel::VERSION; our @EXPORT = qw( - NODE $NODE *SELF node_of _any_ + NODE $NODE *SELF node_of after resolve_node initialise_node - snd rcv mon kil reg psub spawn + snd rcv mon mon_guard kil reg psub spawn port ); @@ -144,133 +155,65 @@ =item $thisnode = NODE / $NODE -The C function returns, and the C<$NODE> variable contains the -noderef of the local node. The value is initialised by a call to -C. +The C function returns, and the C<$NODE> variable contains the node +ID of the node running in the current process. This value is initialised by +a call to C. -=item $noderef = node_of $port +=item $nodeid = node_of $port -Extracts and returns the noderef from a port ID or a noderef. +Extracts and returns the node ID part from a port ID or a node ID. -=item initialise_node $noderef, $seednode, $seednode... +=item initialise_node $profile_name -=item initialise_node "slave/", $master, $master... - -Before a node can talk to other nodes on the network it has to initialise -itself - the minimum a node needs to know is it's own name, and optionally -it should know the noderefs of some other nodes in the network. +Before a node can talk to other nodes on the network (i.e. enter +"distributed mode") it has to initialise itself - the minimum a node needs +to know is its own name, and optionally it should know the addresses of +some other nodes in the network to discover other nodes. This function initialises a node - it must be called exactly once (or never) before calling other AnyEvent::MP functions. -All arguments (optionally except for the first) are noderefs, which can be -either resolved or unresolved. - -The first argument will be looked up in the configuration database first -(if it is C then the current nodename will be used instead) to find -the relevant configuration profile (see L). If none is found then -the default configuration is used. The configuration supplies additional -seed/master nodes and can override the actual noderef. - -There are two types of networked nodes, public nodes and slave nodes: - -=over 4 - -=item public nodes - -For public nodes, C<$noderef> (supplied either directly to -C or indirectly via a profile or the nodename) must be a -noderef (possibly unresolved, in which case it will be resolved). - -After resolving, the node will bind itself on all endpoints and try to -connect to all additional C<$seednodes> that are specified. Seednodes are -optional and can be used to quickly bootstrap the node into an existing -network. - -=item slave nodes - -When the C<$noderef> (either as given or overriden by the config file) -is the special string C, then the node will become a slave -node. Slave nodes cannot be contacted from outside and will route most of -their traffic to the master node that they attach to. - -At least one additional noderef is required (either by specifying it -directly or because it is part of the configuration profile): The node -will try to connect to all of them and will become a slave attached to the -first node it can successfully connect to. - -Note that slave nodes cannot change their name, and consequently, their -master, so if the master goes down, the slave node will not function well -anymore until it can re-establish conenciton to its master. This makes -slave nodes unsuitable for long-term nodes or fault-tolerant networks. +The first argument is a profile name. If it is C or missing, then +the current nodename will be used instead (i.e. F). -=back +The function then looks up the profile in the aemp configuration (see the +L commandline utility). -This function will block until all nodes have been resolved and, for slave -nodes, until it has successfully established a connection to a master -server. - -All the seednodes will also be specially marked to automatically retry -connecting to them infinitely. - -Example: become a public node listening on the guessed noderef, or the one -specified via C for the current node. This should be the most common -form of invocation for "daemon"-type nodes. +If the profile specifies a node ID, then this will become the node ID of +this process. If not, then the profile name will be used as node ID. The +special node ID of C will be replaced by a random node ID. + +The next step is to look up the binds in the profile, followed by binding +aemp protocol listeners on all binds specified (it is possible and valid +to have no binds, meaning that the node cannot be contacted form the +outside. This means the node cannot talk to other nodes that also have no +binds, but it can still talk to all "normal" nodes). + +If the profile does not specify a binds list, then the node ID will be +treated as if it were of the form C, which will be resolved and +used as binds list. + +Lastly, the seeds list from the profile is passed to the +L module, which will then use it to keep +connectivity with at least on of those seed nodes at any point in time. + +Example: become a distributed node listening on the guessed noderef, or +the one specified via C for the current node. This should be the +most common form of invocation for "daemon"-type nodes. initialise_node; -Example: become a slave node to any of the the seednodes specified via -C. This form is often used for commandline clients. - - initialise_node "slave/"; - -Example: become a slave node to any of the specified master servers. This -form is also often used for commandline clients. - - initialise_node "slave/", "master1", "192.168.13.17", "mp.example.net"; +Example: become an anonymous node. This form is often used for commandline +clients. -Example: become a public node, and try to contact some well-known master -servers to become part of the network. + initialise_node "anon/"; - initialise_node undef, "master1", "master2"; - -Example: become a public node listening on port C<4041>. - - initialise_node 4041; - -Example: become a public node, only visible on localhost port 4044. +Example: become a distributed node. If there is no profile of the given +name, or no binds list was specified, resolve C and bind +on the resulting addresses. initialise_node "localhost:4044"; -=item $cv = resolve_node $noderef - -Takes an unresolved node reference that may contain hostnames and -abbreviated IDs, resolves all of them and returns a resolved node -reference. - -In addition to C pairs allowed in resolved noderefs, the -following forms are supported: - -=over 4 - -=item the empty string - -An empty-string component gets resolved as if the default port (4040) was -specified. - -=item naked port numbers (e.g. C<1234>) - -These are resolved by prepending the local nodename and a colon, to be -further resolved. - -=item hostnames (e.g. C, C) - -These are resolved by using AnyEvent::DNS to resolve them, optionally -looking up SRV records for the C port, if no port was -specified. - -=back - =item $SELF Contains the current port id while executing C callbacks or C @@ -684,6 +627,28 @@ "$noderef#$id" } +=item after $timeout, @msg + +=item after $timeout, $callback + +Either sends the given message, or call the given callback, after the +specified number of seconds. + +This is simply a utility function that come sin handy at times. + +=cut + +sub after($@) { + my ($timeout, @action) = @_; + + my $t; $t = AE::timer $timeout, 0, sub { + undef $t; + ref $action[0] + ? $action[0]() + : snd @action; + }; +} + =back =head1 AnyEvent::MP vs. Distributed Erlang