aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjestin2002-06-04 17:02:02 +0000
committerjestin2002-06-04 17:02:02 +0000
commit6a0be62488b406149903a7368cea8df0f1f27d33 (patch)
treeec3073dae7e11b55b3badef001a39fcb5ec6a1e1
parentba4e7756c028129dc0c22650b17ba52ee92c6056 (diff)
downloadivy-java-6a0be62488b406149903a7368cea8df0f1f27d33.zip
ivy-java-6a0be62488b406149903a7368cea8df0f1f27d33.tar.gz
ivy-java-6a0be62488b406149903a7368cea8df0f1f27d33.tar.bz2
ivy-java-6a0be62488b406149903a7368cea8df0f1f27d33.tar.xz
Many major corrections, see changelogs for details.
- Domain bug fix - die semantics OK - non CPU-eating socket listeners cVS: ----------------------------------------------------------------------
-rwxr-xr-xsrc/Ivy.java10
-rwxr-xr-xsrc/IvyClient.java19
-rwxr-xr-xsrc/IvyWatcher.java160
-rw-r--r--src/Makefile26
-rw-r--r--src/Probe.java8
-rwxr-xr-xsrc/TestIvy.java13
-rw-r--r--src/TestIvySwing.java1
7 files changed, 150 insertions, 87 deletions
diff --git a/src/Ivy.java b/src/Ivy.java
index fe11428..f5e32e2 100755
--- a/src/Ivy.java
+++ b/src/Ivy.java
@@ -43,7 +43,7 @@ public class Ivy implements Runnable, IvyApplicationListener {
/**
* the library version
*/
- public static String libVersion ="1.0.9";
+ public static String libVersion ="1.0.10";
private boolean debug;
private static int serial=0; /* an unique ID for each regexp */
@@ -110,10 +110,13 @@ public class Ivy implements Runnable, IvyApplicationListener {
* disconnects from the Ivy bus.
*/
public void stop() {
- if (!ivyRunning) { return; }
+ if (!ivyRunning) {
+ traceDebug("was already stropped ...");
+ return;
+ }
try {
- app.close();
ivyRunning = false;
+ app.close();
watch.stop();
for (int i=0;i<clients.size();i++) {
IvyClient client = (IvyClient)clients.elementAt(i);
@@ -227,6 +230,7 @@ public class Ivy implements Runnable, IvyApplicationListener {
for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ ) {
((IvyApplicationListener)ivyApplicationListenerList.elementAt(i)).disconnect(client);
}
+ stop();
}
/* invokes the application listeners upon death of an Ivy client
diff --git a/src/IvyClient.java b/src/IvyClient.java
index 08864f4..9555d8a 100755
--- a/src/IvyClient.java
+++ b/src/IvyClient.java
@@ -17,9 +17,13 @@ import gnu.regexp.*;
* once ready, a ready message is sent, and then we can send messages,
* die messages, direct messages, add or remove regexps, or quit. A thread is
* created for each remote client.
+ *
+ * CHANGELOG:
+ * 1.0.10:
+ * - removed the timeout bug eating all the CPU resources
*/
-public class IvyClient extends Thread {
+public class IvyClient implements Runnable {
/* the protocol magic numbers */
final static int Bye = 0; /* end of the peer */
@@ -46,6 +50,7 @@ public class IvyClient extends Thread {
private int appPort;
private boolean gardefou=true;
private boolean peerCalling;
+ private Thread client;
IvyClient(Ivy bus, Socket socket,boolean peerCalling) throws IOException {
appName = "Unknown";
@@ -53,7 +58,7 @@ public class IvyClient extends Thread {
this.bus = bus;
this.socket = socket;
this.peerCalling=peerCalling;
- socket.setSoTimeout(100);
+ // CHANGE: socket.setSoTimeout(100);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = socket.getOutputStream();
Hashtable regexps=bus.regexp_out;
@@ -70,7 +75,8 @@ public class IvyClient extends Thread {
send( EndRegexp,0,"");
// spawns a thread to manage the incoming traffic on this
// socket. We should be ready to receive messages now.
- start();
+ client= new Thread(this);
+ client.start();
}
/**
@@ -116,9 +122,10 @@ public class IvyClient extends Thread {
* the thread managing the socket is stopped
*/
void close(String msg) throws IOException {
- traceDebug(msg);
+ traceDebug("(closing) "+msg);
gardefou=false;
- socket.close(); // should I ?
+ client.interrupt();
+ // socket.close(); // should I ?
}
/**
@@ -149,6 +156,8 @@ public class IvyClient extends Thread {
} catch (InterruptedIOException ioe) {
// okay, nothing on the line
// do nothing but loop. It might be a bit resource-eating ...
+ System.out.println("DEBUG IvyClient: I have been interrupted");
+ if (!gardefou) break;
}
}
traceDebug("normally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort());
diff --git a/src/IvyWatcher.java b/src/IvyWatcher.java
index 669287d..e371ea6 100755
--- a/src/IvyWatcher.java
+++ b/src/IvyWatcher.java
@@ -6,6 +6,7 @@ import java.io.*;
import java.util.StringTokenizer;
import gnu.regexp.*;
import java.util.Vector;
+import java.util.Enumeration;
/**
* A private Class for the Ivy rendezvous
@@ -14,18 +15,28 @@ import java.util.Vector;
* @author Yannick Jestin
* @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
*
- * right now, the rendez vous is on a UDP socket. The watcher will answer to
+ * right now, the rendez vous is either an UDP socket or a TCP multicast.
+ * The watcher will answer to
* each peer advertising its arrival on the bus. The intrinsics of Unix are so
* that the broadcast is done using the same socket, which is not a good
* thing.
+ *
+ * CHANGELOG:
+ * 1.0.10:
+ * - isInDomain() is wrong in multicast. I've removed it
+ * - there was a remanence effect in the datagrampacket buffer. I clean it up after each message
+ * - cleaned up the getDomain() and getPort() code
+ * - close message sends an interruption on all threads for a clean exit
+ * - removed the timeout bug eating all the CPU resources
+ * - now handles a Vector of broadcast listeners
*/
class IvyWatcher implements Runnable {
private static boolean debug = (System.getProperty("IVY_DEBUG")!=null);
- private Vector domainaddrList;
+ //private Vector domainaddrList;
private boolean watcherrunning = false;
private boolean isMulticastAddress = false;
- private Thread broadcastListener ;
+ private Vector broadcastListener ;
private Ivy bus; /* master bus controler */
private DatagramSocket broadcast; /* supervision socket */
// it can also be a MulticastSocket, which inherits from the previous
@@ -35,7 +46,7 @@ class IvyWatcher implements Runnable {
*/
IvyWatcher(Ivy bus) throws IvyException {
this.bus = bus;
- domainaddrList = new Vector();
+ //domainaddrList = new Vector();
}
/**
@@ -54,11 +65,14 @@ class IvyWatcher implements Runnable {
while( watcherrunning && bus.ivyRunning ) try {
broadcast.receive(packet);
String msg = new String(packet.getData()) ;
+ // clean up the buffer after each message
+ for (int i=0;i<buf.length;i++) { buf[i]=0; }
InetAddress remotehost = packet.getAddress();
traceDebug("BUSWATCHER Receive Broadcast from "+
remotehost.getHostName()+":"+packet.getPort());
- // check if remoteaddr is in our broadcast domain list otherwise we ignore the broadcast
- if ( !isInDomain( remotehost ) ) continue;
+ // we used to check if remoteaddr is in our broadcast domain list otherwise we
+ // ignore the broadcast
+ // if ( !isInDomain( remotehost ) ) continue;
StringTokenizer st = new StringTokenizer(msg);
if ( !st.hasMoreTokens()) {
System.err.println("Bad format "+msg);
@@ -89,36 +103,33 @@ class IvyWatcher implements Runnable {
}
} catch (java.io.InterruptedIOException jii ){
if (!watcherrunning) break;
+ System.out.println("DEBUG IvyClient: I have been interrupted");
} catch (java.io.IOException ioe ){
System.err.println("IvyWatcher IOException "+ ioe.getMessage() );
}
- broadcast.close();
- traceDebug("broadcast listener normal shutdown");
+ stop();
} // while
/**
* stops the thread waiting on the broadcast socket
*/
- void stop() { watcherrunning=false; }
-
- private void sendBroadcast(String data, String net) throws IvyException {
- try {
- // simple trick to expand to 255 (Alex Bustico)
- net += ".255.255.255";
- RE exp = new RE( "^(\\d+\\.\\d+\\.\\d+\\.\\d+).*");
- net = exp.substitute( net , "$1" );
- } catch ( REException e ){
- throw new IvyException("Bad broascat addr");
+ void stop() {
+ traceDebug("broadcast listener normal shutdown");
+ watcherrunning=false;
+ for (Enumeration e = broadcastListener.elements();e.hasMoreElements();) {
+ Thread t = (Thread) e.nextElement();
+ t.interrupt();
}
+ }
+
+ private static void sendBroadcast(String data, String domain, int port) throws IvyException {
+ MulticastSocket send ;
try {
- InetAddress iaddr = InetAddress.getByName(net);
- domainaddrList.addElement(iaddr);
- DatagramPacket packet = new DatagramPacket(
- data.getBytes(),
- data.length(),
- iaddr,
- broadcast.getLocalPort() );
- broadcast.send(packet);
+ InetAddress group = InetAddress.getByName(domain);
+ send = new MulticastSocket(port);
+ if (group.isMulticastAddress()) { ((MulticastSocket)send).joinGroup(group); }
+ DatagramPacket packet = new DatagramPacket( data.getBytes(), data.length(), group, port );
+ send.send(packet);
} catch ( UnknownHostException e ) {
throw new IvyException("Broadcast sent on unknown network "+
e.getMessage());
@@ -127,46 +138,47 @@ class IvyWatcher implements Runnable {
}
}
- void start(String domain) throws IvyException {
- String domainaddr;
- // parse Domain to get port number
- int port;
- int sep_index = domain.lastIndexOf( ":" );
- if ( sep_index == -1 ) {
- port = bus.DEFAULT_PORT;
- domainaddr = domain;
- } else {
- port = Integer.parseInt( domain.substring( sep_index +1 ));
- domainaddr = domain.substring(0,sep_index);
- }
- // Handling of multicast address
- try {
- InetAddress group = InetAddress.getByName(domainaddr);
- if (group.isMulticastAddress()) {
- isMulticastAddress = true;
- broadcast = new MulticastSocket(port ); // create the UDP socket
- ((MulticastSocket)broadcast).joinGroup(group);
- } else {
- broadcast = new MulticastSocket(port ); // create the UDP socket
+ void start(String net) throws IvyException {
+ String hello = bus.PROCOCOLVERSION + " " + bus.applicationPort + "\n";
+ StringTokenizer st = new StringTokenizer(net,",");
+ broadcastListener = new Vector();
+ while ( st.hasMoreTokens()) {
+ String s = st.nextToken() ;
+ String domainaddr=getDomain(s);
+ int port=getPort(s);
+ // System.out.println("Domaine: "+domainaddr+" : "+port);
+ try {
+ InetAddress group = InetAddress.getByName(domainaddr);
+ broadcast = new MulticastSocket(port);
+ // Handling of multicast address
+ if (group.isMulticastAddress()) {
+ isMulticastAddress = true;
+ ((MulticastSocket)broadcast).joinGroup(group);
+ }
+ } catch ( IOException e ) {
+ throw new IvyException("IvyWatcher I/O error" + e );
+ }
+ /*
+ try {
+ broadcast.setSoTimeout(100);
+ } catch ( java.net.SocketException jns ) {
+ throw new IvyException("IvyWatcher setSoTimeout error" + jns.getMessage() );
}
- } catch ( IOException e ) {
- throw new IvyException("IvyWatcher I/O error" + e );
- }
- try {
- broadcast.setSoTimeout(100);
- } catch ( java.net.SocketException jns ) {
- throw new IvyException("IvyWatcher setSoTimeout error" + jns.getMessage() );
+ */
+ // starts a Thread listening on the socket
+ watcherrunning=true;
+ Thread t = new Thread(this);
+ broadcastListener.addElement(t);
+ t.start();
+ // notifies our arrival on each domain: protocol version + port
+ sendBroadcast(hello,domainaddr,port);
}
- // starts a Thread listening on the socket
- watcherrunning=true;
- broadcastListener = new Thread(this);
- broadcastListener.start();
- // notifies our arrival on each domain: protocol version + port
- String hello = bus.PROCOCOLVERSION + " " + bus.applicationPort + "\n";
- StringTokenizer st = new StringTokenizer(domainaddr," \t:,");
- while ( st.hasMoreTokens()) { sendBroadcast( hello, st.nextToken() ); }
}
+ /*
+ * TODO
+ * deprecated since we use Multicast. How to check when we are in UDP
+ * broadcast ?
private boolean isInDomain( InetAddress host ){
byte rem_addr[] = host.getAddress();
for ( int i = 0 ; i < domainaddrList.size(); i++ ) {
@@ -182,6 +194,30 @@ class IvyWatcher implements Runnable {
traceDebug( "host " + host + " Not in domain\n" );
return false;
}
+ */
+
+ private static String getDomain(String net) {
+ int sep_index = net.lastIndexOf( ":" );
+ if ( sep_index != -1 ) { net = net.substring(0,sep_index); }
+ try {
+ net += ".255.255.255";
+ RE exp = new RE( "^(\\d+\\.\\d+\\.\\d+\\.\\d+).*");
+ net = exp.substitute( net , "$1" );
+ } catch ( REException e ){
+ System.out.println("Bad broascat addr " + net);
+ return null;
+ }
+ //System.out.println("net: "+net);
+ return net;
+ }
+
+ private static int getPort(String net) {
+ int sep_index = net.lastIndexOf( ":" );
+ int port= ( sep_index == -1 ) ? Ivy.DEFAULT_PORT :Integer.parseInt( net.substring( sep_index +1 ));
+ // System.out.println("net: ["+net+"]\nsep_index: "+sep_index+"\nport: "+port);
+ return port;
+ }
+
private void traceDebug(String s){
if (debug) System.out.println("-->ivywatcher<-- "+s);
diff --git a/src/Makefile b/src/Makefile
index fbd2ffb..c5e5060 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,30 +1,30 @@
-# JAVAJAR = /usr/lib/j2re1.3/lib/rt.jar
-#CLASSPATH = -classpath $(JAVAJAR)
-JAVACOPTS = -d . -deprecation $(CLASSPATH)
+# Be sure to set this before compiling ...
+# JIKESPATH = /usr/lib/j2re1.3/lib/rt.jar:/usr/share/java/repository
+JAVACOPTS = -d . -deprecation
+.SUFFIXES: .java .class
SRCS = *.java
+ OBJS = $(SRCS:.java=.class)
JAR = ../lib/Ivy.jar
- VER = 1.0.9
+ VER = 1.0.10
DIST = ../lib/ivy-java-$(VER).jar
JAVAC = jikes
-# JAVAC = javac
+ #JAVAC = javac
DOCS = ../doc/html/api
+.java.class:
+ $(JAVAC) $<
+
ivy-java:
$(JAVAC) $(JAVACOPTS) $(SRCS)
-all:
- $(JAVAC) $(JAVACOPTS) $(SRCS)
+all: $(OBJS)
clean:
- /bin/rm -f -- *class *~ *.bak $(JAR)
- ctags $(SRCS)
+ /bin/rm -f -- $(OBJS) *~ *.bak $(JAR)
-jar:
- fastjar cvfm $(JAR) ../manifest fr
-
dist:
cd ..
- fastjar cvfm $(DIST) ../manifest fr src debian redhat doc Makefile manifest TODO
+ fastjar cvfm $(DIST) ../manifest fr gnu
docs:
rm -fR $(DOCS)/*html
diff --git a/src/Probe.java b/src/Probe.java
index 7719e73..be2275e 100644
--- a/src/Probe.java
+++ b/src/Probe.java
@@ -8,7 +8,12 @@ import gnu.getopt.Getopt;
* @see fr.dgac.ivy.TestIvySwing
* @author Yannick Jestin
* @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
- * TODO BUG ! Should exit on end of user input
+ *
+ *
+ * Changelog:
+ * 1.0.10
+ * Should exit on end of user input
+ * Should handle multiple domains - it was a IvyWatcher problem -
*/
class Probe implements IvyApplicationListener, IvyMessageListener {
@@ -82,6 +87,7 @@ class Probe implements IvyApplicationListener, IvyMessageListener {
public void die(IvyClient client, int id) {
looping=false;
System.out.println("received die msg from " + client.getApplicationName() );
+ System.exit(0);
}
public void directMessage(IvyClient client, int id, String arg) {
diff --git a/src/TestIvy.java b/src/TestIvy.java
index 27a6d08..802f982 100755
--- a/src/TestIvy.java
+++ b/src/TestIvy.java
@@ -12,6 +12,10 @@ import java.awt.event.* ;
* @author François-Régis Colin
* @author Yannick Jestin
* @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a>
+ *
+ * CHANGELOG
+ * 1.0.10:
+ * - System.exit on bus die
*/
class TestIvy extends Panel implements IvyApplicationListener {
@@ -41,14 +45,16 @@ class TestIvy extends Panel implements IvyApplicationListener {
tfSend.addActionListener(new SENDCB());
p.add(tfSend,BorderLayout.CENTER);
add(p,BorderLayout.SOUTH);
- bus = new Ivy("JAVA TESTBUS","Testbus is ready",this);
+ bus = new Ivy("JAVATESTBUS","Testbus is ready",this);
bus.start(null);
append( "Ivy Domain: "+ bus.getDomain(null) );
}
+ public static Frame f;
+
public static void main(String[] args) throws IvyException {
TestIvy tb = new TestIvy();
- Frame f = new Frame("TestIvy");
+ f = new Frame("TestIvy");
f.addWindowListener( tb.new WCCB(f,tb)) ;
f.add(tb, BorderLayout.CENTER);
f.pack();
@@ -63,7 +69,8 @@ class TestIvy extends Panel implements IvyApplicationListener {
append(client.getApplicationName() + " disconnected " );
}
public void die(IvyClient client, int id) {
- append(client.getApplicationName() + " die "+ id );
+ f.dispose();
+ System.exit(0);
}
public void directMessage(IvyClient client, int id, String arg) {
append(client.getApplicationName() + " direct Message "+ id + arg );
diff --git a/src/TestIvySwing.java b/src/TestIvySwing.java
index f3f2ae6..ed61741 100644
--- a/src/TestIvySwing.java
+++ b/src/TestIvySwing.java
@@ -43,6 +43,7 @@ class TestIvySwing extends JPanel implements IvyApplicationListener {
"127.255.255.255:2010",
"10.192.36:3110",
"10.0.0:54321",
+ "228.1.2.4:4567",
};
private static java.util.Vector domainList;