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
This commit is contained in:
Mark Wielaard
2002-11-07 18:01:05 +00:00
committed by Mark Wielaard
parent 396a80436c
commit f150fe3fa7
18 changed files with 601 additions and 200 deletions
@@ -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
+57 -8
View File
@@ -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;
public class DGCImpl
extends UnicastRemoteObject implements DGC {
import java.util.Hashtable;
private static final long leaseValue = 600000L;
/**
* I let DGCImpl to extend UnicastServerRef, but not
* UnicastRemoteObject, because UnicastRemoteObject must
* exportObject automatically.
*/
public class DGCImpl
extends UnicastServerRef implements DGC {
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;
@@ -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 {
super(strm);
manager = man;
enableResolveObject(true);
}
public RMIObjectInputStream(InputStream strm) throws IOException {
this(strm, UnicastConnectionManager.getInstance(0, null));
super(strm);
enableResolveObject(true);
}
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();
}
}
}
@@ -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;
}
@@ -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);
}
}
@@ -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);
}
}
+51 -25
View File
@@ -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 {
@@ -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()
+13 -3
View File
@@ -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();
@@ -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.