From 750f33265d208df8218f85359e3f027900c58363 Mon Sep 17 00:00:00 2001 From: jestin Date: Fri, 22 Jul 2011 16:49:57 +0000 Subject: Passage en 1.2.14 --- src/Ivy.java | 811 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 439 insertions(+), 372 deletions(-) (limited to 'src/Ivy.java') diff --git a/src/Ivy.java b/src/Ivy.java index 5e3362f..b147af3 100755 --- a/src/Ivy.java +++ b/src/Ivy.java @@ -1,10 +1,12 @@ /** * a software bus package * - * @author Yannick Jestin - * @author http://www.tls.cena.fr/products/ivy/ + * @author Yannick Jestin yannick.jestin&enac.fr + * @author http://www.tls.cena.fr/products/ivy/ * * (c) CENA 1998-2004 + * (c) ENAC 2005-2011 * *
  *Ivy bus = new Ivy("Dummy agent","ready",null);
@@ -13,6 +15,37 @@
  *
* * CHANGELOG: + * 1.2.14 + * - added a lock mechanism to be sure that once a connexion has been + * initiated, the ready message will be sent before stopping the bus + * now: Ivy b = new Ivy(...); b.sendMsg("coucou"); b.stop(); should + * send messages (at least the ready message) if there is a connexion + * attempt made before b.stop() is effective. To be sure, there is a 200ms + * delay before b.stop() can be effective (the Threads stopped, the sockets + * closed) + * - reintroduced a mechanism to allow the drop of a double connexion + * attempt + * - removed protected methods from javadoc + * - switch to apache fop + docbook for documentation + * - added sypport to the Swing Dispatch Thread in the bindAsyncMsg api + * (this breaks the former API, this is BAAAAAD). Use BindType.SWING as the + * latter argument + * - javadoc updated + * - appName gone private, with a protected accessor + * - add a lockApp synchronization for application socket control + * - use of stringbuffers to concatenate strings, instead of using +, which + * could lead to a quadractic cost in the number of iteraction (the growing + * string was recopied in each iteration) + * - throws RuntimeException instead of System.exit(), allows code reuse + * - ready message is set to appName + " READY" if null has been provided + * - switch from gnu regexp (deprecated) to the built in java regexp + * - when possible, move the regexp Pattern.compile in static areas, to avoid multiple + * calls + * - add generic types to declarations + * - fxed a potential null pointer dereference on quit + * - lowercase CheckRegexp to checkRegexp (bad practice, thanks to FindBugs) + * - recopy the filter String[] in setfilter, to avoid exposing internal + * representation (unsafe operation) * 1.2.13: * - adds support for RESyntaxException * 1.2.12: @@ -86,114 +119,131 @@ * adding the sendToSelf feature * fixed the printStackTrace upon closing of the ServerSocket after a close() */ -package fr.dgac.ivy ; +package fr.dgac.ivy; import java.net.*; import java.io.*; import java.util.*; import gnu.getopt.Getopt; -import org.apache.regexp.*; +import java.util.regex.*; public class Ivy implements Runnable { /** - * the name of the application on the bus + * the protocol version number. */ - String appName; + public static final int PROTOCOLVERSION = 3; + public static final int PROTOCOLMINIMUM = 3; + private static final int GRACEDELAY = 200; // in milliseconds /** - * the protocol version number + * the port for the UDP rendez vous, if none is supplied. */ - public static final int PROTOCOLVERSION = 3 ; - public static final int PROTOCOLMINIMUM = 3 ; + public static final int DEFAULT_PORT = 2010; /** - * the port for the UDP rendez vous, if none is supplied + * the domain for the UDP rendez vous. */ - public static final int DEFAULT_PORT = 2010 ; - /** - * the domain for the UDP rendez vous - */ - public static final String DEFAULT_DOMAIN = "127.255.255.255:"+DEFAULT_PORT; + public static final String DEFAULT_DOMAIN = "127.255.255.255:" + DEFAULT_PORT; /** * the library version, useful for development purposes only, when java is * invoked with -DIVY_DEBUG */ - public static final String libVersion ="1.2.13"; + public static final String LIBVERSION ="1.2.14"; + public static final int TIMEOUTLENGTH = 1000; + private String appName; + private int applicationPort; /* Application port number */ + private String ready_message = null; + private boolean doProtectNewlines = false; + private SelfIvyClient selfIvyClient; + private Object lockApp = new Object(); private boolean debug; private ServerSocket app; - private Vector watchers = new Vector(); + private Vector watchers = new Vector(); private volatile Thread serverThread; // to ensure quick communication of the end - private Hashtable clients = new Hashtable(); - private Hashtable half = new Hashtable(); - private Vector ivyApplicationListenerList = new Vector(); - private Vector ivyBindListenerList = new Vector(); - private Vector sendThreads = new Vector(); + private Hashtable clients = new Hashtable(); + private Hashtable half = new Hashtable(); + private Vector ivyApplicationListenerList = new Vector(); + private Vector ivyBindListenerList = new Vector(); + private Vector sendThreads = new Vector(); private String[] filter = null; - private boolean stopped=true; - protected int applicationPort; /* Application port number */ - protected String ready_message = null; - protected boolean doProtectNewlines = false ; - private boolean doSendToSelf = false ; - protected SelfIvyClient selfIvyClient ; - public final static int TIMEOUTLENGTH = 1000; - private static int serial=0; - private int myserial=serial++; - static long current = System.currentTimeMillis(); - private static java.util.Random generator = new java.util.Random(current*(serial+1)); - private String watcherId=null; - + private boolean stopped = true; + private boolean starting = false; + protected Object readyToSend = new Object(); + private boolean doSendToSelf = false; + private static int serial = 0; + private int myserial = serial++; + private static long current = System.currentTimeMillis(); + private static java.util.Random generator = new java.util.Random(current*(serial + 1)); + private String watcherId = null; + private static Pattern rangeRE; // tcp range min and max + private static Pattern bounded; + + private static final Object lock = new Object(); + /** * Readies the structures for the software bus connexion. * * All the dirty work is done un the start() method * @see #start * @param name The name of your Ivy agent on the software bus - * @param message The hellow message you will send once ready + * @param message The hellow message you will send once ready. It can be + * null, in which case "appname READY" will be the default * @param appcb A callback handling the notification of connexions and - * disconnections, may be null + * disconnections, (may be null for most agents) */ - public Ivy(String name, String message, IvyApplicationListener appcb) { + public Ivy(final String name, final String message, final IvyApplicationListener appcb) { appName = name; - ready_message = message; - debug = (System.getProperty("IVY_DEBUG")!=null); - if ( appcb != null ) ivyApplicationListenerList.addElement( appcb ); - selfIvyClient=new SelfIvyClient(this,name); + ready_message = (message == null) ? name + " READY" : message; + debug = + (System.getProperty("IVY_DEBUG") != null) + || (System.getProperty("IVY_DEBUG") != null); + if ( appcb != null ) { + ivyApplicationListenerList.addElement( appcb ); + } + selfIvyClient = new SelfIvyClient(this , name); } /** - * Waits for a message to be received + * Waits for a message to be received. * * @since 1.2.4 * @param regexp the message we're waiting for to continue the main thread. * @param timeout in millisecond, 0 if infinite + * @throws IvyException if something bad happens * @return the IvyClient who sent the message, or null if the timeout is * reached */ - public IvyClient waitForMsg(String regexp,int timeout) throws IvyException { + public final IvyClient waitForMsg(final String regexp , final int timeout) throws IvyException { Waiter w = new Waiter(timeout); - int re = bindMsg(regexp,w); - IvyClient ic=w.waitFor(); + int re = bindMsg(regexp , w); + IvyClient ic = w.waitFor(); unBindMsg(re); return ic; } /** - * Waits for an other IvyClient to join the bus + * Waits for an other IvyClient to join the bus. * * @since 1.2.4 * @param name the name of the client we're waiting for to continue the main thread. * @param timeout in millisecond, 0 if infinite + * @throws IvyException if something bad happens * @return the first IvyClient with the name or null if the timeout is * reached */ - public IvyClient waitForClient(String name,int timeout) throws IvyException { + public final IvyClient waitForClient(final String name , final int timeout) throws IvyException { IvyClient ic; - if (name==null) throw new IvyException("null name given to waitForClient"); + if (name == null) { + throw new IvyException("null name given to waitForClient"); + } // first check if client with the same name is on the bus - if ((ic=alreadyThere(clients,name))!=null) return ic; + ic = alreadyThere(clients , name); + if (ic != null) { + return ic; + } // if not enter the waiting loop - WaiterClient w = new WaiterClient(name,timeout,clients); + WaiterClient w = new WaiterClient(name , timeout , clients); int i = addApplicationListener(w); - ic=w.waitForClient(); + ic = w.waitForClient(); removeApplicationListener(i); return ic; } @@ -201,15 +251,9 @@ public class Ivy implements Runnable { /* * since 1.2.8 */ - static protected IvyClient alreadyThere(Hashtable c,String name) { - IvyClient ic; - for (Enumeration e=c.elements();e.hasMoreElements();) { - try { - ic = (IvyClient)e.nextElement(); - } catch (ArrayIndexOutOfBoundsException _ ) { - return null; // with gij, it ... can happen - } - if ((ic!=null)&&(name.compareTo(ic.getApplicationName())==0)) return ic; + protected static IvyClient alreadyThere(final Hashtable c , final String name) { + for (IvyClient ic : c.values()) { + if ((ic != null)&&(name.compareTo(ic.getApplicationName()) == 0)) return ic; } return null; } @@ -220,8 +264,11 @@ public class Ivy implements Runnable { *
  • One thread (IvyWatcher) for each traffic rendezvous (either UDP broadcast or TCPMulticast) *
  • One thread (serverThread/Ivy) to accept incoming connexions on server socket *
  • a thread for each IvyClient when the connexion has been done - * - * @param domainbus a domain of the form 10.0.0:1234, it is similar to the + * @throws IvyException if there is a problem joining the bus + * @param domainbus a domain of the form 10.0.0:1234, A good practice is to + * sick to a null value, so that your agent will honor the IVY_BUS parameter + * given to the jvm (java -DIVYBUS= ... . Otherwise, you can provide some + * hard-coded value, similar to the * netmask without the trailing .255. This will determine the meeting point * of the different applications. Right now, this is done with an UDP * broadcast. Beware of routing problems ! You can also use a comma @@ -230,108 +277,124 @@ public class Ivy implements Runnable { * 1.2.8: goes synchronized. I don't know if it's really useful * */ - public synchronized void start(String domainbus) throws IvyException { + + public final void start(final String domainbus) throws IvyException { if (!stopped) throw new IvyException("cannot start a bus that's already started"); + setStarting(true); // this will remain true entil one of the PacketSenders has finished stopped=false; - if (domainbus==null) domainbus=getDomain(null); - Properties sysProp = System.getProperties(); - sysProp.put("IVYBUS",domainbus); - String range=(String)sysProp.get("IVYRANGE"); - RE rangeRE; // tcp range min and max - try { - rangeRE = new RE("(\\d+)-(\\d+)"); // tcp range min and max - } catch ( RESyntaxException res ) { - throw new IvyException("Regular Expression bug in Ivy source code ... bailing out"); + String db = domainbus; + if (db == null) { + db = getDomain(null); } - if ((range!=null)&&rangeRE.match(range)) { - int rangeMin=Integer.parseInt(rangeRE.getParen(1)); - int rangeMax=Integer.parseInt(rangeRE.getParen(2)); - int index=rangeMin; - traceDebug("trying to allocate a TCP port between "+rangeMin+" and "+rangeMax); - boolean allocated=false; + Properties sysProp = System.getProperties(); + sysProp.put("IVYBUS" , db); + String range = (String)sysProp.get("IVYRANGE"); + Matcher match; + if ((range != null)&&(match = rangeRE.matcher(range)).matches()) { + int rangeMin = Integer.parseInt(match.group(1)); + int rangeMax = Integer.parseInt(match.group(2)); + int index = rangeMin; + traceDebug("trying to allocate a TCP port between " + rangeMin + " and " + rangeMax); + boolean allocated = false; while (!allocated) try { - if (index>rangeMax) throw new IvyException("no available port in IVYRANGE" + range ); - app = new ServerSocket(index); - app.setSoTimeout(TIMEOUTLENGTH); - applicationPort = app.getLocalPort(); - allocated=true; + if (index>rangeMax) throw new IvyException("no available port in IVYRANGE" + range ); + synchronized (lockApp) { + app = new ServerSocket(index); + app.setSoTimeout(TIMEOUTLENGTH); + applicationPort = app.getLocalPort(); + } + allocated = true; } catch (BindException e) { index++; } catch (IOException e) { - throw new IvyException("can't open TCP service socket " + e ); + throw new IvyException("can't open TCP service socket " + e ); } } else try { - app = new ServerSocket(0); - app.setSoTimeout(TIMEOUTLENGTH); - applicationPort = app.getLocalPort(); + synchronized (lockApp) { + app = new ServerSocket(0); + app.setSoTimeout(TIMEOUTLENGTH); + applicationPort = app.getLocalPort(); + } } catch (IOException e) { throw new IvyException("can't open TCP service socket " + e ); } - // app.getInetAddress().getHostName()) is always 0.0.0.0 - traceDebug("lib: "+libVersion+" protocol: "+PROTOCOLVERSION+" TCP service open on port "+applicationPort); + traceDebug("lib: " + LIBVERSION + " protocol: " + PROTOCOLVERSION + " TCP service open on port " + applicationPort); - Domain[] d = parseDomains(domainbus); - if (d.length==0) throw new IvyException("no domain found in "+domainbus); - watcherId=getWBUId().replace(' ','*'); // no space in the watcherId + Domain[] d = parseDomains(db); + if (d.length == 0) throw new IvyException("no domain found in " + db); + watcherId = getWBUId().replace(' ' , '*'); // no space in the watcherId // readies the rendezvous : an IvyWatcher (thread) per domain bus - for (int index=0;index=0;index--) { - Domain dom=d[index]; - if (dom.port==0) dom.port=lastport; - lastport=dom.port; + for (index--; index >= 0; index--) { + Domain dom = d[index]; + if (dom.port == 0) dom.port = lastport; + lastport = dom.port; } return d; } + + private void waitForRemote(String s) { + try { + while (starting==true) { + Thread.sleep(GRACEDELAY); + traceDebug("I'm waiting before "+s+", a starting tread is in progress"); + } + } catch (InterruptedException ie) { + // should not happen, and it's not a problem anyway + } + } + /** - * disconnects from the Ivy bus + * disconnects from the Ivy bus. */ - public void stop() { + public final void stop() { + waitForRemote("stopping"); if (stopped) return; - stopped=true; + stopped = true; + serverThread = null; traceDebug("beginning stopping"); try { // stopping the serverThread - Thread t=serverThread; - serverThread=null; - if (t!=null) t.interrupt(); // The serverThread might be stopped even before having been created - // System.out.println("IZZZ joining "+t); - try { t.join(); } catch ( InterruptedException _ ) { } - // TODO BUG avec gcj+kaffe, le close() reste pendu et ne rend pas la main - app.close(); + Thread t = serverThread; + if (t != null) { + t.interrupt(); // The serverThread might be stopped even before having been created + // System.out.println("IZZZ joining " + t); + try { t.join(); } catch ( InterruptedException ie ) { + ie.printStackTrace(); + } + } + synchronized (lockApp) { app.close(); } // stopping the IvyWatchers - for (int i=0;i getIvyClients() { + Vector v = new Vector(); + for (IvyClient ic : clients.values() ) if (ic != null) v.addElement(ic); return v; } /** - * gives a list of IvyClient with the name given in parameter + * gives a list of IvyClient with the name given in parameter. * * @param name The name of the Ivy agent you're looking for + * @return a vector of IvyClients */ - public Vector getIvyClientsByName(String name) { - Vector v=new Vector(); + public final Vector getIvyClientsByName(final String name) { + Vector v = new Vector(); String icname; - for (Enumeration e=clients.elements();e.hasMoreElements();) { - try { - IvyClient ic = (IvyClient)e.nextElement(); - if ( (ic==null)||((icname=ic.getApplicationName())==null) ) break; - if (icname.compareTo(name)==0) v.addElement(ic); - } catch (ArrayIndexOutOfBoundsException _ ) { - continue; - } + for (IvyClient ic : clients.values() ) { + if ( (ic == null)||((icname = ic.getApplicationName()) == null) ) break; + if (icname.compareTo(name) == 0) v.addElement(ic); } return v; } /** - * returns the domain bus + * returns the domain bus. * * @param domainbus if non null, returns the argument * @return It returns domainbus, if non null, * otherwise it returns the IVYBUS property if non null, otherwise it * returns Ivy.DEFAULT_DOMAIN */ - public static String getDomain(String domainbus) { - if ( domainbus == null ) domainbus = System.getProperty("IVYBUS"); - if ( domainbus == null ) domainbus = DEFAULT_DOMAIN; - return domainbus; + public static final String getDomain(final String domainbus) { + String db = null; + db = domainbus; + if ( db == null ) db = System.getProperty("IVYBUS"); + if ( db == null ) db = DEFAULT_DOMAIN; + return db; } /** - * returns the domain bus + * returns the domain bus. * * @since 1.2.8 * @param progname The name of your program, for error message @@ -732,37 +782,35 @@ public class Ivy implements Runnable { * @return returns the domain bus, ascending priority : ivy default bus, IVY_BUS * property, -b domain on the command line */ - public static String getDomainArgs(String progname, String[] args) { - Getopt opt = new Getopt(progname,args,"b:"); + public static final String getDomainArgs(final String progname, final String[] args) { + Getopt opt = new Getopt(progname , args , "b:"); int c; - if ( ((c=opt.getopt())!=-1) && c=='b' ) return opt.getOptarg(); + if ( ((c = opt.getopt()) != -1) && c == 'b' ) return opt.getOptarg(); return getDomain(null); } /** - * returns a "wana be unique" ID to make requests on the bus + * returns a "wana be unique" ID to make requests on the bus. * * @since 1.2.8 * @return returns a string wich is meant to be noisy enough to be unique */ - public String getWBUId() { - return "ID<"+appName+myserial+":"+nextId()+":"+generator.nextInt()+">"; + public final String getWBUId() { + return "ID<" + appName + myserial + ":" + nextId() + ":" + generator.nextInt() + ">"; } private synchronized long nextId() { return current++; } /** - * prints a human readable representation of the list of domains + * prints a human readable representation of the list of domains. * * @since 1.2.9 */ public String domains(String toparse) { - String s=""; + StringBuffer s = new StringBuffer(); Ivy.Domain[] d = parseDomains(toparse); - for (int index=0;index0 ){ + clients.put(c.getClientKey() , c); + setStarting(false); + traceDebug("added " + c + " in clients: " + getClientNames(clients)); + } else { + traceDebug("not adding "+c+" in clients, double connexion detected, removing lowest one"); + try { + c.close(false); + } catch (IOException ioe) { + // TODO + } + } + } } - protected void removeHalf(IvyClient c) { - if (half==null||c==null) return; - synchronized(half){half.remove(c.getClientKey());} - traceDebug("removed "+c+" from half: "+getClientNames(half)); + protected synchronized void addHalf(IvyClient c) { + synchronized(lock){ half.put(c.getClientKey() , c); } + traceDebug("added " + c + " in half: " + getClientNames(half)); } - private boolean shouldIleave(IvyClient ic) { - traceDebug("looking for "+ic+" in "+getClientNames(half)+" and "+getClientNames(clients)); - IvyClient peer=searchPeer(ic); - if (peer==null) return false; - boolean shoulda=peer.compareTo(ic)>0; - traceDebug(ic+" "+ic.toStringExt()+((shoulda)?" must leave ":" must not leave")); - traceDebug(peer+" "+peer.toStringExt()+((!shoulda)?" must leave ":" must not leave")); + protected synchronized void removeHalf(IvyClient c) { + synchronized(lock) { + if (half == null||c == null) return; + half.remove(c.getClientKey()); + } + traceDebug("removed " + c + " from half: " + getClientNames(half)); + } + + /* + private synchronized boolean shouldIleave(IvyClient ic) { + traceDebug("looking for " + ic + " in " + getClientNames(half) + " and " + getClientNames(clients)); + IvyClient peer = searchPeer(ic); + if (peer == null) return false; + boolean shoulda = peer.distanceTo(ic)>0; + traceDebug(ic + " " + ic.toStringExt() + ((shoulda) ? " must leave " : " must not leave")); + traceDebug(peer + " " + peer.toStringExt() + ((!shoulda) ? " must leave " : " must not leave")); return shoulda; } + */ - private IvyClient searchPeer(IvyClient ic) { - IvyClient peer; - for (Enumeration e=half.elements();e.hasMoreElements();) { - peer=(IvyClient)e.nextElement(); - if ((peer!=null)&&(peer.equals(ic))) return peer; - } - synchronized (clients) { - for (Enumeration e=clients.elements();e.hasMoreElements();){ - peer=(IvyClient)e.nextElement(); - if ((peer!=null)&&(peer.equals(ic))) return peer; - } + private synchronized IvyClient searchPeer(IvyClient ic) { + synchronized(lock) { + //for (Enumeration e = half.elements(); e.hasMoreElements(); ) { +// peer = e.nextElement(); +// if ((peer != null)&&(peer.equals(ic))) return peer; + // } + for (IvyClient peer : clients.values()) if ((peer != null)&&(peer.equals(ic))) return peer; } return null; } @@ -830,78 +895,80 @@ public class Ivy implements Runnable { */ public void run() { traceDebug("service thread started"); // THREADDEBUG - Thread thisThread=Thread.currentThread(); - while(thisThread==serverThread){ + Thread thisThread = Thread.currentThread(); + Socket socket = null; + while ( thisThread == serverThread ){ try { - Socket socket = app.accept(); - if ((thisThread!=serverThread)||stopped) break; // early disconnexion - createIvyClient(socket,0,true); // the peer called me + synchronized (this) { + //System.out.println("DEBUG stopped: "+stopped); + if ((thisThread != serverThread)||stopped) break; // early disconnexion + } + synchronized (lockApp) { + socket = app.accept(); // TODO I can't synchronize on (this) in the run + } + synchronized (this) { + if ((thisThread != serverThread)||stopped) break; // early disconnexion + createIvyClient(socket , 0 , true); // the peer called me + } } catch (InterruptedIOException ie) { - // traceDebug("server socket was interrupted. good"); - if (thisThread!=serverThread) break; + // traceDebug("server socket was interrupted. good"); + if (thisThread != serverThread) break; } catch( IOException e ) { - if (serverThread==thisThread) { + if (serverThread == thisThread) { traceDebug("Error IvyServer exception: " + e.getMessage()); - System.out.println("Ivy server socket reader caught an exception " + e.getMessage()); - System.out.println("this is probably a bug in your JVM ! (e.g. blackdown jdk1.1.8 linux)"); - System.exit(0); - } else { - traceDebug("my server socket has been closed"); - } + System.out.println("Ivy server socket reader caught an exception " + e.getMessage()); + System.out.println("this is probably a bug in your JVM ! (e.g. blackdown jdk1.1.8 linux)"); + throw new RuntimeException(); + } else { + traceDebug("my server socket has been closed"); + } } } traceDebug("service thread stopped"); // THREADDEBUG } - protected String getWatcherId() { return watcherId ; } + protected String getAppName() { return appName; } + protected int getAppPort() { return applicationPort; } + protected String getReadyMessage() { return ready_message; } + protected boolean getProtectNewlines() { return doProtectNewlines; } + + protected void setStarting(boolean s) { + synchronized(readyToSend) { + traceDebug("setStarting "+s); + starting = s; + } + } + protected String getWatcherId() { return watcherId; } - protected int getSerial() { return myserial ; } + protected int getSerial() { return myserial; } private void traceDebug(String s){ - if (debug) System.out.println("-->Ivy["+myserial+"]<-- "+s); + if (debug) System.out.println("-->Ivy[" + myserial + "]<-- " + s); } // stuff to guarantee that all the treads have left synchronized void registerThread(Thread t) { sendThreads.addElement(t); } synchronized void unRegisterThread(Thread t) { sendThreads.removeElement(t); } synchronized Thread getOneThread() { - if (sendThreads.size()==0) return null; + if (sendThreads.size() == 0) return null; return (Thread) sendThreads.firstElement(); } // a small private method for debbugging purposes - private String getClientNames(Hashtable t) { - String s = "("; - for (Enumeration e=t.elements();e.hasMoreElements();){ - IvyClient ic = (IvyClient)e.nextElement(); - if (ic!=null) s+=ic.getApplicationName()+","; - } - return s+")"; - } - - private class Domain { - String domainaddr; - int port; - public Domain(String domainaddr,int port) {this.domainaddr=domainaddr;this.port=port;} - public String toString() {return domainaddr+":"+port;} + private String getClientNames(Hashtable t) { + StringBuffer s = new StringBuffer(); + s.append("("); + for (IvyClient ic : t.values() ) if (ic != null) s.append(ic.getApplicationName() + ","); + s.append(")"); + return s.toString(); + } + + private static class Domain { + private String domainaddr; + private int port; + public Domain(String ddomainaddr , int dport) { this.domainaddr = ddomainaddr;this.port = dport; } + public String toString() { return domainaddr + ":" + port; } public String getDomainaddr() { return domainaddr; } public int getPort() { return port; } } - // test. Normally, running java fr.dgac.ivy.Ivy should stop in 2.3 seconds :) - public static void main(String[] args) { - Ivy bus = new Ivy("Test Unitaire","TU ready",null); - try { - bus.start(Ivy.getDomainArgs("IvyTest",args)); - System.out.println("waiting 5 seconds for a coucou"); - System.out.println(((bus.waitForMsg("^coucou",5000))!=null)?"coucou received":"coucou not received"); - System.out.println("waiting 5 seconds for IvyProbe"); - System.out.println(((bus.waitForClient("IVYPROBE",5000))!=null)?"Ivyprobe joined the bus":"nobody came"); - System.out.println("random values: "+bus.getWBUId()+", "+bus.getWBUId()+", "+bus.getWBUId()); - bus.stop(); - } catch (IvyException ie) { - System.out.println("Ivy main test error"); - ie.printStackTrace(); - } - } - } // class Ivy -- cgit v1.1