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