diff options
Diffstat (limited to 'src/IvyWatcher.java')
-rwxr-xr-x | src/IvyWatcher.java | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/src/IvyWatcher.java b/src/IvyWatcher.java index 3281079..5a47da3 100755 --- a/src/IvyWatcher.java +++ b/src/IvyWatcher.java @@ -2,7 +2,7 @@ * IvyWatcher, A private Class for the Ivy rendezvous * * @author Yannick Jestin - * @author François-Régis Colin + * @author Francois-Regis Colin * @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a> * * (C) CENA @@ -14,6 +14,13 @@ * thing. * * CHANGELOG: + * 1.2.14 + * - tries to fix a lock on accept() by becoming a Thread instead of + * runnalbe (see tests/test2) + * - removed unread field (domainaddr, e.g.) + * - throws RuntimeException instead of System.exit(), allows code reuse + * - switch from gnu regexp (deprecated) to the built in java regexp + * - add generic types to declarations * 1.2.13: * - TCP_NO_DELAY to disable Nagle's algorithm * - private static ?! pour already present ... @@ -73,17 +80,14 @@ package fr.dgac.ivy ; import java.lang.Thread; import java.net.*; import java.io.*; -import org.apache.regexp.*; import java.util.Hashtable; +import java.util.regex.*; -class IvyWatcher implements Runnable { +class IvyWatcher extends Thread { private static boolean debug = (System.getProperty("IVY_DEBUG")!=null); - private boolean isMulticastAddress = false; private boolean alreadyIgnored = false; private Ivy bus; /* master bus controler */ private DatagramSocket broadcast; /* supervision socket */ - private InetAddress localhost,loopback; - private String domainaddr; private int port; private volatile Thread listenThread = null; private InetAddress group; @@ -91,6 +95,8 @@ class IvyWatcher implements Runnable { private int myserial=serial++; private String busWatcherId = null; + private static Pattern recoucou, numbersPoint, exp; + /** * creates an Ivy watcher * @param bus the bus @@ -98,7 +104,6 @@ class IvyWatcher implements Runnable { */ IvyWatcher(Ivy bus,String domainaddr,int port) throws IvyException { this.bus = bus; - this.domainaddr=domainaddr; this.port=port; busWatcherId=bus.getWatcherId(); listenThread = new Thread(this); @@ -106,13 +111,8 @@ class IvyWatcher implements Runnable { try { group = InetAddress.getByName(domainaddr); broadcast = new MulticastSocket(port); - if (group.isMulticastAddress()) { - isMulticastAddress = true; - ((MulticastSocket)broadcast).joinGroup(group); - } + if (group.isMulticastAddress()) ((MulticastSocket)broadcast).joinGroup(group); broadcast.setSoTimeout(Ivy.TIMEOUTLENGTH); - localhost=InetAddress.getLocalHost(); - loopback=InetAddress.getByName(null); } catch ( UnknownHostException uhe ) { } catch ( IOException e ) { throw new IvyException("IvyWatcher I/O error" + e ); @@ -134,35 +134,35 @@ class IvyWatcher implements Runnable { byte buf[] = new byte[256]; DatagramPacket packet=new DatagramPacket(buf,buf.length); broadcast.receive(packet); + bus.setStarting(true); // someone's coming if (listenThread!=thisThread) break; // I was summoned to leave during the receive String msg = new String(buf,0,packet.getLength()); String remotehostname=null; try { remotehost = packet.getAddress(); remotehostname = remotehost.getHostName(); - RE re = new RE("([0-9]*) ([0-9]*)"); - if (!(re.match(msg))) { - System.err.println("Ignoring bad format broadcast from "+ - remotehostname+":"+packet.getPort()); + Matcher m = recoucou.matcher(msg); + if (!m.matches()) { + System.err.println("Ignoring bad format broadcast from "+ remotehostname+":"+packet.getPort()); continue; } - int version = Integer.parseInt(re.getParen(1)); + int version = Integer.parseInt(m.group(1)); if ( version < Ivy.PROTOCOLMINIMUM ) { System.err.println("Ignoring bad format broadcast from "+ remotehostname+":"+packet.getPort() +" protocol version "+remotehost+" we need "+Ivy.PROTOCOLMINIMUM+" minimum"); continue; } - remotePort = Integer.parseInt(re.getParen(2)); - if (bus.applicationPort==remotePort) { // if (same port number) - RE reId = new RE("([0-9]*) ([0-9]*) ([^ ]*) (.*)"); - if (reId.match(msg)&&(busWatcherId!=null)) { - traceDebug("there's an appId: "+reId.getParen(3)); - String otherId=reId.getParen(3); - String otherName=reId.getParen(4); + remotePort = Integer.parseInt(m.group(2)); + if (bus.getAppPort()==remotePort) { // if (same port number) + if (busWatcherId!=null) { + traceDebug("there's an appId: "+m.group(3)); + String otherId=m.group(3); + String otherName=m.group(4); if (busWatcherId.compareTo(otherId)==0) { // same port #, same bus Id, It's me, I'm outta here traceDebug("ignoring my own broadcast"); + bus.setStarting(false); continue; } else { // same port #, different bus Id, it's another agent @@ -199,9 +199,6 @@ class IvyWatcher implements Runnable { } else { traceDebug("there is already a request originating from " + remotehost + ":" + remotePort); } - } catch (RESyntaxException ree) { - ree.printStackTrace(); - System.exit(-1); } catch (NumberFormatException nfe) { System.err.println("Ignoring bad format broadcast from "+remotehostname); continue; @@ -225,15 +222,23 @@ class IvyWatcher implements Runnable { traceDebug("Thread stopped"); // THREADDEBUG } + @Override public void interrupt(){ + super.interrupt(); + broadcast.close(); + } + /** * stops the thread waiting on the broadcast socket */ - synchronized void stop() { + synchronized void doStop() { traceDebug("begining stopping"); + bus.setStarting(true); Thread t = listenThread; listenThread=null; + interrupt(); broadcast.close(); if (t!=null) { t.interrupt(); } // it might not even have been created + bus.setStarting(false); traceDebug("stopped"); } @@ -242,8 +247,10 @@ class IvyWatcher implements Runnable { // domain. DatagramPacket packet; String data; - public PacketSender(String data) { + Ivy bus; + public PacketSender(String data, Ivy b) { this.data=data; + bus = b; packet=new DatagramPacket(data.getBytes(),data.length(),group,port); new Thread((PacketSender.this)).start(); } @@ -263,15 +270,17 @@ class IvyWatcher implements Runnable { e.printStackTrace(); } } + try { Thread.sleep(100); } catch (InterruptedException ie ){ } + bus.setStarting(false); // one of the senders has finished its work, plus extra time traceDebug("PacketSender thread stopped"); // THREADDEBUG } } - synchronized void start() throws IvyException { - // String hello = Ivy.PROTOCOLVERSION + " " + bus.applicationPort + "\n"; - String hello = Ivy.PROTOCOLVERSION + " " + bus.applicationPort + " "+busWatcherId+" "+bus.selfIvyClient.getApplicationName()+"\n"; + synchronized void doStart() throws IvyException { + // String hello = Ivy.PROTOCOLVERSION + " " + bus.getAppPort() + "\n"; + String hello = Ivy.PROTOCOLVERSION + " " + bus.getAppPort() + " "+busWatcherId+" "+bus.getSelfIvyClient().getApplicationName()+"\n"; if (broadcast==null) throw new IvyException("IvyWatcher PacketSender null broadcast address"); - new PacketSender(hello); // notifies our arrival on each domain: protocol version + port + new PacketSender(hello,bus); // notifies our arrival on each domain: protocol version + port listenThread.start(); } @@ -284,13 +293,13 @@ class IvyWatcher implements Runnable { * regoes static ... */ //private static Hashtable alreadySocks=new Hashtable(); - private Hashtable alreadySocks=new Hashtable(); + private Hashtable<String,Integer> alreadySocks=new Hashtable<String,Integer>(); private synchronized boolean alreadyBroadcasted(String s,int port) { // System.out.println("DEBUUUUUUUG " + s+ ":" + port); if (s==null) return false; - Integer i = (Integer)alreadySocks.get(s); - if (((i!=null)&&(i.compareTo(new Integer(port)))==0)) return true; - alreadySocks.put(s,new Integer(port)); + Integer i = alreadySocks.get(s); + if (((i!=null)&&(i.compareTo(port))==0)) return true; + alreadySocks.put(s,port); return false; } @@ -322,22 +331,22 @@ class IvyWatcher implements Runnable { int sep_index = net.lastIndexOf( ":" ); if ( sep_index != -1 ) { net = net.substring(0,sep_index); } try { - RE numbersPoint = new RE("([0-9]|\\.)+"); - if (!numbersPoint.match(net)) { + Matcher m = numbersPoint.matcher(net); + if (!m.matches()) { // traceDebug("should only have numbers and point ? I won't add anything... " + net); return "127.255.255.255"; // return net; } net += ".255.255.255"; - RE exp = new RE( "^(\\d+\\.\\d+\\.\\d+\\.\\d+).*"); - if (!exp.match(net)) { + Matcher mm= exp.matcher(net); + if (!mm.matches()) { System.out.println("Bad broascat addr " + net); throw new IvyException("bad broadcast addr"); } - net=exp.getParen(1); - } catch ( RESyntaxException e ){ - System.out.println(e); - System.exit(0); + net=mm.group(1); + } catch ( PatternSyntaxException e ){ + e.printStackTrace(); + throw new RuntimeException(); } //System.out.println("next domain: "+net); return net; @@ -354,5 +363,17 @@ class IvyWatcher implements Runnable { private void traceDebug(String s){ if (debug) System.out.println("-->IvyWatcher["+myserial+","+bus.getSerial()+"]<-- "+s); } + + static { + try { + numbersPoint = Pattern.compile("([0-9]|\\.)+"); + recoucou = Pattern.compile("([0-9]+) ([0-9]+) ([^ ]*) (.*)",Pattern.DOTALL); + exp = Pattern.compile( "^(\\d+\\.\\d+\\.\\d+\\.\\d+).*"); + } catch (PatternSyntaxException res) { + res.printStackTrace(); + System.out.println("Regular Expression bug in Ivy source code ... bailing out"); + throw new RuntimeException(); + } + } } // class IvyWatcher |