aboutsummaryrefslogtreecommitdiff
path: root/libjava/gnu/java
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2002-11-07 18:01:05 +0000
committerMark Wielaard <mark@gcc.gnu.org>2002-11-07 18:01:05 +0000
commitf150fe3fa7cc90fa7abd9bd64e4b5ccd6646d5a7 (patch)
treedfca54cc19c9efec9125010fd9fcb7030f24bea4 /libjava/gnu/java
parent396a80436c733527118877c95bfec72e38401eeb (diff)
downloadgcc-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.java28
-rw-r--r--libjava/gnu/java/rmi/dgc/DGCImpl.java63
-rw-r--r--libjava/gnu/java/rmi/registry/RegistryImpl.java3
-rw-r--r--libjava/gnu/java/rmi/registry/RegistryImpl_Stub.java2
-rw-r--r--libjava/gnu/java/rmi/server/ConnectionRunnerPool.java1
-rw-r--r--libjava/gnu/java/rmi/server/RMIObjectInputStream.java33
-rw-r--r--libjava/gnu/java/rmi/server/RMIObjectOutputStream.java9
-rw-r--r--libjava/gnu/java/rmi/server/UnicastConnection.java33
-rw-r--r--libjava/gnu/java/rmi/server/UnicastConnectionManager.java176
-rw-r--r--libjava/gnu/java/rmi/server/UnicastRef.java76
-rw-r--r--libjava/gnu/java/rmi/server/UnicastRemoteCall.java122
-rw-r--r--libjava/gnu/java/rmi/server/UnicastServer.java16
-rw-r--r--libjava/gnu/java/rmi/server/UnicastServerRef.java20
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.