From f150fe3fa7cc90fa7abd9bd64e4b5ccd6646d5a7 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 7 Nov 2002 18:01:05 +0000 Subject: backport: MarshalledObject.java (equals): Check hashcode first. Merge Orp RMI patches from Wu Gansha * java/rmi/MarshalledObject.java (equals): Check hashcode first. * java/rmi/server/RMIClassLoader.java (MyClassLoader): Create/Use annotation. (loadClass): Take String as codebases. (getClassAnnotation): Use MyClassLoader annotations. * java/rmi/server/UnicastRemoteObject.java (UnicastRemoteObject): call exportObject(this). * gnu/java/rmi/RMIMarshalledObjectOutputStream.java (RMIMarshalledObjectOutputStream): set locBytesStream and locStream. (setAnnotation): Don't set locBytesStream and locStream. (replaceObject): Removed. (flush): Don't test locStream. (getLocBytes): LikeWise. * gnu/java/rmi/dgc/DGCImpl.java: extends UnicastServerRef. (leaseCache): New field. (dirty): Use leaseCache. (LeaseRecord): New inner class. * gnu/java/rmi/registry/RegistryImpl.java (RegistryImpl): Don't explicitly call exportObject(). * gnu/java/rmi/registry/RegistryImpl_Stub.java: set useNewInvoke to false to communicate with Sun JDK130. * gnu/java/rmi/server/ConnectionRunnerPool.java: Add CPU comment. * gnu/java/rmi/server/RMIObjectInputStream.java (UnicastConnectionManager): Removed field. * gnu/java/rmi/server/RMIObjectOutputStream.java (replaceObject): Use UnicastServer.getExportedRef(). * gnu/java/rmi/server/UnicastConnection.java (reviveTime): New field. (expireTime): Likewise. (CONNECTION_TIMEOUT): Likewise. (disconnect): Call sock.close(). (isExpired): New method. (resetTime): Likewise. (run): Use do while loop and catch Exception for discardConnection(). * gnu/java/rmi/server/UnicastConnectionManager.java: Pool connections. * gnu/java/rmi/server/UnicastRef.java: Lots of changes. * gnu/java/rmi/server/UnicastRemoteCall.java: Lots of changes. * gnu/java/rmi/server/UnicastServer.java (refcache): New field. (exportObject): Use refcache. (unexportObject): Likewise. (getExportedRef): New method. * gnu/java/rmi/server/UnicastServerRef.java (UnicastServerRef): New constructor. (exportObject): Save manager.serverobj. (getStub): New method. From-SVN: r58900 --- .../java/rmi/server/UnicastConnectionManager.java | 176 +++++++++++++++++++-- 1 file changed, 160 insertions(+), 16 deletions(-) (limited to 'libjava/gnu/java/rmi/server/UnicastConnectionManager.java') diff --git a/libjava/gnu/java/rmi/server/UnicastConnectionManager.java b/libjava/gnu/java/rmi/server/UnicastConnectionManager.java index 64fecdce2a0..d54dcf1d4cd 100644 --- a/libjava/gnu/java/rmi/server/UnicastConnectionManager.java +++ b/libjava/gnu/java/rmi/server/UnicastConnectionManager.java @@ -1,5 +1,5 @@ /* - Copyright (c) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Copyright (c) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -41,18 +41,25 @@ import java.rmi.server.RMISocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.RMIClientSocketFactory; import java.rmi.RemoteException; -import gnu.java.rmi.server.UnicastConnection; -import java.util.Hashtable; -import java.net.Socket; -import java.net.ServerSocket; import java.io.IOException; import java.io.ObjectOutput; import java.io.ObjectInput; +import java.io.DataInputStream; import java.lang.Thread; import java.lang.Runnable; import java.net.InetAddress; +import java.net.Socket; +import java.net.ServerSocket; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; + +import gnu.java.rmi.server.UnicastConnection; + public class UnicastConnectionManager implements Runnable, ProtocolConstants { @@ -60,15 +67,33 @@ private static String localhost; // use different maps for server/client type UnicastConnectionManager private static Hashtable servers = new Hashtable(); private static Hashtable clients = new Hashtable(); +private ArrayList connections; //client connection pool // make serverThread volatile for poll private volatile Thread serverThread; private ServerSocket ssock; String serverName; int serverPort; + +static private Thread scavenger; + +// If client and server are in the same VM, serverobj represents server +Object serverobj; + +private static RMISocketFactory defaultSocketFactory = RMISocketFactory.getSocketFactory(); private RMIServerSocketFactory serverFactory; private RMIClientSocketFactory clientFactory; +// The following is for debug +private static int ncsock = 0; //count of client socket +private static int nssock = 0; //count of server socket +private static int ncmanager = 0; //count of client manager +private static int nsmanager = 0; //count of server manager + +private static final boolean debug = false; + +private static final Object GLOBAL_LOCK = new Object(); + static { try { //Use host address instead of host name to avoid name resolving issues @@ -78,16 +103,73 @@ static { catch (UnknownHostException _) { localhost = "localhost"; } + + +} + +//Only one scavenger thread running globally +private static void startScavenger(){ + scavenger = new Thread(new Runnable(){ + public void run(){ + if (debug) System.out.println("************* start scavenger."); + boolean liveon = true; + while (liveon){ + // Sleep for the expire timeout + try{ + Thread.sleep(UnicastConnection.CONNECTION_TIMEOUT); + }catch(InterruptedException _ie){ + break; + } + liveon = false; + // Scavenge all clients' connections that're expired + Iterator iter = clients.values().iterator(); + long l = System.currentTimeMillis(); + try{ + while(iter.hasNext()){ + UnicastConnectionManager man = (UnicastConnectionManager)iter.next(); + ArrayList conns = man.connections; + synchronized(conns) { // is the lock a little coarser? + for (int last = conns.size() - 1; + last >= 0; + --last) + { + UnicastConnection conn = (UnicastConnection)conns.get(last); + if (UnicastConnection.isExpired(conn, l)){ + conns.remove(last); + conn.disconnect(); + conn = null; + }else + liveon = true; //there're still live connections + } + } + } + }catch(ConcurrentModificationException cme) { + // handle it lazily + liveon = true; + } + } + scavenger = null; + if (debug) System.out.println("************* exit scavenger."); + } + }); + scavenger.start(); } +/** + * Client UnicastConnectionManager constructor + */ private UnicastConnectionManager(String host, int port, RMIClientSocketFactory csf) { ssock = null; serverName = host; serverPort = port; serverFactory = null; clientFactory = csf; + connections = new ArrayList(); } +/** + * Server UnicastConnectionManager constructor + */ private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) { try { ssock = ssf.createServerSocket(port); @@ -115,7 +197,7 @@ private UnicastConnectionManager(int port, RMIServerSocketFactory ssf) { public static synchronized UnicastConnectionManager getInstance(String host, int port, RMIClientSocketFactory csf) { //System.out.println("getInstance: " + host + "," + port + "," + csf); if (csf == null) { - csf = RMISocketFactory.getSocketFactory(); + csf = defaultSocketFactory; } // change host name to host address to avoid name resolving issues try{ @@ -126,7 +208,17 @@ public static synchronized UnicastConnectionManager getInstance(String host, int UnicastConnectionManager man = (UnicastConnectionManager)clients.get(key); if (man == null) { man = new UnicastConnectionManager(host, port, csf); + if (debug) { + ncmanager++; + System.out.println("\n\n ====== " + ncmanager + " client managers.\n\n"); + } clients.put(key, man); + + // Detect if client and server are in the same VM, i.e., their keys are equal + UnicastConnectionManager svrman = (UnicastConnectionManager)servers.get(key); + if(svrman != null){ // server and client are in the same VM + man.serverobj = svrman.serverobj; + } } return (man); } @@ -138,12 +230,16 @@ public static synchronized UnicastConnectionManager getInstance(String host, int public static synchronized UnicastConnectionManager getInstance(int port, RMIServerSocketFactory ssf) { //System.out.println("getInstance: " + port + "," + ssf); if (ssf == null) { - ssf = RMISocketFactory.getSocketFactory(); + ssf = defaultSocketFactory; } TripleKey key = new TripleKey(localhost, port, ssf); UnicastConnectionManager man = (UnicastConnectionManager)servers.get(key); if (man == null) { man = new UnicastConnectionManager(port, ssf); + if (debug) { + nsmanager++; + System.out.println("\n\n ****** " + nsmanager + " server managers.\n\n"); + } // The provided port might not be the set port. key.port = man.serverPort; servers.put(key, man); @@ -168,9 +264,14 @@ public UnicastConnection getConnection() throws IOException { */ private UnicastConnection getServerConnection() throws IOException { Socket sock = ssock.accept(); + sock.setTcpNoDelay(true); //?? UnicastConnection conn = new UnicastConnection(this, sock); conn.acceptConnection(); -//System.out.println("Server connection " + conn); + if (debug){ + nssock++; + System.out.println("\n\n ****** " + nssock + " server socks.\n\n"); + } + //System.out.println("Server connection " + sock); return (conn); } @@ -178,10 +279,38 @@ private UnicastConnection getServerConnection() throws IOException { * Make a conection from this client to the server. */ private UnicastConnection getClientConnection() throws IOException { + ArrayList conns = connections; + UnicastConnection conn; + + synchronized(conns) { + int nconn = conns.size() - 1; + + // if there're free connections in connection pool + if(nconn >= 0) { + conn = (UnicastConnection)conns.get(nconn); + //Should we check if conn is alive using Ping?? + conns.remove(nconn); + + // Check if the connection is already expired + long l = System.currentTimeMillis(); + if (!UnicastConnection.isExpired(conn, l)){ + return conn; + }else { + conn.disconnect(); + conn = null; + } + } + } + Socket sock = clientFactory.createSocket(serverName, serverPort); - UnicastConnection conn = new UnicastConnection(this, sock); + conn = new UnicastConnection(this, sock); conn.makeConnection(DEFAULT_PROTOCOL); -//System.out.println("Client connection " + conn); + + if (debug) { + ncsock++; + System.out.println("\n\n ====== " + ncsock + " client socks.\n\n"); + } + return (conn); } @@ -191,7 +320,19 @@ private UnicastConnection getClientConnection() throws IOException { */ public void discardConnection(UnicastConnection conn) { //System.out.println("Discarding connection " + conn); + //conn.disconnect(); + if (ssock != null) //server connection conn.disconnect(); + else { + // To client connection, we'd like to return back to pool + UnicastConnection.resetTime(conn); + //Ensure there're only one scavenger globally + synchronized(GLOBAL_LOCK) { + connections.add(conn); //borrow this lock to garantee thread safety + if (scavenger == null) + startScavenger(); + } + } } /** @@ -204,6 +345,8 @@ public void startServer() { return; } serverThread = new Thread(this); + // The following is not necessary when java.lang.Thread's constructor do this. + // serverThread.setContextClassLoader(Thread.currentThread().getContextClassLoader()); } serverThread.start(); } @@ -231,11 +374,11 @@ public void run() { //System.out.println("Waiting for connection on " + serverPort); UnicastConnection conn = getServerConnection(); // use a thread pool to improve performance - // (new Thread(conn)).start(); - ConnectionRunnerPool.dispatchConnection(conn); + //ConnectionRunnerPool.dispatchConnection(conn); + (new Thread(conn)).start(); } catch (Exception e) { - // e.printStackTrace(); + e.printStackTrace(); } } } @@ -254,8 +397,9 @@ void write(ObjectOutput out) throws IOException { static UnicastConnectionManager read(ObjectInput in) throws IOException { String host = in.readUTF(); int port = in.readInt(); - RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory; - return (getInstance(host, port, csf)); + //RMIClientSocketFactory csf = ((RMIObjectInputStream)in).manager.clientFactory; + //return (getInstance(host, port, csf)); + return (getInstance(host, port, null)); } } @@ -288,7 +432,7 @@ public boolean equals(Object obj) { TripleKey other = (TripleKey)obj; if (this.host.equals(other.host) && this.other == other.other && - (this.port == other.port || this.port == 0 || other.port == 0)) { + (this.port == other.port /* || this.port == 0 || other.port == 0*/)) { return (true); } } -- cgit v1.2.3