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();
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.
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.
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.
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.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.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.