6. Advanced functions

6.1. Sending to self

By default, an application doesn't send the messages to itself. Usually, there are more efficient and convenient ways to communicate withing a program. However, if you want to take benefit of the ease of ivy or to be as transparent as possible, you can set the Ivy object so that the pattern matching and message sending will be done for the sender too. This method exists since 1.2.4.

public void sendToSelf(boolean b);
public boolean isSendToSelf();

6.2. Initializing a domain

The default behaviour of an Ivy agent is to accept a command line switch ( -b 10:2010, e.g. ), and if not present, to use the IVYBUS property, ( given by the -DIVYBUS=10:34567 parameter to the jvm ), and, if not present, to default to Ivy.DEFAULT_DOMAIN. This domain is given as a string ardument to the Ivy.start() function. To make this logic easier to follow, the Ivy class provides the programmer with two useful function:

public static String getDomain(String arg);
public static String getDomainArgs(String progname,String[] args);
The getDomain() function, if arg is non null, will return arg, otherwise it will return the IVYBUS property, otherwise the DEFAULT_DOMAIN. A very simple way to start an Ivy agent is with ivy.start(getDomain(null)). The getDomainArgs(name,args) will add very simple processing of the args given to the main() function, and give higher priority to the command line argument.

6.3. Newline within messages

As we have seen in Ivy.sendMsg(), you can not have newline characters within the string you send on the bus. If you still want to send messages with newline, you can encode and decode them at the emitter and receiver's side. With Ivy.protectNewLine(boolean b), you can set your Ivy object to ensure encoding and decoding of newlines characters. This is tested and working between Java ivy applications, but not yet implemented in other ivy libraries. The newlines are replaced by ESC characters ( hex 0x1A ). As the encoding and decoding cost a little more CPU and is not yet standardised in the Ivy protocol, use it at your own risk. We should of course protect the other protocol special characters.

6.4. Sending direct messages

Direct messages is an ivy feature allowing the exchange of information between two ivy clients. It overrides the subscription mechanism, making the exchange faster ( there is no regexp matching, etc ). However, this features breaks the software bus metaphor, and should be replaced with the relevant bounded regexps, at the cost of a small CPU overhead. The full direct message mechanism in Java has been made available since the ivy-java-1.2.3, but i won't document it to make it harder to use.

6.5. Asynchronous Subscription to messages

For each and every remote agent on the bus, a thread is in charge of handling the encoding and decoding of the messages and of the execution of the callbacks. Thus, if a callback consumes much time, the rest of the communication is put on hold and the processing is serialised, eventually leading to a stacking in the socket buffer and to the blocking of the message sender. To alleviate this, we have set up since ivy-java 1.2.4 an asynchronous subscription, where each and every time a callback is performed, it is done in a newly created separate thread. As creating a thread is quite expensive, one should use this method for lengthy callbacks only. Furthermore, to avoid concurrent access to the callback data, the String[] argument passed on to the callbacks are cloned. This causes an extra overhead.

public int bindMsg(String regexp, IvyMessageListener callback,boolean async);
public int bindAsyncMsg(String regexp, IvyMessageListener callback);
If the async boolean parameter is set to true, a new thread will be created for each callback. The same unBindMsg() can be called to cancel a subscription.

6.6. Waiting for someone: waitForClient and waitForMsg

Very often, while developing an Ivy agent, you will be facing the need of the arrival of another agent on the bus to perform your task correctly. For instance, for your spiffy application to run, a gesture recognition engine will have to be on the bus, or another data sending application. The Ivy way to do this is to subscribe to the known agent's ready message (be sure to subscribe before starting the bus), or to implement an IvyApplicationListener and change of state in the connect() method. However, it is often useful to stop and wait, and it is awkward to wait for a variable change.

IvyClient waitForClient(String name, int timeout)
IvyClient waitForMsg(String regexp, int timeout) 
These two methods allow you to stop the flow of your main (or other) thread by waiting for the arrival of an agent, or for the arrival of a message. If the agent is already here, waitForClient will return immediately. If timeout is set to null, your thread can wait "forever", otherwise it will wait timeout milliseconds. With waitForMsg, be aware that your subscription can be propagated to the remote agents after that their message was sent, so that you'd wait for nothing. You had better be sure that the waitForMsg method is called early enough.

6.7. Subscribing to subscriptions

A very common practice when beginning to play with ivy is to develop an ivy agent monitor (the good practice is to use the excellent ivymon written in perl by Daniel Etienne). If you want to notity the user that a remote agent has subscribed or unsubscribed to a regular expression after the protocol handshake, then your monitor agent has to subscribe to subscriptions. To do so, use the following functions:

public int addBindListener(IvyBindListener callback);
public void	 removeBindListener(int id)
A IvyBindListener object must implement the following interface:
public void bindPerformed(IvyClient client, int id, String regexp);
public void unbindPerformed(IvyClient client, int id, String regexp);
For a code sample, see the Probe utility source code.