We've always been at war with Eurasia. Changed InvocationManager to

InvocationDirector (please god let the renaming be done). Removed IntMap
and modified code to use samskivert's HashIntMap.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@375 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2001-10-02 02:08:16 +00:00
parent 1f663669c9
commit 6620936a04
13 changed files with 73 additions and 295 deletions
@@ -1,5 +1,5 @@
//
// $Id: Client.java,v 1.13 2001/08/21 19:33:06 mdb Exp $
// $Id: Client.java,v 1.14 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.client;
@@ -178,12 +178,12 @@ public class Client
}
/**
* Returns the invocation manager associated with this session. This
* Returns the invocation director associated with this session. This
* reference is only valid for the duration of the session.
*/
public InvocationManager getInvocationManager ()
public InvocationDirector getInvocationDirector ()
{
return _invmgr;
return _invdir;
}
/**
@@ -277,16 +277,16 @@ public class Client
// extract bootstrap information
_cloid = data.clientOid;
// create our invocation manager
_invmgr = new InvocationManager(this, data.invOid);
// create our invocation director
_invdir = new InvocationDirector(this, data.invOid);
// we can't quite call initialization completed at this point
// because we need for the invocation manager to fully initialize
// because we need for the invocation director to fully initialize
// (which requires a round trip to the server) before turning the
// client loose to do things like request invocation services
}
void invocationManagerReady (ClientObject clobj)
void invocationDirectorReady (ClientObject clobj)
{
// keep this around
_clobj = clobj;
@@ -309,7 +309,7 @@ public class Client
protected Communicator _comm;
protected int _cloid;
protected InvocationManager _invmgr;
protected InvocationDirector _invdir;
// client observer codes
static final int CLIENT_DID_LOGON = 0;
@@ -1,18 +1,18 @@
//
// $Id: InvocationDirector.java,v 1.9 2001/08/21 19:33:06 mdb Exp $
// $Id: InvocationDirector.java,v 1.10 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.client;
import java.lang.reflect.Method;
import java.util.HashMap;
import com.samskivert.util.HashIntMap;
import com.samskivert.util.StringUtil;
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;
/**
* The invocation services provide client to server invocations (service
@@ -28,23 +28,23 @@ import com.threerings.cocktail.cher.util.IntMap;
* non-local objects (it is assumed that the distributed object facility
* will already be in use for any objects that should be shared).
*
* <p> The client invocation manager delivers invocation requests to the
* <p> The client invocation director delivers invocation requests to the
* server invocation manager and maps the responses back to the proper
* response target objects when they arrive. It also maintains the mapping
* of invocation receivers that can receive asynchronous invocation
* notifications at any time from the server.
*/
public class InvocationManager
public class InvocationDirector
implements Subscriber
{
/**
* Constructs a new invocation manager with the specified invocation
* Constructs a new invocation director with the specified invocation
* manager oid. It will obtain its distributed object manager and
* client object references from the supplied client instance. The
* invocation manager oid is the oid of the object on the server to
* which to deliver invocation requests.
*/
public InvocationManager (Client client, int imoid)
public InvocationDirector (Client client, int imoid)
{
_client = client;
_omgr = client.getDObjectManager();
@@ -120,14 +120,14 @@ public class InvocationManager
{
// let the client know that we're ready to go now that we've got
// our subscription to the client object
_client.invocationManagerReady((ClientObject)object);
_client.invocationDirectorReady((ClientObject)object);
}
public void requestFailed (int oid, ObjectAccessException cause)
{
// aiya! we were unable to subscribe to the client object. we're
// hosed, hosed, hosed
Log.warning("Invocation manager unable to subscribe to client " +
Log.warning("Invocation director unable to subscribe to client " +
"object. All is wrong in the universe.");
}
@@ -266,6 +266,6 @@ public class InvocationManager
protected int _imoid;
protected int _invocationId;
protected IntMap _targets = new IntMap();
protected HashIntMap _targets = new HashIntMap();
protected HashMap _receivers = new HashMap();
}
@@ -1,12 +1,12 @@
//
// $Id: InvocationReceiver.java,v 1.2 2001/08/04 02:31:20 mdb Exp $
// $Id: InvocationReceiver.java,v 1.3 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.client;
/**
* Classes registered to process invocation notifications should implement
* the invocation receiver interface and register themselves with the
* invocation manager. Because the invocation notification procedures are
* invocation director. Because the invocation notification procedures are
* looked up using reflection, there are no methods to implement in the
* receiver interface, but it serves as a useful point for documentation
* and as a useful indicator that the class in question is serving as an
@@ -15,7 +15,7 @@ package com.threerings.cocktail.cher.client;
* <p> Invocation notifications are identified by a module name and a
* procedure name. The module name identifies which invocation receiver
* instance will receive the notification. Receivers are registered with
* the invocation manager as handling all notification procedures for a
* the invocation director as handling all notification procedures for a
* particular module. The notification procedure name is used to construct
* a method name which is then reflected and invoked.
*
@@ -29,7 +29,7 @@ package com.threerings.cocktail.cher.client;
* the standard reflection argument type conversion process taken into
* account).
*
* @see InvocationManager#registerReceiver
* @see InvocationDirector#registerReceiver
*/
public interface InvocationReceiver
{
@@ -1,5 +1,5 @@
//
// $Id: DSet.java,v 1.6 2001/08/21 19:35:56 mdb Exp $
// $Id: DSet.java,v 1.7 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.dobj;
@@ -28,15 +28,14 @@ import com.threerings.cocktail.cher.io.Streamable;
*
* <p> Classes that wish to act as set elements must implement the {@link
* com.threerings.cocktail.cher.dobj.DSet.Element} interface which extends
* {@link com.threerings.cocktail.cher.io.Streamable} and adds the
* requirement that the object provide a key which will be used to
* identify element equality. Thus an element is declared to be in a set
* of the object returned by that element's <code>geyKey()</code> method
* is equal (using <code>equal()</code>) to the element returned by the
* <code>getKey()</code> method of some other element in the set.
* Additionally, in the case of element removal, only the key for the
* element to be removed will be transmitted with the removal event to
* save network bandwidth. Lastly, the object returned by
* {@link Streamable} and adds the requirement that the object provide a
* key which will be used to identify element equality. Thus an element is
* declared to be in a set of the object returned by that element's
* <code>geyKey()</code> method is equal (using <code>equal()</code>) to
* the element returned by the <code>getKey()</code> method of some other
* element in the set. Additionally, in the case of element removal, only
* the key for the element to be removed will be transmitted with the
* removal event to save network bandwidth. Lastly, the object returned by
* <code>getKey()</code> must be a valid distributed object type.
*/
public class DSet
@@ -1,19 +1,19 @@
//
// $Id: PresentsClient.java,v 1.18 2001/08/11 00:12:11 mdb Exp $
// $Id: PresentsClient.java,v 1.19 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.server;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import com.samskivert.util.HashIntMap;
import com.threerings.cocktail.cher.Log;
import com.threerings.cocktail.cher.data.ClientObject;
import com.threerings.cocktail.cher.dobj.*;
import com.threerings.cocktail.cher.net.*;
import com.threerings.cocktail.cher.server.net.*;
import com.threerings.cocktail.cher.util.IntMap;
/**
* A client object represents a client session in the server. It is
@@ -213,9 +213,9 @@ public class CherClient implements Subscriber, MessageHandler
*/
protected synchronized void clearSubscrips ()
{
Enumeration enum = _subscrips.elements();
while (enum.hasMoreElements()) {
DObject object = (DObject)enum.nextElement();
Iterator enum = _subscrips.elements();
while (enum.hasNext()) {
DObject object = (DObject)enum.next();
// Log.info("Clearing subscription [client=" + this +
// ", obj=" + object + "].");
object.removeSubscriber(this);
@@ -562,7 +562,7 @@ public class CherClient implements Subscriber, MessageHandler
protected String _username;
protected Connection _conn;
protected ClientObject _clobj;
protected IntMap _subscrips = new IntMap();
protected HashIntMap _subscrips = new HashIntMap();
protected static HashMap _disps = new HashMap();
@@ -1,16 +1,16 @@
//
// $Id: PresentsDObjectMgr.java,v 1.14 2001/08/11 01:00:26 mdb Exp $
// $Id: PresentsDObjectMgr.java,v 1.15 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.server;
import java.lang.reflect.*;
import java.util.HashMap;
import com.samskivert.util.HashIntMap;
import com.samskivert.util.Queue;
import com.threerings.cocktail.cher.Log;
import com.threerings.cocktail.cher.dobj.*;
import com.threerings.cocktail.cher.util.IntMap;
/**
* The cher distributed object manager implements the
@@ -328,7 +328,7 @@ public class CherDObjectMgr implements DObjectManager
int oid = oae.getOid();
// ensure that the target object exists
if (!_objects.contains(oid)) {
if (!_objects.containsKey(oid)) {
Log.info("Rejecting object added event of non-existent object " +
"[refferOid=" + target.getOid() +
", reffedOid=" + oid + "].");
@@ -427,7 +427,7 @@ public class CherDObjectMgr implements DObjectManager
// come to an end long before we had two billion objects
do {
_nextOid = (_nextOid + 1) % Integer.MAX_VALUE;
} while (_objects.contains(_nextOid));
} while (_objects.containsKey(_nextOid));
return _nextOid;
}
@@ -646,13 +646,13 @@ public class CherDObjectMgr implements DObjectManager
protected Queue _evqueue = new Queue();
/** The managed distributed objects table. */
protected IntMap _objects = new IntMap();
protected HashIntMap _objects = new HashIntMap();
/** Used to assign a unique oid to each distributed object. */
protected int _nextOid = 0;
/** Used to track oid list references of distributed objects. */
protected IntMap _refs = new IntMap();
protected HashIntMap _refs = new HashIntMap();
/** The default size of an oid list refs vector. */
protected static final int DEFREFVEC_SIZE = 4;
@@ -1,221 +0,0 @@
//
// $Id: IntMap.java,v 1.1 2001/06/01 19:56:13 mdb Exp $
package com.threerings.cocktail.cher.util;
import java.util.Enumeration;
import java.util.NoSuchElementException;
/**
* An int map is like a hash map, but with ints as keys. We avoid the
* annoyance of having to create <code>Integer</code> objects every time
* we want to lookup or insert values. Like <code>java.util.HashMap</code>
* it is not thread safe.
*/
public class IntMap
{
public final static int DEFAULT_BUCKETS = 64;
public IntMap (int buckets)
{
_buckets = new Record[buckets];
}
public IntMap ()
{
this(DEFAULT_BUCKETS);
}
public int size ()
{
return _size;
}
public void put (int key, Object value)
{
int index = Math.abs(key)%_buckets.length;
Record rec = _buckets[index];
// either we start a new chain
if (rec == null) {
_buckets[index] = new Record(key, value);
_size++; // we're bigger
return;
}
// or we replace an element in an existing chain
Record prev = rec;
for (; rec != null; rec = rec.next) {
if (rec.key == key) {
rec.value = value; // we're not bigger
return;
}
prev = rec;
}
// or we append it to this chain
prev.next = new Record(key, value);
_size++; // we're bigger
}
public Object get (int key)
{
int index = Math.abs(key)%_buckets.length;
for (Record rec = _buckets[index]; rec != null; rec = rec.next) {
if (rec.key == key) {
return rec.value;
}
}
return null;
}
public boolean contains (int key)
{
return get(key) != null;
}
public Object remove (int key)
{
int index = Math.abs(key)%_buckets.length;
Record rec = _buckets[index];
// if there's no chain, there's no object
if (rec == null) {
return null;
}
// maybe it's the first one in this chain
if (rec.key == key) {
_buckets[index] = rec.next;
_size--;
return rec.value;
}
// or maybe it's an element further down the chain
for (Record prev = rec; rec != null; rec = rec.next) {
if (rec.key == key) {
prev.next = rec.next;
_size--;
return rec.value;
}
prev = rec;
}
return null;
}
public void clear ()
{
// abandon all of our hash chains (the joy of garbage collection)
for (int i = 0; i < _buckets.length; i++) {
_buckets[i] = null;
}
// zero out our size
_size = 0;
}
public Enumeration keys ()
{
return new Enumerator(_buckets, true);
}
public Enumeration elements ()
{
return new Enumerator(_buckets, false);
}
protected static class Record
{
public Record next;
public int key;
public Object value;
public Record (int key, Object value)
{
this.key = key;
this.value = value;
}
}
class Enumerator implements Enumeration
{
public Enumerator (Record[] buckets, boolean returnKeys)
{
_buckets = buckets;
_index = buckets.length;
_returnKeys = returnKeys;
}
public boolean hasMoreElements ()
{
// if we're pointing to an entry, we've got more entries
if (_record != null) {
return true;
}
// search backward through the buckets looking for the next
// non-empty hash chain
while (_index-- > 0) {
if ((_record = _buckets[_index]) != null) {
return true;
}
}
// found no non-empty hash chains, we're done
return false;
}
public Object nextElement ()
{
// if we're not pointing to an entry, search for the next
// non-empty hash chain
if (_record == null) {
while ((_index-- > 0) &&
((_record = _buckets[_index]) == null));
}
// if we found a record, return it's value and move our record
// reference to it's successor
if (_record != null) {
Record r = _record;
_record = r.next;
return _returnKeys ? new Integer(r.key) : r.value;
}
throw new NoSuchElementException("IntMapEnumerator");
}
private int _index;
private Record _record;
private Record[] _buckets;
private boolean _returnKeys;
}
// public static void main (String[] args)
// {
// IntMap table = new IntMap();
// System.out.print("Inserting: ");
// for (int i = 10; i < 100; i++) {
// Integer value = new Integer(i);
// table.put(i, value);
// System.out.print("(" + i + "," + value + ")");
// }
// System.out.println("");
// System.out.print("Looking up: ");
// for (int i = 10; i < 100; i++) {
// System.out.print("(" + i + "," + table.get(i) + ")");
// }
// System.out.println("");
// System.out.print("Removing: ");
// for (int i = 10; i < 100; i++) {
// System.out.print("(" + i + "," + table.remove(i) + ")");
// }
// System.out.println("");
// }
private Record[] _buckets;
private int _size;
}
@@ -1,13 +1,13 @@
//
// $Id: SceneDirector.java,v 1.3 2001/10/01 22:16:02 mdb Exp $
// $Id: SceneDirector.java,v 1.4 2001/10/02 02:08:16 mdb Exp $
package com.threerings.whirled.client;
import java.io.IOException;
import com.samskivert.util.HashIntMap;
import com.threerings.cocktail.cher.dobj.DObject;
import com.threerings.cocktail.cher.dobj.ObjectAccessException;
import com.threerings.cocktail.cher.util.IntMap;
import com.threerings.cocktail.party.client.LocationDirector;
import com.threerings.cocktail.party.client.LocationObserver;
@@ -200,7 +200,7 @@ public class SceneDirector
protected WhirledContext _ctx;
protected SceneRepository _screp;
protected IntMap _scache = new IntMap();
protected HashIntMap _scache = new HashIntMap();
/** The scene object of the scene we currently occupy. */
protected Scene _scene;
@@ -1,10 +1,10 @@
//
// $Id: SceneService.java,v 1.3 2001/10/01 22:16:02 mdb Exp $
// $Id: SceneService.java,v 1.4 2001/10/02 02:08:16 mdb Exp $
package com.threerings.whirled.client;
import com.threerings.cocktail.cher.client.Client;
import com.threerings.cocktail.cher.client.InvocationManager;
import com.threerings.cocktail.cher.client.InvocationDirector;
import com.threerings.whirled.Log;
@@ -25,10 +25,10 @@ public class SceneService implements SceneCodes
public static void moveTo (Client client, int sceneId,
int sceneVers, SceneDirector rsptarget)
{
InvocationManager invmgr = client.getInvocationManager();
InvocationDirector invdir = client.getInvocationDirector();
Object[] args = new Object[] {
new Integer(sceneId), new Integer(sceneVers) };
invmgr.invoke(MODULE_NAME, MOVE_TO_REQUEST, args, rsptarget);
invdir.invoke(MODULE_NAME, MOVE_TO_REQUEST, args, rsptarget);
Log.info("Sent moveTo request [scene=" + sceneId +
", version=" + sceneVers + "].");
}
@@ -1,13 +1,13 @@
//
// $Id: SceneRegistry.java,v 1.2 2001/08/14 06:51:07 mdb Exp $
// $Id: SceneRegistry.java,v 1.3 2001/10/02 02:08:16 mdb Exp $
package com.threerings.whirled.server;
import java.util.ArrayList;
import java.util.Properties;
import com.samskivert.util.HashIntMap;
import com.threerings.cocktail.cher.util.Invoker;
import com.threerings.cocktail.cher.util.IntMap;
import com.threerings.cocktail.party.server.PartyServer;
@@ -159,14 +159,14 @@ public class SceneRegistry
// that is finally complete, then we can let our penders know
// what's up
// we'll eventually want to load up the proper properties file for
// the scene, but for now let's punt
try {
Properties props = new Properties();
SceneManager scmgr = (SceneManager)
PartyServer.plreg.createPlace(
SceneObject.class, SceneManager.class, props);
// configure the scene manager with references to useful stuff
PartyServer.plreg.createPlace(SceneManager.class);
// configure the scene manager with references to useful
// stuff; we'll somehow need to convey configuration
// information for the scene to the scene manager, but for now
// let's punt
scmgr.postInit(scene, this);
// when the scene manager completes its startup procedings, it
@@ -223,6 +223,6 @@ public class SceneRegistry
protected SceneRepository _screp;
protected Invoker _invoker;
protected IntMap _scenemgrs = new IntMap();
protected IntMap _penders = new IntMap();
protected HashIntMap _scenemgrs = new HashIntMap();
protected HashIntMap _penders = new HashIntMap();
}
@@ -1,5 +1,5 @@
//
// $Id: WhirledServer.java,v 1.4 2001/09/28 22:32:28 mdb Exp $
// $Id: WhirledServer.java,v 1.5 2001/10/02 02:08:16 mdb Exp $
package com.threerings.whirled.server;
@@ -61,7 +61,7 @@ public class WhirledServer extends PartyServer
* provider, it can override this method. The default mechanism is to
* load a properties file referenced by <code>dbmap</code> in the
* whirled server configuration and use those properties to create a
* {@link com.samskivert.jdbc.StaticConnectionProvider}.
* {@link StaticConnectionProvider}.
*
* @exception Exception thrown if an error occurs creating the
* connection provider.
@@ -1,5 +1,5 @@
//
// $Id: TestClient.java,v 1.8 2001/08/07 20:38:58 mdb Exp $
// $Id: TestClient.java,v 1.9 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.client.test;
@@ -42,8 +42,8 @@ public class TestClient
{
Log.info("Client did logon [client=" + client + "].");
// register our test notification receiver
client.getInvocationManager().registerReceiver(TestService.MODULE,
new TestReceiver());
client.getInvocationDirector().registerReceiver(TestService.MODULE,
new TestReceiver());
// get the test object id
TestService.getTestOid(client, this);
}
@@ -1,11 +1,11 @@
//
// $Id: TestService.java,v 1.2 2001/08/07 20:38:58 mdb Exp $
// $Id: TestService.java,v 1.3 2001/10/02 02:05:50 mdb Exp $
package com.threerings.cocktail.cher.client.test;
import com.threerings.cocktail.cher.Log;
import com.threerings.cocktail.cher.client.Client;
import com.threerings.cocktail.cher.client.InvocationManager;
import com.threerings.cocktail.cher.client.InvocationDirector;
/**
* A test of the invocation services.
@@ -17,16 +17,16 @@ public class TestService
public static void test (
Client client, String one, int two, Object rsptarget)
{
InvocationManager invmgr = client.getInvocationManager();
InvocationDirector invdir = client.getInvocationDirector();
Object[] args = new Object[] { one, new Integer(two) };
invmgr.invoke(MODULE, "Test", args, rsptarget);
invdir.invoke(MODULE, "Test", args, rsptarget);
Log.info("Sent test request [one=" + one + ", two=" + two + "].");
}
public static void getTestOid (Client client, Object rsptarget)
{
InvocationManager invmgr = client.getInvocationManager();
InvocationDirector invdir = client.getInvocationDirector();
Object[] args = new Object[0];
invmgr.invoke(MODULE, "GetTestOid", args, rsptarget);
invdir.invoke(MODULE, "GetTestOid", args, rsptarget);
}
}