Finished wiring up oid list tracking; made shutdown() work on the cher
server; added an easy mechanism to write test modules and invoke them on the server. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@192 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -3,8 +3,6 @@ Cher Notes -*- outline -*-
|
|||||||
* TODO
|
* TODO
|
||||||
Pass cause back to client somehow via FailureResponse in Client.requestFailed
|
Pass cause back to client somehow via FailureResponse in Client.requestFailed
|
||||||
|
|
||||||
Finish wiring up oid list tracking.
|
|
||||||
|
|
||||||
Ensure at time of OBJECT_ADDED that the object being added exists and has
|
Ensure at time of OBJECT_ADDED that the object being added exists and has
|
||||||
not been destroyed.
|
not been destroyed.
|
||||||
|
|
||||||
@@ -12,10 +10,6 @@ clientWillLogff becomes clientMayLogoff?
|
|||||||
|
|
||||||
Look into nbio waking up all sockets when any data comes in.
|
Look into nbio waking up all sockets when any data comes in.
|
||||||
|
|
||||||
Wire up Client.sessionDidTerminate; do session termination in general.
|
|
||||||
|
|
||||||
Clear out subscriptions when we lose connection from the client.
|
|
||||||
|
|
||||||
* Server-side event concentrator
|
* Server-side event concentrator
|
||||||
The client objects will not subscribe directly, but will subscribe through
|
The client objects will not subscribe directly, but will subscribe through
|
||||||
the concentrator so that, at least, it can create a single
|
the concentrator so that, at least, it can create a single
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: DObject.java,v 1.20 2001/08/07 20:38:58 mdb Exp $
|
// $Id: DObject.java,v 1.21 2001/08/08 00:28:49 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cocktail.cher.dobj;
|
package com.threerings.cocktail.cher.dobj;
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ public class DObject
|
|||||||
// scan the lock array to see if this lock is already acquired
|
// scan the lock array to see if this lock is already acquired
|
||||||
int slot = -1;
|
int slot = -1;
|
||||||
for (int i = 0; i < _locks.length; i++) {
|
for (int i = 0; i < _locks.length; i++) {
|
||||||
if (_locks[i] == null) {
|
if (_locks[i] == null && slot == -1) {
|
||||||
// keep track of this for later
|
// keep track of this for later
|
||||||
slot = i;
|
slot = i;
|
||||||
} else if (name.equals(_locks[i])) {
|
} else if (name.equals(_locks[i])) {
|
||||||
@@ -343,6 +343,17 @@ public class DObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this object is active and registered with the
|
||||||
|
* distributed object system. If an object is created via
|
||||||
|
* <code>DObjectManager.createObject</code> it will be active until
|
||||||
|
* such time as it is destroyed.
|
||||||
|
*/
|
||||||
|
public boolean isActive ()
|
||||||
|
{
|
||||||
|
return _mgr != null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Don't call this function! It initializes this distributed object
|
* Don't call this function! It initializes this distributed object
|
||||||
* with the supplied distributed object manager. This is called by the
|
* with the supplied distributed object manager. This is called by the
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
//
|
//
|
||||||
// $Id: PresentsDObjectMgr.java,v 1.11 2001/08/07 21:25:13 mdb Exp $
|
// $Id: PresentsDObjectMgr.java,v 1.12 2001/08/08 00:28:49 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cocktail.cher.server;
|
package com.threerings.cocktail.cher.server;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.*;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import com.samskivert.util.Queue;
|
import com.samskivert.util.Queue;
|
||||||
@@ -172,9 +172,191 @@ public class CherDObjectMgr implements DObjectManager
|
|||||||
*/
|
*/
|
||||||
public void objectDestroyed (DEvent event, DObject target)
|
public void objectDestroyed (DEvent event, DObject target)
|
||||||
{
|
{
|
||||||
// Log.info("Removing destroyed object from table " +
|
int oid = target.getOid();
|
||||||
// "[oid=" + target.getOid() + "].");
|
|
||||||
_objects.remove(target.getOid());
|
// Log.info("Removing destroyed object from table " +
|
||||||
|
// "[oid=" + oid + "].");
|
||||||
|
|
||||||
|
// remove the object from the table
|
||||||
|
_objects.remove(oid);
|
||||||
|
|
||||||
|
// inactivate the object
|
||||||
|
target.setManager(null);
|
||||||
|
|
||||||
|
// deal with any remaining oid lists that reference this object
|
||||||
|
Reference[] refs = (Reference[])_refs.remove(oid);
|
||||||
|
if (refs != null) {
|
||||||
|
for (int i = 0; i < refs.length; i++) {
|
||||||
|
// skip empty spots
|
||||||
|
if (refs[i] == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference ref = refs[i];
|
||||||
|
DObject reffer = (DObject)_objects.get(ref.reffingOid);
|
||||||
|
|
||||||
|
// ensure that the referencing object is still around
|
||||||
|
if (reffer != null) {
|
||||||
|
// post an object removed event to clear the reference
|
||||||
|
postEvent(new ObjectRemovedEvent(
|
||||||
|
ref.reffingOid, ref.field, oid));
|
||||||
|
// Log.info("Forcing removal " + ref + ".");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.info("Dangling reference from inactive object " +
|
||||||
|
ref + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this object has any oid list fields that are still
|
||||||
|
// referencing other objects, we need to clear out those
|
||||||
|
// references
|
||||||
|
Class oclass = target.getClass();
|
||||||
|
Field[] fields = oclass.getFields();
|
||||||
|
for (int f = 0; f < fields.length; f++) {
|
||||||
|
Field field = fields[f];
|
||||||
|
|
||||||
|
// ignore static and non-public fields
|
||||||
|
int mods = field.getModifiers();
|
||||||
|
if ((mods & Modifier.STATIC) != 0 ||
|
||||||
|
(mods & Modifier.PUBLIC) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore non-oidlist fields
|
||||||
|
if (!OidList.class.isAssignableFrom(field.getType())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
OidList list = (OidList)field.get(target);
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
clearReference(target, field.getName(), list.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to clean up after oid list field " +
|
||||||
|
"[target=" + target + ", field=" + field + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by <code>objectDestroyed</code>; clears out the tracking
|
||||||
|
* info for a reference by the supplied object to the specified oid
|
||||||
|
* via the specified field.
|
||||||
|
*/
|
||||||
|
protected void clearReference (
|
||||||
|
DObject reffer, String field, int reffedOid)
|
||||||
|
{
|
||||||
|
// look up the reference vector for the referenced object
|
||||||
|
Reference[] refs = (Reference[])_refs.get(reffedOid);
|
||||||
|
Reference ref = null;
|
||||||
|
|
||||||
|
if (refs != null) {
|
||||||
|
for (int i = 0; i < refs.length; i++) {
|
||||||
|
if (refs[i].equals(reffer.getOid(), field)) {
|
||||||
|
ref = refs[i];
|
||||||
|
refs[i] = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref == null) {
|
||||||
|
Log.warning("Requested to clear out non-existent reference " +
|
||||||
|
"[refferOid=" + reffer.getOid() +
|
||||||
|
", field=" + field +
|
||||||
|
", reffedOid=" + reffedOid + "].");
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// Log.info("Cleared out reference " + ref + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called as a helper for <code>ObjectAddedEvent</code> events. It
|
||||||
|
* updates the object/oid list tracking structures.
|
||||||
|
*/
|
||||||
|
public void objectAdded (DEvent event, DObject target)
|
||||||
|
{
|
||||||
|
ObjectAddedEvent oae = (ObjectAddedEvent)event;
|
||||||
|
int oid = oae.getOid();
|
||||||
|
Reference ref = new Reference(target.getOid(), oae.getName(), oid);
|
||||||
|
|
||||||
|
// get the reference vector for the referenced object. we use bare
|
||||||
|
// arrays rather than something like an array list to conserve
|
||||||
|
// memory. there will be many objects and references
|
||||||
|
Reference[] refs = (Reference[])_refs.get(oid);
|
||||||
|
if (refs == null) {
|
||||||
|
refs = new Reference[DEFREFVEC_SIZE];
|
||||||
|
_refs.put(oid, refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine where to add the reference
|
||||||
|
int rpos = -1;
|
||||||
|
for (int i = 0; i < refs.length; i++) {
|
||||||
|
if (ref.equals(refs[i])) {
|
||||||
|
Log.warning("Ignoring request to track existing " +
|
||||||
|
"reference " + ref + ".");
|
||||||
|
return;
|
||||||
|
} else if (refs[i] == null && rpos == -1) {
|
||||||
|
rpos = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand the refvec if necessary
|
||||||
|
if (rpos == -1) {
|
||||||
|
Reference[] nrefs = new Reference[refs.length*2];
|
||||||
|
System.arraycopy(refs, 0, nrefs, 0, refs.length);
|
||||||
|
rpos = refs.length;
|
||||||
|
_refs.put(oid, refs = nrefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally add the reference
|
||||||
|
refs[rpos] = ref;
|
||||||
|
|
||||||
|
// Log.info("Tracked reference " + ref + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called as a helper for <code>ObjectRemovedEvent</code> events. It
|
||||||
|
* updates the object/oid list tracking structures.
|
||||||
|
*/
|
||||||
|
public void objectRemoved (DEvent event, DObject target)
|
||||||
|
{
|
||||||
|
ObjectRemovedEvent ore = (ObjectRemovedEvent)event;
|
||||||
|
String field = ore.getName();
|
||||||
|
int toid = target.getOid();
|
||||||
|
int oid = ore.getOid();
|
||||||
|
|
||||||
|
// get the reference vector for the referenced object
|
||||||
|
Reference[] refs = (Reference[])_refs.get(oid);
|
||||||
|
if (refs == null) {
|
||||||
|
// this can happen normally when an object is destroyed. it
|
||||||
|
// will remove itself from the reference system and then
|
||||||
|
// generate object removed events for all of its referencees.
|
||||||
|
// so we opt not to log anything in this case
|
||||||
|
|
||||||
|
// Log.warning("Object removed without reference to track it " +
|
||||||
|
// "[toid=" + toid + ", field=" + field +
|
||||||
|
// ", oid=" + oid + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for the matching reference
|
||||||
|
for (int i = 0; i < refs.length; i++) {
|
||||||
|
if (refs[i].equals(toid, field)) {
|
||||||
|
// Log.info("Removed reference " + refs[i] + ".");
|
||||||
|
refs[i] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.warning("Unable to locate reference for removal " +
|
||||||
|
"[reffingOid=" + toid + ", field=" + field +
|
||||||
|
", reffedOid=" + oid + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized boolean isRunning ()
|
protected synchronized boolean isRunning ()
|
||||||
@@ -224,7 +406,7 @@ public class CherDObjectMgr implements DObjectManager
|
|||||||
// insert it into the table
|
// insert it into the table
|
||||||
_objects.put(oid, obj);
|
_objects.put(oid, obj);
|
||||||
|
|
||||||
// Log.info("Created object [obj=" + obj + "].");
|
// Log.info("Created object [obj=" + obj + "].");
|
||||||
|
|
||||||
if (_target != null) {
|
if (_target != null) {
|
||||||
// add the subscriber to this object's subscriber list
|
// add the subscriber to this object's subscriber list
|
||||||
@@ -351,17 +533,74 @@ public class CherDObjectMgr implements DObjectManager
|
|||||||
method = omgrcl.getMethod("objectDestroyed", ptypes);
|
method = omgrcl.getMethod("objectDestroyed", ptypes);
|
||||||
_helpers.put(ObjectDestroyedEvent.class, method);
|
_helpers.put(ObjectDestroyedEvent.class, method);
|
||||||
|
|
||||||
|
method = omgrcl.getMethod("objectAdded", ptypes);
|
||||||
|
_helpers.put(ObjectAddedEvent.class, method);
|
||||||
|
|
||||||
|
method = omgrcl.getMethod("objectRemoved", ptypes);
|
||||||
|
_helpers.put(ObjectRemovedEvent.class, method);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.warning("Unable to register event helpers " +
|
Log.warning("Unable to register event helpers " +
|
||||||
"[error=" + e + "].");
|
"[error=" + e + "].");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to track references of objects in oid lists.
|
||||||
|
*/
|
||||||
|
protected static class Reference
|
||||||
|
{
|
||||||
|
public int reffingOid;
|
||||||
|
public String field;
|
||||||
|
public int reffedOid;
|
||||||
|
|
||||||
|
public Reference (int reffingOid, String field, int reffedOid)
|
||||||
|
{
|
||||||
|
this.reffingOid = reffingOid;
|
||||||
|
this.field = field;
|
||||||
|
this.reffedOid = reffedOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals (Reference other)
|
||||||
|
{
|
||||||
|
if (other == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return (reffingOid == other.reffingOid &&
|
||||||
|
field.equals(other.field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals (int reffingOid, String field)
|
||||||
|
{
|
||||||
|
return (this.reffingOid == reffingOid && this.field.equals(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString ()
|
||||||
|
{
|
||||||
|
return "[reffingOid=" + reffingOid + ", field=" + field +
|
||||||
|
", reffedOid=" + reffedOid + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A flag indicating that the event dispatcher is still running. */
|
||||||
protected boolean _running = true;
|
protected boolean _running = true;
|
||||||
|
|
||||||
|
/** The event queue via which all events are processed. */
|
||||||
protected Queue _evqueue = new Queue();
|
protected Queue _evqueue = new Queue();
|
||||||
|
|
||||||
|
/** The managed distributed objects table. */
|
||||||
protected IntMap _objects = new IntMap();
|
protected IntMap _objects = new IntMap();
|
||||||
|
|
||||||
|
/** Used to assign a unique oid to each distributed object. */
|
||||||
protected int _nextOid = 0;
|
protected int _nextOid = 0;
|
||||||
|
|
||||||
|
/** Used to track oid list references of distributed objects. */
|
||||||
|
protected IntMap _refs = new IntMap();
|
||||||
|
|
||||||
|
/** The default size of an oid list refs vector. */
|
||||||
|
protected static final int DEFREFVEC_SIZE = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This table maps event classes to helper methods that perform some
|
* This table maps event classes to helper methods that perform some
|
||||||
* additional processing for particular events.
|
* additional processing for particular events.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: PresentsServer.java,v 1.9 2001/07/19 21:29:01 mdb Exp $
|
// $Id: PresentsServer.java,v 1.10 2001/08/08 00:28:49 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cocktail.cher.server;
|
package com.threerings.cocktail.cher.server;
|
||||||
|
|
||||||
@@ -132,15 +132,49 @@ public class CherServer
|
|||||||
// start up the connection manager
|
// start up the connection manager
|
||||||
conmgr.start();
|
conmgr.start();
|
||||||
// invoke the dobjmgr event loop
|
// invoke the dobjmgr event loop
|
||||||
((CherDObjectMgr)omgr).run();
|
omgr.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the server shut down.
|
||||||
|
*/
|
||||||
|
public static void shutdown ()
|
||||||
|
{
|
||||||
|
// shut down our managers
|
||||||
|
authmgr.shutdown();
|
||||||
|
conmgr.shutdown();
|
||||||
|
omgr.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main (String[] args)
|
public static void main (String[] args)
|
||||||
{
|
{
|
||||||
|
Log.info("Cher server starting...");
|
||||||
|
|
||||||
CherServer server = new CherServer();
|
CherServer server = new CherServer();
|
||||||
try {
|
try {
|
||||||
|
// initialize the server
|
||||||
server.init();
|
server.init();
|
||||||
|
|
||||||
|
// check to see if we should load and invoke a test module
|
||||||
|
// before running the server
|
||||||
|
String testmod = System.getProperty("test_module");
|
||||||
|
if (testmod != null) {
|
||||||
|
try {
|
||||||
|
Log.info("Invoking test module [mod=" + testmod + "].");
|
||||||
|
Class tmclass = Class.forName(testmod);
|
||||||
|
Runnable trun = (Runnable)tmclass.newInstance();
|
||||||
|
trun.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.warning("Unable to invoke test module " +
|
||||||
|
"[mod=" + testmod + "].");
|
||||||
|
Log.logStackTrace(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the server to running (this method call won't return
|
||||||
|
// until the server is shut down)
|
||||||
server.run();
|
server.run();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.warning("Unable to initialize server.");
|
Log.warning("Unable to initialize server.");
|
||||||
Log.logStackTrace(e);
|
Log.logStackTrace(e);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: AuthManager.java,v 1.3 2001/06/01 22:12:03 mdb Exp $
|
// $Id: AuthManager.java,v 1.4 2001/08/08 00:28:49 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cocktail.cher.server.net;
|
package com.threerings.cocktail.cher.server.net;
|
||||||
|
|
||||||
@@ -55,8 +55,16 @@ public class AuthManager extends LoopingThread
|
|||||||
protected void iterate ()
|
protected void iterate ()
|
||||||
{
|
{
|
||||||
// grab the next authing connection from the queue
|
// grab the next authing connection from the queue
|
||||||
AuthingConnection aconn = (AuthingConnection)_authq.get();
|
Object item = _authq.get();
|
||||||
|
|
||||||
|
// if we're being kicked and requested to exit, we'll just post
|
||||||
|
// some bogus item on the queue to wake up the auth manager and
|
||||||
|
// get him the hell out of dodge
|
||||||
|
if (!(item instanceof AuthingConnection)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthingConnection aconn = (AuthingConnection)item;
|
||||||
try {
|
try {
|
||||||
// instruct the authenticator to process the auth request
|
// instruct the authenticator to process the auth request
|
||||||
AuthResponse rsp = _author.process(aconn.getAuthRequest());
|
AuthResponse rsp = _author.process(aconn.getAuthRequest());
|
||||||
@@ -74,6 +82,12 @@ public class AuthManager extends LoopingThread
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void kick ()
|
||||||
|
{
|
||||||
|
// we post something bogus to the queue to wake up the authmgr
|
||||||
|
_authq.append(new Integer(0));
|
||||||
|
}
|
||||||
|
|
||||||
protected Authenticator _author;
|
protected Authenticator _author;
|
||||||
protected ConnectionManager _conmgr;
|
protected ConnectionManager _conmgr;
|
||||||
protected Queue _authq = new Queue();
|
protected Queue _authq = new Queue();
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// $Id: RefTest.java,v 1.1 2001/08/08 00:28:49 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.cocktail.cher.server.test;
|
||||||
|
|
||||||
|
import com.threerings.cocktail.cher.Log;
|
||||||
|
import com.threerings.cocktail.cher.dobj.*;
|
||||||
|
import com.threerings.cocktail.cher.server.CherServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the oid list reference tracking code.
|
||||||
|
*/
|
||||||
|
public class RefTest
|
||||||
|
implements Runnable, Subscriber
|
||||||
|
{
|
||||||
|
public void run ()
|
||||||
|
{
|
||||||
|
// create two test objects
|
||||||
|
CherServer.omgr.createObject(TestObject.class, this, true);
|
||||||
|
CherServer.omgr.createObject(TestObject.class, this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void objectAvailable (DObject object)
|
||||||
|
{
|
||||||
|
// keep references to our test objects
|
||||||
|
if (_objone == null) {
|
||||||
|
_objone = (TestObject)object;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_objtwo = (TestObject)object;
|
||||||
|
|
||||||
|
// now that we have both objects, set up the references
|
||||||
|
_objone.addToList(_objtwo.getOid());
|
||||||
|
_objtwo.addToList(_objone.getOid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestFailed (int oid, ObjectAccessException cause)
|
||||||
|
{
|
||||||
|
Log.warning("Ack. Unable to create object [cause=" + cause + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean handleEvent (DEvent event, DObject target)
|
||||||
|
{
|
||||||
|
// Log.info("Got event: " + event);
|
||||||
|
|
||||||
|
// once we receive the second object added we can destroy the
|
||||||
|
// target object to see if the reference is cleaned up
|
||||||
|
if (event instanceof ObjectAddedEvent && target == _objtwo) {
|
||||||
|
Log.info("Destroying object two " + _objtwo + ".");
|
||||||
|
_objtwo.destroy();
|
||||||
|
|
||||||
|
} else if (event instanceof ObjectDestroyedEvent) {
|
||||||
|
if (target == _objtwo) {
|
||||||
|
Log.info("List won't yet be empty: " + _objone.list);
|
||||||
|
} else {
|
||||||
|
Log.info("Other object destroyed.");
|
||||||
|
// go bye bye
|
||||||
|
CherServer.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (event instanceof ObjectRemovedEvent) {
|
||||||
|
Log.info("List should be empty: " + _objone.list);
|
||||||
|
// finally destroy the other object to complete the circle
|
||||||
|
_objone.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TestObject _objone;
|
||||||
|
protected TestObject _objtwo;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: TestObject.dobj,v 1.2 2001/07/19 05:56:20 mdb Exp $
|
// $Id: TestObject.dobj,v 1.3 2001/08/08 00:28:49 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.cocktail.cher.server.test;
|
package com.threerings.cocktail.cher.server.test;
|
||||||
|
|
||||||
@@ -12,12 +12,12 @@ import com.threerings.cocktail.cher.dobj.*;
|
|||||||
public class TestObject extends DObject
|
public class TestObject extends DObject
|
||||||
{
|
{
|
||||||
public static final String FOO = "foo";
|
public static final String FOO = "foo";
|
||||||
|
public static final String BAR = "bar";
|
||||||
|
public static final String LIST = "list";
|
||||||
|
|
||||||
public int foo;
|
public int foo;
|
||||||
|
|
||||||
public static final String BAR = "bar";
|
|
||||||
|
|
||||||
public String bar;
|
public String bar;
|
||||||
|
public OidList list = new OidList();
|
||||||
|
|
||||||
public void setFoo (int foo)
|
public void setFoo (int foo)
|
||||||
{
|
{
|
||||||
@@ -29,8 +29,29 @@ public class TestObject extends DObject
|
|||||||
requestAttributeChange(BAR, bar);
|
requestAttributeChange(BAR, bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString ()
|
/**
|
||||||
|
* Requests that the specified oid be added to the
|
||||||
|
* <code>list</code> oid list.
|
||||||
|
*/
|
||||||
|
public void addToList (int oid)
|
||||||
{
|
{
|
||||||
return "[foo=" + foo + ", bar=" + bar + "]";
|
requestOidAdd(LIST, oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests that the specified oid be removed from the
|
||||||
|
* <code>list</code> oid list.
|
||||||
|
*/
|
||||||
|
public void removeFromList (int oid)
|
||||||
|
{
|
||||||
|
requestOidRemove(LIST, oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void toString (StringBuffer buf)
|
||||||
|
{
|
||||||
|
super.toString(buf);
|
||||||
|
buf.append(", foo=").append(foo);
|
||||||
|
buf.append(", bar=").append(bar);
|
||||||
|
buf.append(", list=").append(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user