… | |
… | |
323 | new: The first argument is the name of a I<database family> and the second |
323 | new: The first argument is the name of a I<database family> and the second |
324 | argument is the name of a I<subkey> within that family. The third argument |
324 | argument is the name of a I<subkey> within that family. The third argument |
325 | would be the I<value> to be associated with the family and subkey, but, |
325 | would be the I<value> to be associated with the family and subkey, but, |
326 | since it is missing, it will simply be C<undef>. |
326 | since it is missing, it will simply be C<undef>. |
327 | |
327 | |
328 | Ok, what's this weird tlak about families you wonder - AnyEvent::MP comes |
328 | OK, what's this weird talk about families you wonder - AnyEvent::MP comes |
329 | with a distributed database. This database runs on so-called "global" |
329 | with a distributed database. This database runs on so-called "global" |
330 | nodes, which usually are the seed nodes of your network. The database |
330 | nodes, which usually are the seed nodes of your network. The database |
331 | structure is "simply" a hash of hashes of values. |
331 | structure is "simply" a hash of hashes of values. |
332 | |
332 | |
333 | In other words, if the database were stored in C<%DB>, then the C<db_set> |
333 | In other words, if the database were stored in C<%DB>, then the C<db_set> |
… | |
… | |
339 | is simply the key in this hash. And C<db_set> very much works like an |
339 | is simply the key in this hash. And C<db_set> very much works like an |
340 | assignment. |
340 | assignment. |
341 | |
341 | |
342 | The family namespace is shared by all nodes in a network, so the names |
342 | The family namespace is shared by all nodes in a network, so the names |
343 | should be reasonably unique, for example, they could start with the name |
343 | should be reasonably unique, for example, they could start with the name |
344 | of your module, or the name of the program. |
344 | of your module, or the name of the program, using your port name or node |
|
|
345 | name as subkey. |
345 | |
346 | |
346 | The purpose behind adding this key to the database is that the sender can |
347 | The purpose behind adding this key to the database is that the sender can |
347 | look it up and find our port. We will shortly see how. |
348 | look it up and find our port. We will shortly see how. |
348 | |
349 | |
349 | The last step in the example is to set up a receiver callback for those |
350 | The last step in the example is to set up a receiver callback for those |
… | |
… | |
352 | application after receiving the first message. Instead we continue to wait |
353 | application after receiving the first message. Instead we continue to wait |
353 | for new messages indefinitely. |
354 | for new messages indefinitely. |
354 | |
355 | |
355 | =head2 The Sender |
356 | =head2 The Sender |
356 | |
357 | |
357 | Ok, now let's take a look at the sender code: |
358 | OK, now let's take a look at the sender code: |
358 | |
359 | |
359 | use AnyEvent; |
360 | use AnyEvent; |
360 | use AnyEvent::MP; |
361 | use AnyEvent::MP; |
361 | |
362 | |
362 | configure nodeid => "eg_sender/%u", seeds => ["*:4040"]; |
363 | configure nodeid => "eg_sender/%u", seeds => ["*:4040"]; |
… | |
… | |
371 | }; |
372 | }; |
372 | |
373 | |
373 | AnyEvent->condvar->recv; |
374 | AnyEvent->condvar->recv; |
374 | |
375 | |
375 | It's even less code. The C<configure> serves the same purpose as in the |
376 | It's even less code. The C<configure> serves the same purpose as in the |
376 | receiver, but instead of specifying binds we specify a list of seeds - |
377 | receiver, but instead of specifying binds we specify a list of seeds - the |
377 | the seed happens to be the same as the bind used by the receiver, which |
378 | only seed happens to be the same as the bind used by the receiver, which |
378 | therefore becomes our seed node. |
379 | therefore becomes our seed node. |
379 | |
380 | |
380 | Remember the part about having to wait till things become available? After |
381 | Remember the part about having to wait till things become available? Well, |
381 | configure returns, nothing has been done yet - the node is not connected |
382 | after configure returns, nothing has been done yet - the node is not |
382 | to the network, knows nothing about the database contents, and it can take |
383 | connected to the network, knows nothing about the database contents, and |
383 | ages (for a computer :) for this situation to change. |
384 | it can take ages (for a computer :) for this situation to change. |
384 | |
385 | |
385 | Therefore, the sender waits, in this case by using the C<db_mon> |
386 | Therefore, the sender waits, in this case by using the C<db_mon> |
386 | function. This function registers an interest in a specific database |
387 | function. This function registers an interest in a specific database |
387 | family (C<eg_receivers>). Each time something inside the family changes |
388 | family (in this case C<eg_receivers>). Each time something inside the |
388 | (a key is added, changed or deleted), it will call our callback with the |
389 | family changes (a key is added, changed or deleted), it will call our |
389 | family hash as first argument, and the list of keys as second argument. |
390 | callback with the family hash as first argument, and the list of keys as |
|
|
391 | second argument. |
390 | |
392 | |
391 | The callback only checks whether the C<%$family> has is empty - in this |
393 | The callback only checks whether the C<%$family> has is empty - if it is, |
392 | case it does nothing. |
394 | then it doesn't do anything. But eventually the family will contain the |
393 | |
395 | port subkey we set in the sender. Then it will send a message to it (and |
394 | Eventually the family will, however, contain the port we set in the |
396 | any other receiver in the same family). Likewise, should the receiver go |
395 | sender. Then it will send a message to it and any other receiver in the |
397 | away and come back, or should another receiver come up, it will again send |
396 | group. |
398 | a message to all of them. |
397 | |
399 | |
398 | You can experiment by having multiple receivers - you have to change the |
400 | You can experiment by having multiple receivers - you have to change the |
399 | "binds" parameter in the receiver to the seeds used in the sender to start |
401 | "binds" parameter in the receiver to the seeds used in the sender to start |
400 | up additional receivers, but then you can start as many as you like. If |
402 | up additional receivers, but then you can start as many as you like. If |
401 | you specify proper IP addresses for the seeds, you can even run them on |
403 | you specify proper IP addresses for the seeds, you can even run them on |
402 | different computers. |
404 | different computers. |
403 | |
405 | |
404 | Each time you start the sender, it will send a message to all receivers it |
406 | Each time you start the sender, it will send a message to all receivers it |
405 | finds (you have to interrupt it manualy afterwards). |
407 | finds (you have to interrupt it manually afterwards). |
406 | |
408 | |
407 | Things you could try include using C<PERL_ANYEVENT_MP_TRACE=1> to see |
409 | Additional things you could try include using C<PERL_ANYEVENT_MP_TRACE=1> |
408 | which messages are exchanged, or starting the sender first and see how |
410 | to see which messages are exchanged, or starting the sender first and see |
409 | long it takes it to find the receiver. |
411 | how long it takes it to find the receiver. |
410 | |
412 | |
411 | =head3 Splitting Network Configuration and Application Code |
413 | =head3 Splitting Network Configuration and Application Code |
412 | |
414 | |
413 | #TODO# |
415 | #TODO# |
414 | OK, so far, this works. In the real world, however, the person configuring |
416 | OK, so far, this works. In the real world, however, the person configuring |