Commit f150fe3f by Mark Wielaard Committed by Mark Wielaard

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
parent 396a8043
2002-11-07 Mark Wielaard <mark@klomp.org>
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.
2002-11-07 Mark Wielaard <mark@klomp.org>
* java/lang/reflect/natField.cc (getBoolean): Use getType().
(getByte): Likewise.
(getShort): Likewise.
......
......@@ -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
......
/*
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
......@@ -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 {
......
......@@ -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});
......
......@@ -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;
......
/*
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
}
/*
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;
}
......
/*
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);
}
}
/*
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);
}
}
......
/*
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 {
......
......@@ -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()
......
/*
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();
......
/*
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.
......
......@@ -78,6 +78,10 @@ public final class MarshalledObject
{
if(obj == null || !(obj instanceof MarshalledObject) )
return false;
// hashCode even differs, don't do the time-consuming comparisons
if (obj.hashCode() != hash)
return false;
MarshalledObject aobj = (MarshalledObject)obj;
if (objBytes == null || aobj.objBytes == null)
......
......@@ -43,39 +43,72 @@ import java.net.URLClassLoader;
import java.io.IOException;
import java.io.DataInputStream;
import java.net.MalformedURLException;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.WeakHashMap;
import java.util.ArrayList;
public class RMIClassLoader
{
static private class MyClassLoader extends URLClassLoader
{
private MyClassLoader(URL[] urls, ClassLoader parent, String annotation)
{
super(urls, parent);
this.annotation = annotation;
}
private MyClassLoader(URL[] urls, ClassLoader parent)
{
super (urls, parent);
this.annotation = urlToAnnotation(urls);
}
Class defineClass(String name, byte[] data)
public static String urlToAnnotation(URL[] urls)
{
return defineClass(name, data, 0, data.length);
if (urls.length == 0)
return null;
StringBuffer annotation = new StringBuffer(64*urls.length);
for(int i = 0; i < urls.length; i++)
{
annotation.append(urls[i].toExternalForm());
annotation.append(' ');
}
return annotation.toString();
}
public final String getClassAnnotation(){
return annotation;
}
private final String annotation;
}
private static Map cacheLoaders; //map annotations to loaders
private static Map cacheClasses; //map loader to classes that the loader loaded+
private static Map cacheAnnotations; //map loaders to annotations
//defaultAnnotation is got from system property
// "java.rmi.server.defaultAnnotation"
private static String defaultAnnotation;
//URL object for defaultAnnotation
private static URL defaultCodebase;
//class loader for defaultAnnotation
private static MyClassLoader defaultLoader;
static
{
cacheLoaders = Collections.synchronizedMap(new WeakHashMap(5));
cacheClasses = Collections.synchronizedMap(new WeakHashMap(5));
// 89 is a nice prime number for Hashtable initial capacity
cacheLoaders = new Hashtable(89);
cacheAnnotations = new Hashtable(89);
defaultAnnotation = System.getProperty("java.rmi.server.defaultAnnotation");
try
{
......@@ -89,9 +122,8 @@ public class RMIClassLoader
if (defaultCodebase != null)
{
defaultLoader = new MyClassLoader(new URL[]{ defaultCodebase },
Thread.currentThread().getContextClassLoader());
null, defaultAnnotation);
cacheLoaders.put(defaultAnnotation, defaultLoader);
cacheClasses.put(defaultLoader, Collections.synchronizedMap(new WeakHashMap()));
}
}
......@@ -104,91 +136,76 @@ public class RMIClassLoader
return (loadClass("", name));
}
public static Class loadClass(URL codebase, String name)
public static Class loadClass(String codebases, String name)
throws MalformedURLException, ClassNotFoundException
{
URL u = new URL(codebase, name + ".class");
Class c = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
//try context class loader first
try
{
URLConnection conn = u.openConnection();
DataInputStream strm = new DataInputStream(conn.getInputStream());
byte data[] = new byte[conn.getContentLength()];
strm.readFully(data);
return (defaultLoader.defineClass(name, data));
}
catch (IOException _)
{
throw new ClassNotFoundException(name);
c = loader.loadClass(name);
}
}
public static Class loadClass(String codebases, String name)
throws MalformedURLException, ClassNotFoundException
{
ClassLoader loader = (ClassLoader)cacheLoaders.get(codebases);
if (loader == null)
catch(ClassNotFoundException e) {}
if (c != null)
return c;
if (codebases.length() == 0) //==""
loader = defaultLoader;
else
{
if (codebases != "")
loader = (ClassLoader)cacheLoaders.get(codebases);
if (loader == null)
{
//codebases are separated by " "
//create an entry in cacheLoaders mapping a loader to codebases.
// codebases are separated by " "
StringTokenizer tok = new StringTokenizer(codebases, " ");
ArrayList urls = new ArrayList();
while (tok.hasMoreTokens())
urls.add(new URL(tok.nextToken()));
loader = new MyClassLoader((URL[])urls.toArray(new URL[urls.size()]),
Thread.currentThread().getContextClassLoader());
null, codebases);
cacheLoaders.put(codebases, loader);
cacheClasses.put(loader, Collections.synchronizedMap(new WeakHashMap()));
}
else
{
//if codebases is empty, construct a classloader
// based on current context classloader,
// and we won't cache classloader for empty codebases
loader = new MyClassLoader(new URL[]{ defaultCodebase },
Thread.currentThread().getContextClassLoader());
}
}
Class c = null;
Map classes = (Map)cacheClasses.get(loader);
if (classes != null)
{
c = (Class)classes.get(name);
if (c == null)
{
c = loader.loadClass(name);
classes.put(name, c);
}
}else
c = loader.loadClass(name);
return c;
return loader != null ? loader.loadClass(name) : Class.forName(name);
}
public static String getClassAnnotation(Class cl)
{
ClassLoader loader = cl.getClassLoader();
if (loader == null)
if (loader == null || loader == ClassLoader.getSystemClassLoader())
{
if (defaultCodebase != null)
return defaultCodebase.toExternalForm();
else
return null;
return null; //??
}
if (loader instanceof MyClassLoader)
{
return ((MyClassLoader)loader).getClassAnnotation();
}
String s = (String)cacheAnnotations.get(loader);
if (s != null)
return s;
if (loader instanceof URLClassLoader)
{
URL[] urls = ((URLClassLoader)loader).getURLs();
if(urls.length == 0)
return null;
StringBuffer annotation = new StringBuffer(urls[0].toExternalForm());
for(int i = 1; i < urls.length; i++)
StringBuffer annotation = new StringBuffer(64*urls.length);
for(int i = 0; i < urls.length; i++)
{
annotation.append(' ');
annotation.append(urls[i].toExternalForm());
annotation.append(' ');
}
return annotation.toString();
s = annotation.toString();
cacheAnnotations.put(loader, s);
}
return null;
}
......
......@@ -127,11 +127,11 @@ public boolean equals(Object obj) {
}
catch (InstantiationException e1)
{
throw new UnmarshalException("failed to create ref");
throw new UnmarshalException("failed to create ref", e1);
}
catch (IllegalAccessException e2)
{
throw new UnmarshalException("failed to create ref");
throw new UnmarshalException("failed to create ref", e2);
}
ref.readExternal(in);
}
......
/*
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.
......@@ -67,16 +67,12 @@ protected UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSoc
//this.csf = csf;
//this.ssf = ssf;
this.ref = new UnicastServerRef(new ObjID(), port, ssf);
//Should we export it here?
// if we export, we got infinite recursive call:
// UnicastRemoteObject.<init>->...->UnicastServer.startDGC()->UnicastRemoteObject.<init>->...
//exportObject(this);
exportObject(this);
}
protected UnicastRemoteObject(RemoteRef ref) throws RemoteException {
super((UnicastServerRef)ref);
//Should we export it here?
//exportObject(this);
exportObject(this);
}
public Object clone() throws CloneNotSupportedException {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment