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.42 by root, Tue Oct 6 19:39:04 2009 UTC vs.
Revision 1.43 by root, Thu Mar 11 19:20:47 2010 UTC

6module, which allows programs to transparently pass messages within the 6module, which allows programs to transparently pass messages within the
7process and to other processes on the same or a different host. 7process and to other processes on the same or a different host.
8 8
9What kind of messages? Basically a message here means a list of Perl 9What kind of messages? Basically a message here means a list of Perl
10strings, numbers, hashes and arrays, anything that can be expressed as a 10strings, numbers, hashes and arrays, anything that can be expressed as a
11L<JSON> text (as JSON is used by default in the protocol). Here are two 11L<JSON> text (as JSON is the default serialiser in the protocol). Here are
12examples: 12two examples:
13 13
14 write_log => 1251555874, "action was successful.\n" 14 write_log => 1251555874, "action was successful.\n"
15 123, ["a", "b", "c"], { foo => "bar" } 15 123, ["a", "b", "c"], { foo => "bar" }
16 16
17When using L<AnyEvent::MP> it is customary to use a descriptive string as 17When using L<AnyEvent::MP> it is customary to use a descriptive string as
18first element of a message, that indictes the type of the message. This 18first element of a message, that indicates the type of the message. This
19element is called a I<tag> in L<AnyEvent::MP>, as some API functions 19element is called a I<tag> in L<AnyEvent::MP>, as some API functions
20(C<rcv>) support matching it directly. 20(C<rcv>) support matching it directly.
21 21
22Supposedly you want to send a ping message with your current time to 22Supposedly you want to send a ping message with your current time to
23somewhere, this is how such a message might look like (in Perl syntax): 23somewhere, this is how such a message might look like (in Perl syntax):
58 | | | | 58 | | | |
59 |-------------| |-------------| 59 |-------------| |-------------|
60 60
61The strings for the I<port IDs> here are just for illustrative 61The strings for the I<port IDs> here are just for illustrative
62purposes: Even though I<ports> in L<AnyEvent::MP> are also identified by 62purposes: Even though I<ports> in L<AnyEvent::MP> are also identified by
63strings, they can't be choosen manually and are assigned by the system 63strings, they can't be chosen manually and are assigned by the system
64dynamically. These I<port IDs> are unique within a network and can also be 64dynamically. These I<port IDs> are unique within a network and can also be
65used to identify senders or as message tags for instance. 65used to identify senders or as message tags for instance.
66 66
67The next sections will explain the API of L<AnyEvent::MP> by going through 67The next sections will explain the API of L<AnyEvent::MP> by going through
68a few simple examples. Later some more complex idioms are introduced, 68a few simple examples. Later some more complex idioms are introduced,
123This will send the message C<'test', 123> to the I<port> with the I<port 123This will send the message C<'test', 123> to the I<port> with the I<port
124ID> stored in C<$port>. Since in this case the receiver has a I<tag> match 124ID> stored in C<$port>. Since in this case the receiver has a I<tag> match
125on C<test> it will call the callback with the first argument being the 125on C<test> it will call the callback with the first argument being the
126number C<123>. 126number C<123>.
127 127
128The callback is a typicall AnyEvent idiom: the callback just passes 128The callback is a typical AnyEvent idiom: the callback just passes
129that number on to the I<condition variable> C<$end_cv> which will then 129that number on to the I<condition variable> C<$end_cv> which will then
130pass the value to the print. Condition variables are out of the scope 130pass the value to the print. Condition variables are out of the scope
131of this tutorial and not often used with ports, so please consult the 131of this tutorial and not often used with ports, so please consult the
132L<AnyEvent::Intro> about them. 132L<AnyEvent::Intro> about them.
133 133
171C<aemp> utility later. 171C<aemp> utility later.
172 172
173=head2 Shooting the Trouble 173=head2 Shooting the Trouble
174 174
175Sometimes things go wrong, and AnyEvent::MP, being a professional module, 175Sometimes things go wrong, and AnyEvent::MP, being a professional module,
176does not gratitiously spill out messages to your screen. 176does not gratuitously spill out messages to your screen.
177 177
178To help troubleshooting any issues, there are two environment variables 178To help troubleshooting any issues, there are two environment variables
179that you can set. The first, C<PERL_ANYEVENT_MP_WARNLEVEL> sets the 179that you can set. The first, C<PERL_ANYEVENT_MP_WARNLEVEL> sets the
180logging level. The default is C<5>, which means nothing much is 180logging level. The default is C<5>, which means nothing much is
181printed. Youc an increase it to C<8> or C<9> to get more verbose 181printed. You can increase it to C<8> or C<9> to get more verbose
182output. This is example output when starting a node: 182output. This is example output when starting a node:
183 183
184 2009-08-31 19:51:50 <8> node anon/5RloFvvYL8jfSScXNL8EpX starting up. 184 2009-08-31 19:51:50 <8> node anon/5RloFvvYL8jfSScXNL8EpX starting up.
185 2009-08-31 19:51:50 <7> starting global service. 185 2009-08-31 19:51:50 <7> starting global service.
186 2009-08-31 19:51:50 <9> 10.0.0.17:4040 connected as ruth 186 2009-08-31 19:51:50 <9> 10.0.0.17:4040 connected as ruth
229 229
230 AnyEvent->condvar->recv; 230 AnyEvent->condvar->recv;
231 231
232=head3 AnyEvent::MP::Global 232=head3 AnyEvent::MP::Global
233 233
234Now, that wasn't too bad, was it? Ok, let's step through the new functions 234Now, that wasn't too bad, was it? OK, let's step through the new functions
235and modules that have been used. 235and modules that have been used.
236 236
237For starters, there is now an additional module being 237For starters, there is now an additional module being
238used: L<AnyEvent::MP::Global>. This module provides us with a I<global 238used: L<AnyEvent::MP::Global>. This module provides us with a I<global
239registry>, which lets us register ports in groups that are visible on all 239registry>, which lets us register ports in groups that are visible on all
246find the right I<port> of another I<node> in the network we will need 246find the right I<port> of another I<node> in the network we will need
247to communicate this somehow to the sender. And exactly that is what 247to communicate this somehow to the sender. And exactly that is what
248L<AnyEvent::MP::Global> provides. 248L<AnyEvent::MP::Global> provides.
249 249
250Especially in larger, more anonymous networks this is handy: imagine you 250Especially in larger, more anonymous networks this is handy: imagine you
251have a few database backends, a few web frontends and some processing 251have a few database backends, a few web front-ends and some processing
252distributed over a number of hosts: all of these would simply register 252distributed over a number of hosts: all of these would simply register
253themselves in the appropriate group, and your web frontends can start to 253themselves in the appropriate group, and your web front-ends can start to
254find some database backend. 254find some database backend.
255 255
256=head3 C<configure> and the Network 256=head3 C<configure> and the Network
257 257
258Now, let's have a look at the new function, C<configure>: 258Now, let's have a look at the new function, C<configure>:
303 | /\ | 303 | /\ |
304 N3--N4 304 N3--N4
305 305
306The new node needs to know the I<binds> of all nodes already 306The new node needs to know the I<binds> of all nodes already
307connected. Exactly this is what the I<seeds> are for: Let's assume that 307connected. Exactly this is what the I<seeds> are for: Let's assume that
308the new node (C<N5>) uses the TCP address of the node C<N2> as seed. This 308the new node (C<N5>) uses the TCP address of the node C<N2> as seed. This
309cuases it to connect to C<N2>: 309causes it to connect to C<N2>:
310 310
311 N1--N2____ 311 N1--N2____
312 | \/ | N5 312 | \/ | N5
313 | /\ | 313 | /\ |
314 N3--N4 314 N3--N4
345 grp_reg eg_receivers => $port; 345 grp_reg eg_receivers => $port;
346 346
347The C<port> function has already been discussed. It simply creates a new 347The C<port> function has already been discussed. It simply creates a new
348I<port> and returns the I<port ID>. The C<grp_reg> function, however, is 348I<port> and returns the I<port ID>. The C<grp_reg> function, however, is
349new: The first argument is the name of a I<global group>, and the second 349new: The first argument is the name of a I<global group>, and the second
350argument is the I<port ID> to register in that group. group>. 350argument is the I<port ID> to register in that group.
351 351
352You can choose the name of such a I<global group> freely (prefixing your 352You can choose the name of such a I<global group> freely (prefixing your
353package name is I<highly recommended> however and might be enforce din 353package name is I<highly recommended> however and might be enforce din
354future versions!). The purpose of such a group is to store a set of port 354future versions!). The purpose of such a group is to store a set of port
355IDs. This set is made available throughout the L<AnyEvent::MP> network, 355IDs. This set is made available throughout the L<AnyEvent::MP> network,
413We then just send a message with a tag and the current time to every 413We then just send a message with a tag and the current time to every
414I<port> in the global group. 414I<port> in the global group.
415 415
416=head3 Splitting Network Configuration and Application Code 416=head3 Splitting Network Configuration and Application Code
417 417
418Ok, so far, this works. In the real world, however, the person configuring 418OK, so far, this works. In the real world, however, the person configuring
419your application to run on a specific network (the end user or network 419your application to run on a specific network (the end user or network
420administrator) is often different to the person coding the application. 420administrator) is often different to the person coding the application.
421 421
422Or to put it differently: the arguments passed to configure are usually 422Or to put it differently: the arguments passed to configure are usually
423provided not by the programmer, but by whoever is deploying the program. 423provided not by the programmer, but by whoever is deploying the program.
577 577
578Then you will find it does not work - when the after callback is executed, 578Then you will find it does not work - when the after callback is executed,
579it does not run in port context anymore, so exceptions will not be caught. 579it does not run in port context anymore, so exceptions will not be caught.
580 580
581For these cases, AnyEvent::MP exports a special "closure constructor" 581For these cases, AnyEvent::MP exports a special "closure constructor"
582called C<psub>, which works just like perl's builtin C<sub>: 582called C<psub>, which works just like perls built-in C<sub>:
583 583
584 my $port = port { 584 my $port = port {
585 after 1, psub { die "oops" }; 585 after 1, psub { die "oops" };
586 }; 586 };
587 587
986 986
987The C<spawn> function creates a new port on a remote node and returns 987The C<spawn> function creates a new port on a remote node and returns
988its port ID. After creating the port it calls a function on the remote 988its port ID. After creating the port it calls a function on the remote
989node, passing any remaining arguments to it, and - most importantly - 989node, passing any remaining arguments to it, and - most importantly -
990executes the function within the context of the new port, so it can be 990executes the function within the context of the new port, so it can be
991manipulated by refering to C<$SELF>. The init function can reside in a 991manipulated by referring to C<$SELF>. The init function can reside in a
992module (actually it normally I<should> reside in a module) - AnyEvent::MP 992module (actually it normally I<should> reside in a module) - AnyEvent::MP
993will automatically load the module if the function isn't defined. 993will automatically load the module if the function isn't defined.
994 994
995The C<spawn> function returns immediately, which means you can instantly 995The C<spawn> function returns immediately, which means you can instantly
996send messages to the port, long before the remote node has even heard 996send messages to the port, long before the remote node has even heard
1041distribution and then configure nodes, for example, if I want to run the 1041distribution and then configure nodes, for example, if I want to run the
1042Bummskraut IRC backend on a machine named "ruth", I could do this: 1042Bummskraut IRC backend on a machine named "ruth", I could do this:
1043 1043
1044 aemp profile ruth addservice BK::Backend::IRC:: 1044 aemp profile ruth addservice BK::Backend::IRC::
1045 1045
1046And any F<aemp run> on that host will automaticllay have the bummskraut 1046And any F<aemp run> on that host will automatically have the Bummskraut
1047irc backend running. 1047IRC backend running.
1048 1048
1049That's plenty of possibilities you can use - it's all up to you how you 1049That's plenty of possibilities you can use - it's all up to you how you
1050structure your application. 1050structure your application.
1051 1051
1052=head1 PART 4: Coro::MP - selective receive 1052=head1 PART 4: Coro::MP - selective receive
1059registering callbacks for each message type, C<Coro::MP> attached a 1059registering callbacks for each message type, C<Coro::MP> attached a
1060(coro-) thread to a port. The thread can then opt to selectively receive 1060(coro-) thread to a port. The thread can then opt to selectively receive
1061messages it is interested in. Other messages are not lost, but queued, and 1061messages it is interested in. Other messages are not lost, but queued, and
1062can be received at a later time. 1062can be received at a later time.
1063 1063
1064The C<Coro::MP> module is not part of L<AnyEvent::MP>, but a seperate 1064The C<Coro::MP> module is not part of L<AnyEvent::MP>, but a separate
1065module. It is, however, tightly integrated into C<AnyEvent::MP> - the 1065module. It is, however, tightly integrated into C<AnyEvent::MP> - the
1066ports it creates are fully compatible to C<AnyEvent::MP> ports. 1066ports it creates are fully compatible to C<AnyEvent::MP> ports.
1067 1067
1068In fact, C<Coro::MP> is more of an extension than a separate module: all 1068In fact, C<Coro::MP> is more of an extension than a separate module: all
1069functions exported by C<AnyEvent::MP> are exported by it as well. 1069functions exported by C<AnyEvent::MP> are exported by it as well.
1110 1110
1111Let's go through it part by part. 1111Let's go through it part by part.
1112 1112
1113 my $ioserver = port_async { 1113 my $ioserver = port_async {
1114 1114
1115Ports cna be created by attaching a thread to an existing port via 1115Ports can be created by attaching a thread to an existing port via
1116C<rcv_async>, or as here by calling C<port_async> with the code to exeucte 1116C<rcv_async>, or as here by calling C<port_async> with the code to execute
1117as a thread. The C<async> component comes from the fact that threads are 1117as a thread. The C<async> component comes from the fact that threads are
1118created using the C<Coro::async> function. 1118created using the C<Coro::async> function.
1119 1119
1120The thread runs in a normal port context (so C<$SELF> is set). In 1120The thread runs in a normal port context (so C<$SELF> is set). In
1121addition, when the thread returns, it will be C<kil> I<normally>, i.e. 1121addition, when the thread returns, it will be C<kil> I<normally>, i.e.
1135 1135
1136 my $fh = aio_open $path, O_WRONLY|O_CREAT, 0666 1136 my $fh = aio_open $path, O_WRONLY|O_CREAT, 0666
1137 or die "$path: $!"; 1137 or die "$path: $!";
1138 1138
1139Then we enter a loop again, to serve as many C<data> messages as 1139Then we enter a loop again, to serve as many C<data> messages as
1140neccessary: 1140necessary:
1141 1141
1142 while () { 1142 while () {
1143 my (undef, undef, $data) = get_cond { 1143 my (undef, undef, $data) = get_cond {
1144 $_[0] eq "data" && $_[1] eq $port 1144 $_[0] eq "data" && $_[1] eq $port
1145 } 5 1145 } 5
1167 1167
1168Otherwise we need to write the data: 1168Otherwise we need to write the data:
1169 1169
1170 aio_write $fh, undef, undef, $data, 0; 1170 aio_write $fh, undef, undef, $data, 0;
1171 1171
1172That's basically it. Note that every process should ahve some kind of 1172That's basically it. Note that every process should have some kind of
1173supervisor. In our case, the supervisor simply prints any error message: 1173supervisor. In our case, the supervisor simply prints any error message:
1174 1174
1175 mon $ioserver, sub { 1175 mon $ioserver, sub {
1176 warn "ioserver was killed: @_\n"; 1176 warn "ioserver was killed: @_\n";
1177 }; 1177 };
1218 }; 1218 };
1219 1219
1220=head1 THE END 1220=head1 THE END
1221 1221
1222This is the end of this introduction, but hopefully not the end of 1222This is the end of this introduction, but hopefully not the end of
1223your career als AEMP user. I hope the tutorial was enough to make the 1223your career as AEMP user. I hope the tutorial was enough to make the
1224basic concepts clear. Keep in mind that distributed programming is not 1224basic concepts clear. Keep in mind that distributed programming is not
1225completely trivial, that AnyEvent::MP is still in it's infancy, and I hope 1225completely trivial, that AnyEvent::MP is still in it's infancy, and I hope
1226it will be useful to create exciting new applications. 1226it will be useful to create exciting new applications.
1227 1227
1228=head1 SEE ALSO 1228=head1 SEE ALSO

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines