NAME

Ivy - Perl extension for implementing a software bus


SYNOPSIS

use Ivy;


DESCRIPTION

The Ivy perl module implements a software bus that provides easy communication between applications. Messages are broadcast as ASCII strings over a network defined by a list of domains and a port. Messages are received if they match a regular expressions and if your application is on the same network as remote ones. Before receive or send message you must call 'init', and 'new' class methods, followed by 'start' method. When you quit your application don't forget to call 'exit' class methods.


CLASS METHODS

init
 Ivy->init(...);
 Ivy::init(...);

Allows one to define global parameters which may be used as default ones at object creation time.

Parameters are :

-loopMode => 'TK'|'LOCAL'
Mode of events loop among TK or LOCAL. According to this mode, you must use Ivy->mainLoop or Tk::MainLoop(3)

-appName => 'your app ivy name'
Name of your application used to identify on ivy bus.

-ivyBus => 'domain 1,...,domain n:port number'
A list of domains (may be empty), followed by a port number where to broadcast messages. If the domain list is empty (i.e. parameter is ':port number'), broadcast will be done on localhost (i.e. '127:port number'). Default is the value of the environment variable IVYBUS and if it is not defined the default is 127:2010.

Since V4.12, it is possible to use multicast (ie. with a domain between 224.0.0.0 and 239.255.255.255). You must be aware than when multicast is used, udp broadcast (defined in the -ivyBus paramter) are skipped. You should also probably avoid using the 244.x.x.x domain often used for networking management.

-messWhenReady => 'your message when ready'
Synchronisation message sent when application is ready to receive and send messages.

-onDieFunc => [\&yourdiefunc, @parameters]
-onDieFunc => [$an_object, \&a_method, @parameters]
A callback or method to call when your application receive a suicide request. Do not call exit() in the callback, Ivy will do it for you.

The prototype of your callback must be as follows:

 sub MyCallback {
   my @parameters = @_;
   ...
 }

The prototype of your method must be as follows:

 sub MyMethod {
   my ($self, @parameters) = @_;
   ...
 }

-pruneRegexp => ['subject 1', ..., 'subject n']
Optimize communication using this option. Regexps which don't match these subjects are removed.
 Example :
  Ivy->init(-loopMode =E<gt> 'TK',
            -appName =E<gt> 'MyWonderfulApp',
            -onDieFunc =E<gt> [\&restorecontext]);

new
 Ivy::new(...);
 Ivy->new(...);

Check parameters, and create an Ivy bus object. You must call Ivy->init before creating a bus.

Parameters are :

-appName => 'your application name'
Name of your application used to identify it with other applications connected on the same bus.

-ivyBus => 'domain 1,...,domain n:port number'
A list of domains, followed by port number where to broadcast messages. Default is 127:2010

-messWhenReady => 'your message when ready'
Synchronisation message sent when your application is ready to receive and send messages.

-onDieFunc => [\&yourdiefunc, @parameters]
-onDieFunc => [$an_object, \&a_method, @parameters]
A callback or method called when your application receives a suicide request. DO NOT CALL exit() in the callback, Ivy will do it for you. The prototype of your callback must be as follows:
 sub MyCallback {
   my @parameters = @_;
   ...
 }

The prototype of your method must be as follows:

 sub MyMethod {
   my ($self, @parameters) = @_;
   ...
 }

-pruneRegexp => ['subject 1', ..., 'subject n']
Optimize communication using this option. Regexps which don't match these subjects are removed.

-neededApp => ['app 1', ..., 'app n']
A list of applications that your application needs present on the bus before running.

-statusFunc => sub {}
A callback which is called every time an agent C connects on the bus, disconnects from the bus, subscribes to a regexp, or unsubscribes to a regexp. When the agent A is stopping, this function is also called inside the agent A for every other agents Ci on the bus, as they are disconnecting. The first 3 parameters are a reference to an array of connected agents Ci, a reference to an array of not connected agents (according to the ``-neededApp'' argument of the new method / function), a reference to a hash table of connected agents Ci (giving the number of each agent). These 3 parameters are maintained for upwards compatibility but should no more be used, since the following three parameters are much easier to use: the name of an appearing / disapearing or subscribing / unsubscribing agent C, its status either ``new'' or ``died'' or ``subscribing'' or ``unsubscribing'', and the hostname where this agent C is running / dying OR the subscribed / unsubscribed regexp. If the hostname of this agent C is not known, it will be replaced by its IP address.

Your callback could be:

 sub MyCallback {
   my ($ref_array_present, $ref_array_absent, $ref_hash_present,
       $appname, $status, $host_or_regexp) = @_;
   # $status is either new or died
   my %present=%$ref_hash_present;
   foreach my $remoteapp (keys %present) {
     if ($present{$remoteapp} > 1) {
       print "n apps $remoteapp are presents on bus\n";
     }
   }
   if ($status eq "new") {
     print "$appname connected from $host_or_regexp\n";
   }
   elsif ($status eq "died") {
     print "$appname disconnected from $host_or_regexp\n";
   }
   elsif ($status eq "subscribing") {
        print "$appname subscribes to $host_or_regexp\n";
   }
   elsif ($status eq "unsubscribing") {
        print "$appname unsubscribed to $host_or_regexp\n";
   }
 }

Example:

 Ivy->new(-ivyBus => '156,157:2204',
          -onDieFunc => [\&restorecontext],
          -neededApp => ["DataServer", "HMI"],
          -statusFunc => \&MyCallback);

mainLoop
 Ivy->mainLoop;
 Ivy::mainLoop;

Local main events loop. Use it if you don't use the Tk library.

stop
 $ivyobj->stop;
 Ivy::stop;

To stop the Ivy main loop.


OBJECT METHODS

start
 $ivyobj->start;
 Ivy::start;

You must call this after you are ready to communicate through an Ivy bus and before you really communicate. The method returns the $ivyobj.

sendMsgs
 $ivyobj->sendMsgs(@messages);
 Ivy::sendMsgs(@messages);

Send a list of messages. A message should not contain a '\n' or it will not be delivered.

 Example :
   $ivyobj->sendMsgs("Hello", "Don't Bother", "Y2K is behind us");
sendAppNameMsgs
 $ivyobj->sendAppNameMsgs(@messages);
 Ivy::sendAppNameMsgs(@messages);

Send a list of messages preceded by your application's name. A message should not contain a '\n' or it will not be delivered.

 Example :
   $ivyobj->sendMsgs("Hello World");
   # it will send "$appName Hello World" over the Ivy bus
bindRegexp
 $ivyobject->bindRegexp($regexp, [\&callback, @cb_parameters]);
 Ivy::bindRegexp($regexp, [\&callback, @cb_parameters]);
 $ivyobject->bindRegexp($regexp, [$an_obj, \&method, @cb_parameters]);
 Ivy::bindRegexp($regexp, [$an_obj, \&method, @cb_parameters]);

This allows you to bind a regular expression to a callback or method. The callback or method will be called for every message that matches the regexp (case insensitive). See perlre(1) to find how to write regexps. Use the bracketing construct ( ... ) so that your callback is called with the captured bits of text as parameters. To unbind callback(s) associated to a regexp use bindRegexp with only one argument, the regexp. Note that doing the same binding more than once will induce multiple call of the same callback (this is usually a bug).

 Example :
   $ivyobject->bindRegexp("\w+ (\d+)", [\&callback, @cb_parameters]);
   # Your callback will be called with one more parameter which will be
   # the name of appli which send the message
   # Your callback and method must be like:
   sub callback {
     my ($sendername, @cb_parameters,
         @matched_regexps_in_brackets) = @_;
     ...
   }
   sub method {
     my ($self, $sendername, @cb_parameters,
                @matched_regexps_in_brackets) = @_;
     ...
   }
   # to unbind:
   $ivyobject->bindRegexp("\w+ (\d+)");
sendDirectMsgs
 $ivyobj->sendDirectMsgs($to, $id, @msgs);
 Ivy::sendDirectMsgs($to, $id, @msgs);

Send a message a message to appli $to. This appli must have done a bindDirect before to accept this message. regexp matching is not used with direct Messages. A message should not contain a '\n' or it will not be delivered.

bindDirect
 $ivyobj->bindDirect($regexp, $id, [\&callback, @cb_parameters]);
 Ivy::bindDirect($id, [\&callback, @cb_parameters]);

The callback will be called with both the @msgs and the @cb_parameters.

 Example :
   $ivyobject->bindDirectMessage("id1", [\&callback, @cb_parameters]);
   # Your callback and method must be like:
   sub cb {
     my (@cb_parameters, @msgs) = @_;
     ...
   }
   sub method {
     my ($self, @cb_parameters, @msgs) = @_;
     ...
   }
sendDieTo
 $ivyobj->sendDieTo($to);
 Ivy::sendDieTo($to);

Send a suicide to the application named $to.

ping
 $ivyobj->ping($to, $timeout);
 Ivy::ping($to, $timeout);

Send a ping message and wait until timeout to receive a pong.

after
 $after_id = $ivyobj->after($timeAfter, \@callbacks_list);
 $after_id = Ivy::after($timeAfter, \@callbacks_list);

Call a list of callbacks after $timeAfter milliseconds. To be used only in conjonction with the 'LOCAL' Mainloop (see the Init method). When using the TK mainloop, you must use the Tk::after method.

repeat
 $repeat_id = $ivyobj->repeat($timeAfter, \@callbacks_list);
 $repeat_id = Ivy:repeat($timeAfter, \@callbacks_list);

Have a list of callbacks repeatedly called every $timeAfter milliseconds. To be used only in conjonction with the 'LOCAL' Mainloop (see the Init method). When using the TK mainloop, you must use the Tk::repeat method.

afterCancel
 $ivyobj->afterCancel($after_or_repeat_id);
 Ivy::afterCancel($after_or_repeat_id);

Cancel an after callback call. To be used only in conjonction with the 'LOCAL' Mainloop (see the Init method). When using the TK mainloop, you must use the Tk::afterCancel method.

afterResetTimer
 $ivyobj->afterResetTimer($after_id);
 Ivy::afterResetTimer($after_id);

Reset a timer if this timer has not yet been triggered. To be used only in conjonction with the 'LOCAL' Mainloop (see the Init method).

fileEvent
 $ivyobj->fileEvent($fd, $cb);
 Ivy::fileEvent($fd, $cb);

Add a fileEvent handler (or remove any handler associated to $fd if $cb paramter is omitted). The callback $cb will get the filehandle $fd as parameter. To be used only in conjonction with the 'LOCAL' Mainloop (see the Init method). When using the TK mainloop, you must use the Tk::fileevent method.

DESTROY
 $ivyobj->DESTROY;

Destroy the $ivyobj object. No other method should be applied to the reference of this deleted object. This method should not be used directly.


BUGS

The stop method does not work!

In the statusFunc, an agent is identified by its name which is not garantted as unique

A message to be sent should not contain '\n' char, because the '\n' is the message separator. Ivy.pm will detect and skip such messages.

No other known bugs at this time. If you find one, please report them to the authors.


SEE ALSO

perl(1), perlre(1), ivyprobe.pl(1)


AUTHORS

Alexandre Bustico <bustico@cena.fr>, Herve Damiano <damiano@cena.fr>, Stephane Chatty <chatty@cena.fr>, Christophe Mertz <mertz@cena.fr>


COPYRIGHT

CENA (C) 1997-2002


HISTORY