More work on invocation manager; modified startup sequence so that server
can get shit together before bootstrapping the client. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@68 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Client.java,v 1.7 2001/07/19 05:56:20 mdb Exp $
|
||||
// $Id: Client.java,v 1.8 2001/07/19 07:09:16 mdb Exp $
|
||||
|
||||
package com.threerings.cocktail.cher.client;
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.List;
|
||||
|
||||
import com.threerings.cocktail.cher.Log;
|
||||
import com.threerings.cocktail.cher.dobj.DObjectManager;
|
||||
import com.threerings.cocktail.cher.net.BootstrapData;
|
||||
import com.threerings.cocktail.cher.net.Credentials;
|
||||
|
||||
/**
|
||||
@@ -142,28 +143,21 @@ public class Client
|
||||
}
|
||||
|
||||
/**
|
||||
* Every client has an associated <code>ClientObject</code> instance.
|
||||
*
|
||||
* @return the oid of the client object or -1 if we are not currently
|
||||
* connected to the server.
|
||||
* Returns the oid of the client object associated with this session.
|
||||
* It is only valid for the duration of the session.
|
||||
*/
|
||||
public int getClientOid ()
|
||||
{
|
||||
return (_comm != null) ? _comm.getClientOid() : -1;
|
||||
return _cloid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the invocation manager associated with this session. This
|
||||
* reference is only valid for the duration of the session and a new
|
||||
* reference must be obtained if the client disconnects and reconnects
|
||||
* to the server.
|
||||
*
|
||||
* @return the invocation manager in effect or null if we have no
|
||||
* established connection to the server.
|
||||
* reference is only valid for the duration of the session.
|
||||
*/
|
||||
public InvocationManager getInvocationManager ()
|
||||
{
|
||||
return (_comm != null) ? _comm.getInvocationManager() : null;
|
||||
return _invmgr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,6 +243,18 @@ public class Client
|
||||
_comm = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the omgr when a bootstrap notification arrives.
|
||||
*/
|
||||
void gotBootstrap (BootstrapData data)
|
||||
{
|
||||
// extract bootstrap information
|
||||
_cloid = data.clientOid;
|
||||
|
||||
// create our invocation manager
|
||||
_invmgr = new InvocationManager(this, data.invOid);
|
||||
}
|
||||
|
||||
protected Credentials _creds;
|
||||
protected Invoker _invoker;
|
||||
|
||||
@@ -261,6 +267,9 @@ public class Client
|
||||
/** The entity that manages our network communications. */
|
||||
protected Communicator _comm;
|
||||
|
||||
protected int _cloid;
|
||||
protected InvocationManager _invmgr;
|
||||
|
||||
// client observer codes
|
||||
static final int CLIENT_DID_LOGON = 0;
|
||||
static final int CLIENT_FAILED_TO_LOGON = 1;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: ClientDObjectMgr.java,v 1.3 2001/06/13 05:17:54 mdb Exp $
|
||||
// $Id: ClientDObjectMgr.java,v 1.4 2001/07/19 07:09:16 mdb Exp $
|
||||
|
||||
package com.threerings.cocktail.cher.client;
|
||||
|
||||
@@ -109,7 +109,11 @@ public class ClientDObjectMgr
|
||||
Object obj;
|
||||
while ((obj = _actions.getNonBlocking()) != null) {
|
||||
// do the proper thing depending on the object
|
||||
if (obj instanceof EventNotification) {
|
||||
if (obj instanceof BootstrapNotification) {
|
||||
BootstrapData data = ((BootstrapNotification)obj).getData();
|
||||
_client.gotBootstrap(data);
|
||||
|
||||
} else if (obj instanceof EventNotification) {
|
||||
DEvent evt = ((EventNotification)obj).getEvent();
|
||||
dispatchEvent(evt);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Communicator.java,v 1.8 2001/07/19 05:56:20 mdb Exp $
|
||||
// $Id: Communicator.java,v 1.9 2001/07/19 07:09:16 mdb Exp $
|
||||
|
||||
package com.threerings.cocktail.cher.client;
|
||||
|
||||
@@ -61,24 +61,6 @@ public class Communicator
|
||||
return _omgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the oid of the client object associated with this session.
|
||||
* It is only valid for the duration of the session.
|
||||
*/
|
||||
public int getClientOid ()
|
||||
{
|
||||
return _cloid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the invocation manager associated with this session. This
|
||||
* reference is only valid for the duration of the session.
|
||||
*/
|
||||
public InvocationManager getInvocationManager ()
|
||||
{
|
||||
return _invmgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs on to the server and initiates our full-duplex message
|
||||
* exchange.
|
||||
@@ -171,15 +153,9 @@ public class Communicator
|
||||
{
|
||||
Log.info("Logon succeeded: " + data);
|
||||
|
||||
// extract bootstrap information
|
||||
_cloid = data.clientOid;
|
||||
|
||||
// create our distributed object manager
|
||||
_omgr = new ClientDObjectMgr(this, _client);
|
||||
|
||||
// create our invocation manager
|
||||
_invmgr = new InvocationManager(_client, data.invOid);
|
||||
|
||||
// create a new writer thread and start it up
|
||||
if (_writer != null) {
|
||||
throw new RuntimeException("Writer already started!?");
|
||||
@@ -502,6 +478,4 @@ public class Communicator
|
||||
protected DataInputStream _din;
|
||||
|
||||
protected ClientDObjectMgr _omgr;
|
||||
protected int _cloid;
|
||||
protected InvocationManager _invmgr;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: InvocationDirector.java,v 1.1 2001/07/19 05:56:20 mdb Exp $
|
||||
// $Id: InvocationDirector.java,v 1.2 2001/07/19 07:09:16 mdb Exp $
|
||||
|
||||
package com.threerings.cocktail.cher.client;
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.HashMap;
|
||||
import com.threerings.cocktail.cher.Log;
|
||||
import com.threerings.cocktail.cher.data.*;
|
||||
import com.threerings.cocktail.cher.dobj.*;
|
||||
import com.threerings.cocktail.cher.util.ClassUtil;
|
||||
import com.threerings.cocktail.cher.util.IntMap;
|
||||
|
||||
/**
|
||||
@@ -53,28 +54,32 @@ public class InvocationManager
|
||||
/**
|
||||
* Sends an invocation request to the server. If a response target is
|
||||
* supplied, the response will be delivered to that object by calling
|
||||
* a member function on it whose name is derived from the invocation
|
||||
* name. For example, if the caller invoked a procedure named
|
||||
* <code>SwitchLocation</code>, the response would be delivered via a
|
||||
* call to the <code>handleSwitchLocationResponse</code> method on the
|
||||
* response target object. The signature of that method would be
|
||||
* defined by the arguments provided in the response message.
|
||||
* a member function on it whose name is defined in the response
|
||||
* generated by the invocation implementation. In general, this is a
|
||||
* derivative of the invocation procedure name. For example, if the
|
||||
* caller invoked a procedure named <code>Switch</code>, the response
|
||||
* may be delivered via a call to the <code>handleSwitchSuccess</code>
|
||||
* method on the response target object. The signature of that method
|
||||
* would be defined by the arguments provided in the response message.
|
||||
*
|
||||
* @param name the name of the invocation.
|
||||
* @param module the name of the invocation module to use.
|
||||
* @param procedure the name of the procedure within that module.
|
||||
* @param args the arguments of the invocation.
|
||||
* @param rsptarget the object that will receive the response, or null
|
||||
* if no response is desired.
|
||||
*/
|
||||
public void invoke (String name, Object[] args, Object rsptarget)
|
||||
public void invoke (String module, String procedure, Object[] args,
|
||||
Object rsptarget)
|
||||
{
|
||||
int invid = nextInvocationId();
|
||||
|
||||
// we need an args array for a message that can contain the
|
||||
// invocation name, an invocation id and the invocation arguments
|
||||
Object[] iargs = new Object[args.length+2];
|
||||
System.arraycopy(args, 0, iargs, 2, args.length);
|
||||
iargs[0] = name;
|
||||
iargs[1] = new Integer(invid);
|
||||
// invocation names, an invocation id and the invocation arguments
|
||||
Object[] iargs = new Object[args.length+3];
|
||||
iargs[0] = module;
|
||||
iargs[1] = procedure;
|
||||
iargs[2] = new Integer(invid);
|
||||
System.arraycopy(args, 0, iargs, 3, args.length);
|
||||
|
||||
// create a message event on the invocation manager object
|
||||
MessageEvent event = new MessageEvent(
|
||||
@@ -83,7 +88,7 @@ public class InvocationManager
|
||||
// if we have a response target, register that for later receipt
|
||||
// of the response
|
||||
if (rsptarget != null) {
|
||||
_targets.put(invid, new Response(name, rsptarget));
|
||||
_targets.put(invid, rsptarget);
|
||||
}
|
||||
|
||||
// and finally ship off the invocation message
|
||||
@@ -110,9 +115,8 @@ public class InvocationManager
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageEvent mevt = (MessageEvent)event;
|
||||
|
||||
// and only those of proper name
|
||||
MessageEvent mevt = (MessageEvent)event;
|
||||
if (!mevt.getName().equals(InvocationObject.MESSAGE_NAME)) {
|
||||
return true;
|
||||
}
|
||||
@@ -120,11 +124,11 @@ public class InvocationManager
|
||||
// we've got an invocation response, so we extract the args and
|
||||
// process it
|
||||
Object[] args = mevt.getArgs();
|
||||
int invid = ((Integer)args[0]).intValue();
|
||||
String name = (String)args[1];
|
||||
String name = (String)args[0];
|
||||
int invid = ((Integer)args[1]).intValue();
|
||||
|
||||
Response rsp = (Response)_targets.get(invid);
|
||||
if (rsp == null) {
|
||||
Object rsptarg = _targets.get(invid);
|
||||
if (rsptarg == null) {
|
||||
Log.warning("No target for invocation response " +
|
||||
"[rsp=" + mevt + "].");
|
||||
return true;
|
||||
@@ -135,53 +139,27 @@ public class InvocationManager
|
||||
System.arraycopy(args, 2, rargs, 0, rargs.length);
|
||||
|
||||
// and invoke the response method
|
||||
Method rspmeth = getResponseMethod(name, target, rargs);
|
||||
if (rspmeth != null) {
|
||||
try {
|
||||
rspmeth.invoke(target, rargs);
|
||||
} catch (Exception e) {
|
||||
Log.warning("Error invoking response target method " +
|
||||
"[target=" + target + ", method=" + rspmeth +
|
||||
", error=" + e + "].");
|
||||
}
|
||||
String mname = "handle" + name;
|
||||
Method rspmeth = ClassUtil.getMethod(mname, rsptarg, _methcache);
|
||||
if (rspmeth == null) {
|
||||
Log.warning("Unable to resolve response method " +
|
||||
"[target=" + rsptarg.getClass().getName() +
|
||||
", method=" + mname + "].");
|
||||
return true;
|
||||
}
|
||||
|
||||
// and invoke it
|
||||
try {
|
||||
rspmeth.invoke(rsptarg, rargs);
|
||||
} catch (Exception e) {
|
||||
Log.warning("Error invoking response target method " +
|
||||
"[target=" + rsptarg + ", method=" + rspmeth +
|
||||
", error=" + e + "].");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Method getResponseMethod (String name, Object target,
|
||||
Object[] args)
|
||||
{
|
||||
Class tclass = target.getClass();
|
||||
String key = tclass.getName() + ":" + name;
|
||||
Method method = (Method)_methcache.get(key);
|
||||
|
||||
if (method == null) {
|
||||
String methname = "handle" + name;
|
||||
method = findMethod(tclass, name);
|
||||
if (method == null) {
|
||||
Log.warning("Unable to locate method on response target " +
|
||||
"[rtclass=" + tclass.getName() +
|
||||
", method=" + methname + "].");
|
||||
return null;
|
||||
}
|
||||
_methcache.put(key, method);
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
protected static Method findMethod (Class clazz, String name)
|
||||
{
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (methods[i].getName().equals(name)) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected synchronized int nextInvocationId ()
|
||||
{
|
||||
return _invocationId++;
|
||||
|
||||
Reference in New Issue
Block a user