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

Comparing AnyEvent-MP/MP/Intro.pod (file contents):
Revision 1.26 by root, Sat Aug 29 16:08:03 2009 UTC vs.
Revision 1.27 by root, Sat Aug 29 16:27:50 2009 UTC

320without listeners, but they can still talk to all other nodes. For this 320without listeners, but they can still talk to all other nodes. For this
321example, as well as in many cases in the real world, we can live with this 321example, as well as in many cases in the real world, we can live with this
322restriction, and this makes it easier to avoid DNS (assuming your setup is 322restriction, and this makes it easier to avoid DNS (assuming your setup is
323broken, eliminating one potential problem :). 323broken, eliminating one potential problem :).
324 324
325Whee, setting up nodes can be complicated at first, but you only have to
326do it once per network, and you can leave this boring task to the admins
327or end-users that want to use your stuff :)
328
325=head3 Registering The Receiver 329=head3 Registering The Receiver
326 330
327Ok, where were we. We now discussed the basic purpose of L<AnyEvent::MP::Global> 331Coming back to our example, we have now introduced the basic purpose of
328and initialise_node with it's relations to profiles. We also setup our profiles 332L<AnyEvent::MP::Global> and C<initialise_node> and its use of profiles. We
329for later use and now have to continue talking about the receiver example. 333also set up our profiles for later use and now we will finally continue
334talking about the receiver.
330 335
331Lets look at the next undiscussed line(s) of code: 336Let's look at the next line(s):
332 337
333 my $port = port; 338 my $port = port;
334 AnyEvent::MP::Global::register $port, "eg_receivers"; 339 AnyEvent::MP::Global::register $port, "eg_receivers";
335 340
336The C<port> function already has been discussed. It just creates a new I<port> 341The C<port> function has already been discussed. It simply creates a new
337and gives us the I<port id>. Now to the C<register> function of 342I<port> and returns the I<port ID>. The C<register> function, however,
338L<AnyEvent::MP::Global>: The first argument is a I<port id> that we want to add 343is new: The first argument is the I<port ID> that we want to add to a
339to a I<global group>, and it's second argument is the name of that I<global 344I<global group>, and its second argument is the name of that I<global
340group>. 345group>.
341 346
342You can choose that name of such a I<global group> freely, and it's purpose is 347You can choose the name of such a I<global group> freely (prefixing your
348package name is highly recommended!). The purpose of such a group is to
343to store a set of I<port ids>. That set is made available throughout the whole 349store a set of I<port IDs>. This set is made available throughout the
344L<AnyEvent::MP> network, so that each node can see which ports belong to that 350whole L<AnyEvent::MP> network, so that each node can see which ports
345group. 351belong to that group.
346 352
347The sender will later look for the ports in that I<global group> and send 353Later we will see how the sender looks for the ports in this I<global
348messages to them. 354group> to send messages to them.
349 355
350Last step in the example is to setup a receiver callback for those messages 356The last step in the example is to set up a receiver callback for those
351like we have discussed in the first example. We again match for the I<tag> 357messages, just as was discussed in the first example. We again match
352C<test>. The difference is just that we don't end the application after 358for the tag C<test>. The difference is that this time we don't exit the
353receiving the first message. We just infinitely continue to look out for new 359application after receiving the first message. Instead we continue to wait
354messages. 360for new messages indefinitely.
355 361
356=head2 The Sender 362=head2 The Sender
357 363
358Ok, now lets take a look at the sender: 364Ok, now let's take a look at the sender code:
359 365
360 #!/opt/perl/bin/perl
361 use AnyEvent; 366 use AnyEvent;
362 use AnyEvent::MP; 367 use AnyEvent::MP;
363 use AnyEvent::MP::Global; 368 use AnyEvent::MP::Global;
364 369
365 initialise_node "eg_simple_sender"; 370 initialise_node "eg_simple_sender";
373 for @$ports; 378 for @$ports;
374 }); 379 });
375 380
376 AnyEvent->condvar->recv; 381 AnyEvent->condvar->recv;
377 382
378It's even less code. The C<initialise_node> is known now from the receiver 383It's even less code. The C<initialise_node> serves the same purpose as in
379above. As discussed in the section where we setup the profiles we configure 384the receiver, we just specify a different profile, the profile we set up
380this application to use the I<profile> C<eg_simple_sender>. 385without the binds.
381 386
382Next we setup a timer that repeatedly calls this chunk of code: 387Next we set up a timer that repeatedly (every second) calls this chunk of
388code:
383 389
384 my $ports = AnyEvent::MP::Global::find "eg_receivers" 390 my $ports = AnyEvent::MP::Global::find "eg_receivers"
385 or return; 391 or return;
386 392
387 snd $_, test => time 393 snd $_, test => time
388 for @$ports; 394 for @$ports;
389 395
390The new function here is the C<find> function of L<AnyEvent::MP::Global>. It 396The only new function here is the C<find> function of
391searches in the I<global group> named C<eg_receivers> for ports. If none are 397L<AnyEvent::MP::Global>. It searches in the global group named
392found C<undef> is returned and we wait for the next time the timer fires. 398C<eg_receivers> for ports. If none are found, it returns C<undef>, which
399makes our code return instantly and wait for the next round, as nobody is
400interested in our message.
393 401
394In case the receiver application has been connected and the newly added port by 402As soon as the receiver application has connected and the information
395the receiver has propagated to the sender C<find> returns an array reference 403about the newly added port in the receiver has propagated to the sender
396that contains the I<port id> of the receiver I<port(s)>. 404node, C<find> returns an array reference that contains the I<port ID> of
405the receiver I<port(s)>.
397 406
398We then just send to every I<port> in the I<global group> a message consisting 407We then just send a message with a tag and the current time to every
399of the I<tag> C<test> and the current time in form of a UNIX timestamp. 408I<port> in the global group.
400 409
401And thats all. 410=head3 Multiple Receivers
411
412You can even run multiple receivers - the only problem is that they will
413use the same node ID. To avoid this problem, you can either not specify a
414profile name at all and rely on DNS and your POSIX node name, or you can
415use a special feature called "anonymous nodes":
416
417 aemp profile eg_simple_receiver setnodeid anon/
418
419The special name C<anon/> will be replaced by a random string each time
420the node starts. This way you can start many receivers (they do not bind
421on a TCP port, so cnanot collide with each other), and all of them will
422receive the central time signal.
423
424That's all for now - next time we will teach you about monitoring by
425writing a simple chat client and server :)
402 426
403=head1 SEE ALSO 427=head1 SEE ALSO
404 428
405L<AnyEvent> 429L<AnyEvent>
406 430

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines