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