diff options
author | Mark Wielaard <mark@klomp.org> | 2002-11-07 18:01:05 +0000 |
---|---|---|
committer | Mark Wielaard <mark@gcc.gnu.org> | 2002-11-07 18:01:05 +0000 |
commit | f150fe3fa7cc90fa7abd9bd64e4b5ccd6646d5a7 (patch) | |
tree | dfca54cc19c9efec9125010fd9fcb7030f24bea4 /libjava/gnu/java | |
parent | 396a80436c733527118877c95bfec72e38401eeb (diff) | |
download | gcc-f150fe3fa7cc90fa7abd9bd64e4b5ccd6646d5a7.zip gcc-f150fe3fa7cc90fa7abd9bd64e4b5ccd6646d5a7.tar.gz gcc-f150fe3fa7cc90fa7abd9bd64e4b5ccd6646d5a7.tar.bz2 |
backport: MarshalledObject.java (equals): Check hashcode first.
Merge Orp RMI patches from Wu Gansha <gansha.wu@intel.com>
* 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
Diffstat (limited to 'libjava/gnu/java')
-rw-r--r-- | libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java | 28 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/dgc/DGCImpl.java | 63 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/registry/RegistryImpl.java | 3 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java | 2 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/ConnectionRunnerPool.java | 1 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/RMIObjectInputStream.java | 33 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/RMIObjectOutputStream.java | 9 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastConnection.java | 33 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastConnectionManager.java | 176 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastRef.java | 76 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastRemoteCall.java | 122 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastServer.java | 16 | ||||
-rw-r--r-- | libjava/gnu/java/rmi/server/UnicastServerRef.java | 20 |
13 files changed, 458 insertions, 124 deletions
diff --git a/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java b/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java index 6639291..a721fc4 100644 --- a/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java +++ b/libjava/gnu/java/rmi/RMIMarshalledObjectOutputStream.java @@ -61,42 +61,22 @@ public class RMIMarshalledObjectOutputStream extends RMIObjectOutputStream public RMIMarshalledObjectOutputStream(OutputStream objStream) throws IOException { super(objStream); + locBytesStream = new ByteArrayOutputStream(256); + locStream = new ObjectOutputStream(locBytesStream); } //This method overrides RMIObjectOutputStream's. protected void setAnnotation(String annotation) throws IOException{ - synchronized(this){ - if(locStream == null){ - locBytesStream = new ByteArrayOutputStream(); - locStream = new ObjectOutputStream(locBytesStream); - } - } locStream.writeObject(annotation); } - //This method overrides ObjectOutputStream's to replace Remote to RemoteStub - protected Object replaceObject(Object obj) throws IOException - { - if((obj instanceof Remote) && !(obj instanceof RemoteStub)) - { - UnicastServerRef ref = new UnicastServerRef(new ObjID(), 0, null); - try{ - return ref.exportObject((Remote)obj); - }catch(Exception e){} - } - return obj; - } - public void flush() throws IOException { super.flush(); - if(locStream != null) - locStream.flush(); + locStream.flush(); } public byte[] getLocBytes(){ - if(locStream != null) - return locBytesStream.toByteArray(); - return null; + return locBytesStream.toByteArray(); } } // End of RMIMarshalledObjectOutputStream diff --git a/libjava/gnu/java/rmi/dgc/DGCImpl.java b/libjava/gnu/java/rmi/dgc/DGCImpl.java index fba18c1..4216b64 100644 --- a/libjava/gnu/java/rmi/dgc/DGCImpl.java +++ b/libjava/gnu/java/rmi/dgc/DGCImpl.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. @@ -46,24 +46,73 @@ import java.rmi.server.UnicastRemoteObject; import java.rmi.server.RMISocketFactory; import gnu.java.rmi.server.UnicastServerRef; +import java.util.Hashtable; + +/** + * I let DGCImpl to extend UnicastServerRef, but not + * UnicastRemoteObject, because UnicastRemoteObject must + * exportObject automatically. + */ public class DGCImpl - extends UnicastRemoteObject implements DGC { + extends UnicastServerRef implements DGC { -private static final long leaseValue = 600000L; + private static final long LEASE_VALUE = 600000L; + // leaseCache caches a LeaseRecord associated with a vmid + private Hashtable leaseCache = new Hashtable(); public DGCImpl() throws RemoteException { - super(new UnicastServerRef(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory())); + super(new ObjID(ObjID.DGC_ID), 0, RMISocketFactory.getSocketFactory()); } public Lease dirty(ObjID[] ids, long sequenceNum, Lease lease) throws RemoteException { VMID vmid = lease.getVMID(); + if (vmid == null) + vmid = new VMID(); + long leaseValue = LEASE_VALUE; + //long leaseValue = lease.getValue(); lease = new Lease(vmid, leaseValue); - System.out.println("DGCImpl.dirty - not completely implemented"); + synchronized(leaseCache){ + LeaseRecord lr = (LeaseRecord)leaseCache.get(vmid); + if (lr != null) + lr.reset(leaseValue); + else{ + lr = new LeaseRecord(vmid, leaseValue); + leaseCache.put(vmid, lr); + } + } + return (lease); } public void clean(ObjID[] ids, long sequenceNum, VMID vmid, boolean strong) throws RemoteException { - System.out.println("DGCImpl.clean - not implemented"); + // Not implemented } + + /** + * LeaseRecord associates a vmid to expireTime. + */ + private static class LeaseRecord{ + private VMID vmid; + private long expireTime; + + LeaseRecord(VMID vmid, long leaseValue){ + this.vmid = vmid; + reset(leaseValue); + } + + // reset expireTime + void reset(long leaseValue){ + long l = System.currentTimeMillis(); + expireTime = l + leaseValue; + } -} + boolean isExpired(){ + long l = System.currentTimeMillis(); + if ( l > expireTime) + return true; + return false; + } + + } //End of LeaseRecord + +} //End of DGCImpl diff --git a/libjava/gnu/java/rmi/registry/RegistryImpl.java b/libjava/gnu/java/rmi/registry/RegistryImpl.java index fdf4506..007d5a9 100644 --- a/libjava/gnu/java/rmi/registry/RegistryImpl.java +++ b/libjava/gnu/java/rmi/registry/RegistryImpl.java @@ -64,7 +64,8 @@ public RegistryImpl(int port) throws RemoteException { public RegistryImpl(int port, RMIClientSocketFactory cf, RMIServerSocketFactory sf) throws RemoteException { super(new UnicastServerRef(new ObjID(ObjID.REGISTRY_ID), port, sf)); - ((UnicastServerRef)getRef()).exportObject(this); + // The following is unnecessary, because UnicastRemoteObject export itself automatically. + //((UnicastServerRef)getRef()).exportObject(this); } public Remote lookup(String name) throws RemoteException, NotBoundException, AccessException { diff --git a/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java b/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java index 33cb06a..45e10c4 100644 --- a/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java +++ b/libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java @@ -67,7 +67,7 @@ public final class RegistryImpl_Stub static { try { java.rmi.server.RemoteRef.class.getMethod("invoke", new java.lang.Class[] { java.rmi.Remote.class, java.lang.reflect.Method.class, java.lang.Object[].class, long.class }); - useNewInvoke = true; + useNewInvoke = false; $method_bind_0 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("bind", new java.lang.Class[] {java.lang.String.class, java.rmi.Remote.class}); $method_list_1 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("list", new java.lang.Class[] {}); $method_lookup_2 = gnu.java.rmi.registry.RegistryImpl.class.getMethod("lookup", new java.lang.Class[] {java.lang.String.class}); diff --git a/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java b/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java index df6363b..af7dc05 100644 --- a/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java +++ b/libjava/gnu/java/rmi/server/ConnectionRunnerPool.java @@ -91,6 +91,7 @@ class ConnectionRunnerPool } + // Should this value equal to number of CPU? private static int size = 5; private static int max_size = 10; diff --git a/libjava/gnu/java/rmi/server/RMIObjectInputStream.java b/libjava/gnu/java/rmi/server/RMIObjectInputStream.java index 5913e92..3e862c3 100644 --- a/libjava/gnu/java/rmi/server/RMIObjectInputStream.java +++ b/libjava/gnu/java/rmi/server/RMIObjectInputStream.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. @@ -50,23 +50,13 @@ import java.lang.reflect.Proxy; public class RMIObjectInputStream extends ObjectInputStream { -UnicastConnectionManager manager; - -public RMIObjectInputStream(InputStream strm, UnicastConnectionManager man) throws IOException { +public RMIObjectInputStream(InputStream strm) throws IOException { super(strm); - manager = man; enableResolveObject(true); } -public RMIObjectInputStream(InputStream strm) throws IOException { - this(strm, UnicastConnectionManager.getInstance(0, null)); -} - protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String annotation = (String)getAnnotation(); - try{ - return super.resolveClass(desc); - }catch(ClassNotFoundException _){}; try { if(annotation == null) @@ -90,24 +80,23 @@ protected Class resolveProxyClass(String intfs[]) throws IOException, ClassNotFoundException { String annotation = (String)getAnnotation(); - try{ - return super.resolveProxyClass(intfs); - }catch(ClassNotFoundException _){}; Class clss[] = new Class[intfs.length]; if(annotation == null) clss[0] = RMIClassLoader.loadClass(intfs[0]); else clss[0] = RMIClassLoader.loadClass(annotation, intfs[0]); + //assume all interfaces can be loaded by the same classloader ClassLoader loader = clss[0].getClassLoader(); - if(loader == null) - for(int i = 1; i < intfs.length; i++) - clss[i] = Class.forName(intfs[i]); - else - for(int i = 1; i < intfs.length; i++) - clss[i] = loader.loadClass(intfs[i]); + for (int i = 0; i < intfs.length; i++) + clss[i] = Class.forName(intfs[i], false, loader); + + try { return Proxy.getProxyClass(loader, clss); + } catch (IllegalArgumentException e) { + throw new ClassNotFoundException(null, e); + } } protected Object readValue(Class valueClass) throws IOException, ClassNotFoundException { @@ -134,4 +123,4 @@ protected Object readValue(Class valueClass) throws IOException, ClassNotFoundEx return readObject(); } -}
\ No newline at end of file +} diff --git a/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java b/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java index 71a2bac..97ac88a 100644 --- a/libjava/gnu/java/rmi/server/RMIObjectOutputStream.java +++ b/libjava/gnu/java/rmi/server/RMIObjectOutputStream.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. @@ -72,10 +72,9 @@ protected Object replaceObject(Object obj) throws IOException { if((obj instanceof Remote) && !(obj instanceof RemoteStub)){ - UnicastServerRef ref = new UnicastServerRef(new ObjID(), 0, null); - try{ - return ref.exportObject((Remote)obj); - }catch(Exception e){} + UnicastServerRef ref = UnicastServer.getExportedRef((Remote)obj); + if (ref != null) + return ref.getStub(); } return obj; } diff --git a/libjava/gnu/java/rmi/server/UnicastConnection.java b/libjava/gnu/java/rmi/server/UnicastConnection.java index e13bb68..14d28f2 100644 --- a/libjava/gnu/java/rmi/server/UnicastConnection.java +++ b/libjava/gnu/java/rmi/server/UnicastConnection.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. @@ -61,6 +61,10 @@ DataOutputStream dout; ObjectInputStream oin; ObjectOutputStream oout; +// reviveTime and expireTime make UnicastConnection pool-able +long reviveTime = 0; +long expireTime = Long.MAX_VALUE; + UnicastConnection(UnicastConnectionManager man, Socket sock) { this.manager = man; this.sock = sock; @@ -137,7 +141,7 @@ DataOutputStream getDataOutputStream() throws IOException { ObjectInputStream getObjectInputStream() throws IOException { if (oin == null) { - oin = new RMIObjectInputStream(din, manager); + oin = new RMIObjectInputStream(din); } return (oin); } @@ -153,6 +157,7 @@ void disconnect() { try { if(oout != null) oout.close(); + sock.close(); } catch (IOException _) { } @@ -164,17 +169,35 @@ void disconnect() { sock = null; } +public static final long CONNECTION_TIMEOUT = 10000L; + +static boolean isExpired(UnicastConnection conn, long l){ + if (l <= conn.expireTime ) + return false; + return true; +} + +static void resetTime(UnicastConnection conn){ + long l = System.currentTimeMillis(); + conn.reviveTime = l; + conn.expireTime = l + CONNECTION_TIMEOUT; +} + /** * We run connects on the server. Dispatch it then discard it. */ public void run() { + do{ try { UnicastServer.dispatch(this); + //don't discardConnection explicitly, only when + // exception happens or the connection's expireTime + // comes + } catch (Exception e ){ manager.discardConnection(this); + break; } - catch (Exception e) { - e.printStackTrace(); - } + }while(true); } } diff --git a/libjava/gnu/java/rmi/server/UnicastConnectionManager.java b/libjava/gnu/java/rmi/server/UnicastConnectionManager.java index 64fecdc..d54dcf1 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); } } diff --git a/libjava/gnu/java/rmi/server/UnicastRef.java b/libjava/gnu/java/rmi/server/UnicastRef.java index d6cda49..9ab020d 100644 --- a/libjava/gnu/java/rmi/server/UnicastRef.java +++ b/libjava/gnu/java/rmi/server/UnicastRef.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. @@ -62,6 +62,8 @@ import java.io.ObjectOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.lang.reflect.InvocationTargetException; + public class UnicastRef implements RemoteRef, ProtocolConstants { @@ -69,9 +71,10 @@ public ObjID objid; UnicastConnectionManager manager; /** - * Used by serialization. + * Used by serialization, and let subclass capable of having default constructor */ -private UnicastRef() { +//private +UnicastRef() { } public UnicastRef(ObjID objid, String host, int port, RMIClientSocketFactory csf) { @@ -84,6 +87,21 @@ public UnicastRef(ObjID objid) { } public Object invoke(Remote obj, Method method, Object[] params, long opnum) throws Exception { + // Check if client and server are in the same VM, then local call can be used to + // replace remote call, but it's somewhat violating remote semantic. + Object svrobj = manager.serverobj; + if(svrobj != null){ + //local call + Object ret = null; + try{ + ret = method.invoke(svrobj, params); + }catch(InvocationTargetException e){ + throw (Exception)e.getTargetException(); + } + //System.out.println("\n\n ***** local call: " + method + "\nreturn: " + ret + "\n\n"); + return ret; + } + //System.out.println("***************** remote call:" + manager.serverPort); return (invokeCommon(obj, method, params, -1, opnum)); } @@ -107,18 +125,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu objid.write(out); out.writeInt(opnum); out.writeLong(hash); - /* - if (params != null) { - for (int i = 0; i < params.length; i++) { - if (params[i] instanceof UnicastRemoteObject) { - out.writeObject(UnicastRemoteObject.exportObject((UnicastRemoteObject)params[i])); - } - else { - out.writeObject(params[i]); - } - } - } - */ + // must handle primitive class and their wrapper classes Class clss[] = method.getParameterTypes(); for(int i = 0; i < clss.length; i++) @@ -137,26 +144,30 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu UID ack; try { din = conn.getDataInputStream(); - if (din.readUnsignedByte() != MESSAGE_CALL_ACK) { - throw new RemoteException("Call not acked"); + + if ((returncode = din.readUnsignedByte()) != MESSAGE_CALL_ACK) { + conn.disconnect(); + throw new RemoteException("Call not acked:" + returncode); } in = conn.getObjectInputStream(); - returncode = in.readUnsignedByte(); ack = UID.read(in); - //returnval = in.readObject(); + Class cls = method.getReturnType(); if(cls == Void.TYPE){ returnval = null; + in.readObject(); }else returnval = ((RMIObjectInputStream)in).readValue(cls); + } catch (IOException e3) { + //for debug: e3.printStackTrace(); throw new RemoteException("call return failed: ", e3); } - /* if DGCAck is necessary + /* if DGCAck is necessary?? //According to RMI wire protocol, send a DGCAck // to indicate receiving return value dout.writeByte(MESSAGE_DGCACK); @@ -166,7 +177,7 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu manager.discardConnection(conn); - if (returncode != RETURN_ACK) { + if (returncode != RETURN_ACK && returnval != null) { throw (Exception)returnval; } @@ -177,7 +188,18 @@ private Object invokeCommon(Remote obj, Method method, Object[] params, int opnu * @deprecated */ public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash) throws RemoteException { - return (new UnicastRemoteCall(obj, opnum, hash)); + UnicastConnection conn; + + try { + conn = manager.getConnection(); + } + catch (IOException e1) { + throw new RemoteException("connection failed to host: " + manager.serverName, e1); + } + + //obj: useless? + + return (new UnicastRemoteCall(conn, objid, opnum, hash)); } /** @@ -185,15 +207,19 @@ public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash */ public void invoke(RemoteCall call) throws Exception { UnicastRemoteCall c = (UnicastRemoteCall)call; - Object ret = invokeCommon((Remote)c.getObject(), (Method)null, c.getArguments(), c.getOpnum(), c.getHash()); - c.setReturnValue(ret); + call.executeCall(); } /** * @deprecated */ public void done(RemoteCall call) throws RemoteException { - /* Does nothing */ + UnicastRemoteCall c = (UnicastRemoteCall)call; + try{ + c.done(); + } catch(IOException e){} + UnicastConnection conn = c.getConnection(); + manager.discardConnection(conn); } public void writeExternal(ObjectOutput out) throws IOException { diff --git a/libjava/gnu/java/rmi/server/UnicastRemoteCall.java b/libjava/gnu/java/rmi/server/UnicastRemoteCall.java index 200538d..734002a 100644 --- a/libjava/gnu/java/rmi/server/UnicastRemoteCall.java +++ b/libjava/gnu/java/rmi/server/UnicastRemoteCall.java @@ -38,14 +38,24 @@ exception statement from your version. */ package gnu.java.rmi.server; import java.lang.Exception; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectOutput; import java.io.ObjectInput; import java.io.StreamCorruptedException; import java.rmi.server.RemoteCall; +import java.rmi.RemoteException; +import java.rmi.MarshalException; +import java.rmi.UnmarshalException; +import java.rmi.server.UID; +import java.rmi.server.ObjID; +import java.rmi.server.RemoteObject; + import java.util.Vector; -public class UnicastRemoteCall implements RemoteCall +public class UnicastRemoteCall + implements RemoteCall, ProtocolConstants { private UnicastConnection conn; @@ -56,6 +66,9 @@ public class UnicastRemoteCall implements RemoteCall private Vector vec; private int ptr; + private ObjectOutput oout; + private ObjectInput oin; + /** * Incoming call. */ @@ -67,30 +80,71 @@ public class UnicastRemoteCall implements RemoteCall /** * Outgoing call. */ - UnicastRemoteCall(Object obj, int opnum, long hash) + UnicastRemoteCall(UnicastConnection conn, ObjID objid, int opnum, long hash) + throws RemoteException { - this.object = obj; + this.conn = conn; this.opnum = opnum; this.hash = hash; + + // signal the call when constructing + try + { + DataOutputStream dout = conn.getDataOutputStream(); + dout.write(MESSAGE_CALL); + + oout = conn.getObjectOutputStream(); + objid.write(oout); + oout.writeInt(opnum); + oout.writeLong(hash); + } + catch(IOException ex) + { + throw new MarshalException("Try to write header but failed.", ex); + } } - + + UnicastConnection getConnection() + { + return conn; + } + public ObjectOutput getOutputStream() throws IOException { - vec = new Vector(); - return new DummyObjectOutputStream(); + if (conn != null) + { + if(oout == null) + return (oout = conn.getObjectOutputStream()); + else + return oout; + } + else + { + vec = new Vector(); + return (new DummyObjectOutputStream()); + } } public void releaseOutputStream() throws IOException { - // Does nothing. + if(oout != null) + oout.flush(); } public ObjectInput getInputStream() throws IOException { if (conn != null) - return conn.getObjectInputStream(); - ptr = 0; - return new DummyObjectInputStream(); + { + if(oin == null) + return (oin = conn.getObjectInputStream()); + else + return oin; + } + else + { + ptr = 0; + return (new DummyObjectInputStream()); + } } public void releaseInputStream() throws IOException @@ -104,15 +158,57 @@ public class UnicastRemoteCall implements RemoteCall vec = new Vector(); return new DummyObjectOutputStream(); } - + public void executeCall() throws Exception { - throw new Error("Not implemented"); + byte returncode; + ObjectInput oin; + try + { + releaseOutputStream(); + DataInputStream din = conn.getDataInputStream(); + if (din.readByte() != MESSAGE_CALL_ACK) + throw new RemoteException("Call not acked"); + + oin = getInputStream(); + returncode = oin.readByte(); + UID.read(oin); + } + catch(IOException ex) + { + throw new UnmarshalException("Try to read header but failed:", ex); + } + + //check return code + switch(returncode) + { + case RETURN_ACK: //it's ok + return; + case RETURN_NACK: + Object returnobj; + try + { + returnobj = oin.readObject(); + } + catch(Exception ex2) + { + throw new UnmarshalException + ("Try to read exception object but failed", ex2); + } + + if(!(returnobj instanceof Exception)) + throw new UnmarshalException("Should be Exception type here: " + + returnobj); + throw (Exception)returnobj; + + default: + throw new UnmarshalException("Invalid return code"); + } } public void done() throws IOException { - /* Does nothing */ + // conn.disconnect(); } Object returnValue() diff --git a/libjava/gnu/java/rmi/server/UnicastServer.java b/libjava/gnu/java/rmi/server/UnicastServer.java index 15c622f..baa1ef1 100644 --- a/libjava/gnu/java/rmi/server/UnicastServer.java +++ b/libjava/gnu/java/rmi/server/UnicastServer.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. @@ -45,6 +45,7 @@ import java.io.IOException; import java.net.InetAddress; import java.util.Hashtable; import java.net.UnknownHostException; +import java.rmi.Remote; import java.rmi.server.ObjID; import java.rmi.server.UnicastRemoteObject; import java.rmi.server.UID; @@ -56,27 +57,36 @@ import gnu.java.rmi.dgc.DGCImpl; public class UnicastServer implements ProtocolConstants { -static private Hashtable objects = new Hashtable(); +static private Hashtable objects = new Hashtable(); //mapping OBJID to server ref +static private Hashtable refcache = new Hashtable(); //mapping obj itself to server ref static private DGCImpl dgc; public static void exportObject(UnicastServerRef obj) { startDGC(); objects.put(obj.objid, obj); + refcache.put(obj.myself, obj); obj.manager.startServer(); } // FIX ME: I haven't handle force parameter public static boolean unexportObject(UnicastServerRef obj, boolean force) { objects.remove(obj.objid); + refcache.remove(obj.myself); obj.manager.stopServer(); return true; } +public static UnicastServerRef getExportedRef(Remote remote){ + return (UnicastServerRef)refcache.get(remote); +} + private static synchronized void startDGC() { if (dgc == null) { try { dgc = new DGCImpl(); - ((UnicastServerRef)dgc.getRef()).exportObject(dgc); + // Changed DGCImpl to inherit UnicastServerRef directly + //((UnicastServerRef)dgc.getRef()).exportObject(dgc); + dgc.exportObject(dgc); } catch (RemoteException e) { e.printStackTrace(); diff --git a/libjava/gnu/java/rmi/server/UnicastServerRef.java b/libjava/gnu/java/rmi/server/UnicastServerRef.java index 196f969..4f64452 100644 --- a/libjava/gnu/java/rmi/server/UnicastServerRef.java +++ b/libjava/gnu/java/rmi/server/UnicastServerRef.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. @@ -63,6 +63,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.ObjectInput; +import java.io.ObjectOutput; import java.util.Hashtable; public class UnicastServerRef @@ -71,11 +73,18 @@ public class UnicastServerRef final static private Class[] stubprototype = new Class[] { RemoteRef.class }; -Remote myself; +Remote myself; //save the remote object itself private Skeleton skel; private RemoteStub stub; private Hashtable methods = new Hashtable(); +/** + * Used by serialization. + */ +UnicastServerRef() +{ +} + public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) { super(id); manager = UnicastConnectionManager.getInstance(port, ssf); @@ -84,6 +93,9 @@ public UnicastServerRef(ObjID id, int port, RMIServerSocketFactory ssf) { public RemoteStub exportObject(Remote obj) throws RemoteException { if (myself == null) { myself = obj; + // Save it to server manager, to let client calls in the same VM to issue + // local call + manager.serverobj = obj; // Find and install the stub Class cls = obj.getClass(); @@ -112,6 +124,10 @@ public RemoteStub exportObject(Remote remote, Object obj) return exportObject(remote); } +public RemoteStub getStub(){ + return stub; +} + public boolean unexportObject(Remote obj, boolean force) throws RemoteException { // Remove all hashes of methods which may be called. |