diff --git a/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java b/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java index 9e96b9adc..25fdf5711 100644 --- a/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java +++ b/src/java/com/threerings/crowd/peer/server/CrowdPeerManager.java @@ -105,24 +105,9 @@ public class CrowdPeerManager extends PeerManager } @Override // documentation inherited - protected void finishInit (NodeObject nodeobj) + protected NodeObject createNodeObject () { - super.finishInit(nodeobj); - - // register and initialize our invocation service - CrowdNodeObject cnobj = (CrowdNodeObject)nodeobj; - cnobj.setCrowdPeerService( - (CrowdPeerMarshaller)CrowdServer.invmgr.registerDispatcher( - new CrowdPeerDispatcher(this), false)); - - // register ourselves as a tell forwarder - CrowdServer.chatprov.setTellForwarder(this); - } - - @Override // documentation inherited - protected Class getNodeObjectClass () - { - return CrowdNodeObject.class; + return new CrowdNodeObject(); } @Override // documentation inherited @@ -138,4 +123,19 @@ public class CrowdPeerManager extends PeerManager ((CrowdClientInfo)info).visibleName = ((BodyObject)client.getClientObject()).getVisibleName(); } + + @Override // documentation inherited + protected void didInit () + { + super.didInit(); + + // register and initialize our invocation service + CrowdNodeObject cnobj = (CrowdNodeObject)_nodeobj; + cnobj.setCrowdPeerService( + (CrowdPeerMarshaller)CrowdServer.invmgr.registerDispatcher( + new CrowdPeerDispatcher(this), false)); + + // register ourselves as a tell forwarder + CrowdServer.chatprov.setTellForwarder(this); + } } diff --git a/src/java/com/threerings/crowd/server/CrowdClientResolver.java b/src/java/com/threerings/crowd/server/CrowdClientResolver.java index 9e0c75b60..cc657dd7e 100644 --- a/src/java/com/threerings/crowd/server/CrowdClientResolver.java +++ b/src/java/com/threerings/crowd/server/CrowdClientResolver.java @@ -32,9 +32,9 @@ import com.threerings.crowd.data.BodyObject; public class CrowdClientResolver extends ClientResolver { // documentation inherited - public Class getClientObjectClass () + public ClientObject createClientObject () { - return BodyObject.class; + return new BodyObject(); } // documentation inherited diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index b3ffd0610..108b474b8 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -161,17 +161,20 @@ public class PlaceManager } /** - * A place manager derived class is likely to have a corresponding - * derived class of {@link com.threerings.crowd.data.PlaceObject} that - * it will be managing. Derived classes should override this method - * and return the class object for the place object derived class they - * desire to use. The place registry will use this method to create - * the proper place object during the place creation process. - * - * @return the class of the class, derived from {@link PlaceObject}, - * that this manager wishes to manage. - * - * @see PlaceRegistry#createPlace + * Derived classes will generally override this method to create a custom + * {@link PlaceObject} derivation that contains extra information. + */ + protected PlaceObject createPlaceObject () + { + try { + return getPlaceObjectClass().newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * @deprecated Use {@link #createPlaceObject}. */ protected Class getPlaceObjectClass () { diff --git a/src/java/com/threerings/crowd/server/PlaceRegistry.java b/src/java/com/threerings/crowd/server/PlaceRegistry.java index 815de071c..b37ae598f 100644 --- a/src/java/com/threerings/crowd/server/PlaceRegistry.java +++ b/src/java/com/threerings/crowd/server/PlaceRegistry.java @@ -24,13 +24,8 @@ package com.threerings.crowd.server; import java.util.Iterator; import com.samskivert.util.HashIntMap; -import com.samskivert.util.Tuple; -import com.samskivert.util.Queue; -import com.threerings.presents.dobj.DObject; -import com.threerings.presents.dobj.ObjectAccessException; import com.threerings.presents.dobj.RootDObjectManager; -import com.threerings.presents.dobj.Subscriber; import com.threerings.presents.server.InvocationException; import com.threerings.presents.server.InvocationManager; @@ -45,21 +40,11 @@ import com.threerings.crowd.data.PlaceObject; * places. */ public class PlaceRegistry - implements Subscriber { - /** - * Used to receive a callback when the place object associated with a - * place manager (created via {@link PlaceRegistry#createPlace}) is - * created. - */ - public static interface CreationObserver + /** Used in conjunction with {@link #createPlace}. */ + public static interface PreStartupHook { - /** - * Called when the place object is created and after it is - * provided to the place manager that will be handling management - * of the place. - */ - public void placeCreated (PlaceObject place, PlaceManager pmgr); + public void invoke (PlaceManager plmgr); } /** The location provider used by the place registry to provide @@ -98,31 +83,39 @@ public class PlaceRegistry } /** - * Creates and registers a new place manager along with the place - * object to be managed. The registry takes care of tracking the - * creation of the object and informing the manager when it is - * created. + * Creates and registers a new place manager along with the place object to + * be managed. The registry takes care of tracking the creation of the + * object and informing the manager when it is created. * - * @param config the configuration object for the place to be - * created. The {@link PlaceManager} derived class that should be - * instantiated to manage the place will be determined from the config - * object. - * @param observer an observer that will be notified when the place - * object creation has completed (called after the place object is - * provided to the place manager). + * @param config the configuration object for the place to be created. The + * {@link PlaceManager} derived class that should be instantiated to manage + * the place will be determined from the config object. * - * @return a reference to the place manager that will manage the new - * place object. + * @return a reference to the place manager, which will have been + * configured with its place object and started up (via a call to {@link + * PlaceManager#startup}. * - * @exception InstantiationException thrown if an error occurs trying - * to instantiate and initialize the place manager. + * @exception InstantiationException thrown if an error occurs trying to + * instantiate and initialize the place manager. * @exception InvocationException thrown if the place manager returns * failure from the call to {@link PlaceManager#checkPermissions}. The - * error string returned by that call will be provided as in the - * exception. + * error string returned by that call will be provided as in the exception. */ - public PlaceManager createPlace ( - PlaceConfig config, CreationObserver observer) + public PlaceManager createPlace (PlaceConfig config) + throws InstantiationException, InvocationException + { + return createPlace(config, null); + } + + /** + * Don't use this method, see {@link #createPlace(PlaceConfig)}.. + * + * @param hook an optional pre-startup hook that allows a place manager to + * be configured prior to having {@link PlaceManager#startup} called. This + * mainly exists because it used to be possible to do such things. Try not + * to use this in new code. + */ + public PlaceManager createPlace (PlaceConfig config, PreStartupHook hook) throws InstantiationException, InvocationException { PlaceManager pmgr = null; @@ -153,16 +146,25 @@ public class PlaceRegistry throw new InvocationException(errmsg); } - // stick the manager on the creation queue because we know - // we'll get our calls to objectAvailable()/requestFailed() in - // the order that we call createObject() - _createq.append( - new Tuple(pmgr, observer)); + // and create and register the place object + PlaceObject plobj = pmgr.createPlaceObject(); + _omgr.registerObject(plobj); - // and request to create the place object - @SuppressWarnings("unchecked") Class pclass = - (Class)pmgr.getPlaceObjectClass(); - _omgr.createObject(pclass, this); + // stick the manager into our table + _pmgrs.put(plobj.getOid(), pmgr); + + // start the place manager up with the newly created place object + try { + if (hook != null) { + hook.invoke(pmgr); + } + + pmgr.startup(plobj); + } catch (Exception e) { + Log.warning("Error starting place manager [obj=" + plobj + + ", pmgr=" + pmgr + "]."); + Log.logStackTrace(e); + } return pmgr; } @@ -213,63 +215,6 @@ public class PlaceRegistry return _pmgrs.values().iterator(); } - // documentation inherited - public void objectAvailable (PlaceObject plobj) - { - // pop the next place manager off of the queue and let it know - // that everything went swimmingly - Tuple tuple = _createq.getNonBlocking(); - if (tuple == null) { - Log.warning("Place created but no manager queued up to hear " + - "about it!? [pobj=" + plobj + "]."); - return; - } - - PlaceManager pmgr = tuple.left; - CreationObserver observer = tuple.right; - - // stick the manager into our table - _pmgrs.put(plobj.getOid(), pmgr); - - // start the place manager up with the newly created place object - try { - pmgr.startup(plobj); - } catch (Exception e) { - Log.warning("Error starting place manager [obj=" + plobj + - ", pmgr=" + pmgr + "]."); - Log.logStackTrace(e); - } - - // inform the creation observer that the place object was created - // and provided to the manager - if (observer != null) { - try { - observer.placeCreated(plobj, pmgr); - } catch (Exception e) { - Log.warning("Error informing CreationObserver of place " + - "[obj=" + plobj + ", pmgr=" + pmgr + - ", obs=" + observer + "]."); - Log.logStackTrace(e); - } - } - } - - // documentation inherited - public void requestFailed (int oid, ObjectAccessException cause) - { - // pop a place manager off the queue since it is queued up to - // manage the failed place object - Tuple tuple = _createq.getNonBlocking(); - if (tuple == null) { - Log.warning("Place creation failed but no manager queued " + - "up to hear about it!? [cause=" + cause + "]."); - return; - } - - Log.warning("Failed to create place object [mgr=" + tuple.left + - ", cause=" + cause + "]."); - } - /** * Called by the place manager when it has been shut down. */ @@ -294,10 +239,6 @@ public class PlaceRegistry /** The distributed object manager with which we operate. */ protected RootDObjectManager _omgr; - /** A queue of place managers waiting for their place objects. */ - protected Queue> _createq = - new Queue>(); - /** A mapping from place object id to place manager. */ protected HashIntMap _pmgrs = new HashIntMap(); } diff --git a/src/java/com/threerings/presents/client/ClientDObjectMgr.java b/src/java/com/threerings/presents/client/ClientDObjectMgr.java index fc6e071b0..74c436adc 100644 --- a/src/java/com/threerings/presents/client/ClientDObjectMgr.java +++ b/src/java/com/threerings/presents/client/ClientDObjectMgr.java @@ -82,14 +82,6 @@ public class ClientDObjectMgr return false; } - // inherit documentation from the interface - public void createObject ( - Class dclass, Subscriber target) - { - // not presently supported - throw new RuntimeException("createObject() not supported"); - } - // inherit documentation from the interface public void subscribeToObject ( int oid, Subscriber target) @@ -125,13 +117,6 @@ public class ClientDObjectMgr _comm.postMessage(new ForwardEventRequest(event)); } - // inherit documentation from the interface - public void destroyObject (int oid) - { - // forward an object destroyed event to the server - postEvent(new ObjectDestroyedEvent(oid)); - } - // inherit documentation from the interface public void removedLastSubscriber (DObject obj, boolean deathWish) { diff --git a/src/java/com/threerings/presents/dobj/DObjectManager.java b/src/java/com/threerings/presents/dobj/DObjectManager.java index 5e45d3cf7..59d9409a1 100644 --- a/src/java/com/threerings/presents/dobj/DObjectManager.java +++ b/src/java/com/threerings/presents/dobj/DObjectManager.java @@ -39,23 +39,6 @@ public interface DObjectManager */ public boolean isManager (DObject object); - /** - * Creates a distributed object instance of the supplied class and - * notifies the specified subscriber when it becomes available. This - * is the proper mechanism for constructing a new distributed object - * as it is the only way in which it can be properly registered with - * the dobj system. - * - * @param dclass The class object of the derived class of - * DObject (or DObject.class itself) that - * should be instantiated. - * @param target The subscriber to be notified when the object is - * created and available, or if there was a problem creating the - * object. - */ - public void createObject ( - Class dclass, Subscriber target); - /** * Requests that the specified subscriber be subscribed to the object * identified by the supplied object id. That subscriber will be @@ -83,15 +66,6 @@ public interface DObjectManager public void unsubscribeFromObject ( int oid, Subscriber target); - /** - * Requests that the specified object be destroyed. Once destroyed an - * object is removed from the runtime system and may no longer have - * events dispatched on it. - * - * @param oid The object id of the distributed object to be destroyed. - */ - public void destroyObject (int oid); - /** * Posts a distributed object event into the system. Instead of * requesting the modification of a distributed object attribute by diff --git a/src/java/com/threerings/presents/dobj/RootDObjectManager.java b/src/java/com/threerings/presents/dobj/RootDObjectManager.java index 4762dc4ac..c69818e98 100644 --- a/src/java/com/threerings/presents/dobj/RootDObjectManager.java +++ b/src/java/com/threerings/presents/dobj/RootDObjectManager.java @@ -35,4 +35,22 @@ public interface RootDObjectManager extends DObjectManager * table, returning null if no object exists with that oid. */ public DObject getObject (int oid); + + /** + * Registers a distributed object instance of the supplied class with the + * system and assigns it an oid. When the call returns the object will be + * registered with the system and its oid will have been assigned. + * + * @return the registered object for the caller's convenience. + */ + public T registerObject (T object); + + /** + * Requests that the specified object be destroyed. Once destroyed an + * object is removed from the runtime system and may no longer have + * events dispatched on it. + * + * @param oid The object id of the distributed object to be destroyed. + */ + public void destroyObject (int oid); } diff --git a/src/java/com/threerings/presents/peer/server/PeerManager.java b/src/java/com/threerings/presents/peer/server/PeerManager.java index a9946bfc1..19d5d0a26 100644 --- a/src/java/com/threerings/presents/peer/server/PeerManager.java +++ b/src/java/com/threerings/presents/peer/server/PeerManager.java @@ -116,16 +116,36 @@ public class PeerManager this, PresentsServer.clmgr.getClientFactory())); // create our node object - @SuppressWarnings("unchecked") Class clazz = - (Class)getNodeObjectClass(); - PresentsServer.omgr.createObject(clazz, new Subscriber() { - public void objectAvailable (NodeObject object) { - finishInit(object); - } - public void requestFailed (int oid, ObjectAccessException cause) { - log.warning("Failed to create NodeObject: " + cause + "."); + _nodeobj = PresentsServer.omgr.registerObject(createNodeObject()); + + // register ourselves with the node table + _invoker.postUnit(new Invoker.Unit() { + public boolean invoke () { + NodeRecord record = new NodeRecord( + _nodeName, _hostName, _publicHostName, _port); + try { + _noderepo.updateNode(record); + } catch (PersistenceException pe) { + log.warning("Failed to register node record " + + "[rec=" + record + ", error=" + pe + "]."); + } + return false; } }); + + // register ourselves as a client observer + PresentsServer.clmgr.addClientObserver(this); + + // and start our peer refresh interval (this need not use a runqueue as + // all it will do is post an invoker unit) + new Interval() { + public void expired () { + refreshPeers(); + } + }.schedule(5000L, 60*1000L); + + // give derived classes an easy way to get in on the init action + didInit(); } /** @@ -201,38 +221,10 @@ public class PeerManager } /** - * Called once our node object is available. + * Called after we have finished our initialization. */ - protected void finishInit (NodeObject nodeobj) + protected void didInit () { - // keep a handle on our node object - _nodeobj = nodeobj; - - // register ourselves with the node table - _invoker.postUnit(new Invoker.Unit() { - public boolean invoke () { - NodeRecord record = new NodeRecord( - _nodeName, _hostName, _publicHostName, _port); - try { - _noderepo.updateNode(record); - } catch (PersistenceException pe) { - log.warning("Failed to register node record " + - "[rec=" + record + ", error=" + pe + "]."); - } - return false; - } - }); - - // register ourselves as a client observer - PresentsServer.clmgr.addClientObserver(this); - - // and start our peer refresh interval (this need not use a runqueue as - // all it will do is post an invoker unit) - new Interval() { - public void expired () { - refreshPeers(); - } - }.schedule(5000L, 60*1000L); } /** @@ -284,11 +276,12 @@ public class PeerManager } /** - * Returns the class we use when creating our {@link NodeObject}. + * Creates the appropriate derived class of {@link NodeObject} which will + * be registered with the distributed object system. */ - protected Class getNodeObjectClass () + protected NodeObject createNodeObject () { - return NodeObject.class; + return new NodeObject(); } /** diff --git a/src/java/com/threerings/presents/server/ClientManager.java b/src/java/com/threerings/presents/server/ClientManager.java index 519aff8d0..d2ad75fd7 100644 --- a/src/java/com/threerings/presents/server/ClientManager.java +++ b/src/java/com/threerings/presents/server/ClientManager.java @@ -265,11 +265,10 @@ public class ClientManager clr.addResolutionListener(listener); _penders.put(username, clr); - // request that the appropriate client object be created by the - // dobject manager which starts the whole business off - @SuppressWarnings("unchecked") Class cclass = - (Class)clr.getClientObjectClass(); - PresentsServer.omgr.createObject(cclass, clr); + // create and register our client object and give it back to the + // client resolver + clr.objectAvailable( + PresentsServer.omgr.registerObject(clr.createClientObject())); } catch (Exception e) { // let the listener know that we're hosed diff --git a/src/java/com/threerings/presents/server/ClientResolver.java b/src/java/com/threerings/presents/server/ClientResolver.java index fafd3f9bb..d4cff4469 100644 --- a/src/java/com/threerings/presents/server/ClientResolver.java +++ b/src/java/com/threerings/presents/server/ClientResolver.java @@ -30,7 +30,6 @@ import com.threerings.presents.Log; import com.threerings.presents.data.ClientObject; import com.threerings.presents.dobj.DObject; import com.threerings.presents.dobj.ObjectAccessException; -import com.threerings.presents.dobj.Subscriber; /** * Used to resolve client data when a user starts a session (or when some @@ -40,7 +39,6 @@ import com.threerings.presents.dobj.Subscriber; * appropriately. */ public class ClientResolver extends Invoker.Unit - implements Subscriber { /** * Initiailizes this instance. @@ -61,32 +59,24 @@ public class ClientResolver extends Invoker.Unit } /** - * Returns the {@link ClientObject} derived class that should be - * created to kick off the resolution process. + * Creates the {@link ClientObject} derived class that should be created to + * kick off the resolution process. */ - public Class getClientObjectClass () + public ClientObject createClientObject () { - return ClientObject.class; + return new ClientObject(); } - // documentation inherited + /** + * Called once our client object is registered with the distributed object + * system. + */ public void objectAvailable (ClientObject object) { - // we've got our object, so shunt ourselves over to the invoker - // thread to perform database loading + // we've got our object, so shunt ourselves over to the invoker thread + // to perform database loading _clobj = object; PresentsServer.invoker.postUnit(this); - - // we no longer need to be a subscriber of the object now that it - // has been created - _clobj.removeSubscriber(this); - } - - // documentation inherited - public void requestFailed (int oid, ObjectAccessException cause) - { - // pass the buck - reportFailure(cause); } // documentation inherited diff --git a/src/java/com/threerings/presents/server/InvocationManager.java b/src/java/com/threerings/presents/server/InvocationManager.java index 9417b0437..4c309a7d9 100644 --- a/src/java/com/threerings/presents/server/InvocationManager.java +++ b/src/java/com/threerings/presents/server/InvocationManager.java @@ -21,8 +21,6 @@ package com.threerings.presents.server; -import java.util.ArrayList; - import com.samskivert.util.HashIntMap; import com.samskivert.util.LRUHashMap; import com.samskivert.util.StringUtil; @@ -41,7 +39,6 @@ import com.threerings.presents.dobj.EventListener; import com.threerings.presents.dobj.InvocationRequestEvent; import com.threerings.presents.dobj.ObjectAccessException; import com.threerings.presents.dobj.RootDObjectManager; -import com.threerings.presents.dobj.Subscriber; /** * The invocation services provide client to server invocations (service @@ -65,7 +62,7 @@ import com.threerings.presents.dobj.Subscriber; * the client. */ public class InvocationManager - implements Subscriber, EventListener + implements EventListener { /** The list of services that are to be provided to clients at boot * time. Don't mess with this list! */ @@ -83,9 +80,16 @@ public class InvocationManager _omgr = omgr; // create the object on which we'll listen for invocation requests - omgr.createObject(DObject.class, this); + DObject invobj = omgr.registerObject(new DObject()); + invobj.addListener(this); + _invoid = invobj.getOid(); + +// Log.info("Created invocation service object [oid=" + _invoid + "]."); } + /** + * Returns the object id of the invocation services object. + */ public int getOid () { return _invoid; @@ -111,13 +115,6 @@ public class InvocationManager InvocationMarshaller marsh = dispatcher.createMarshaller(); marsh.init(_invoid, invCode); - // if we haven't yet finished our own initialization, we need to - // throw this dispatcher on a queue so that we can fill in its - // invocation oid when we know what it should be - if (_invoid == -1) { - _lateInitQueue.add(marsh); - } - // register the dispatcher _dispatchers.put(invCode, dispatcher); @@ -165,32 +162,6 @@ public class InvocationManager return (dispatcher == null) ? null : dispatcher.getClass(); } - public void objectAvailable (DObject object) - { - // this must be our invocation object - _invoid = object.getOid(); - - // add ourselves as a message listener - object.addListener(this); - - // let any early registered marshallers know about our invoid - while (_lateInitQueue.size() > 0) { - InvocationMarshaller marsh = _lateInitQueue.remove(0); - marsh.setInvocationOid(_invoid); - } - -// Log.info("Created invocation service object [oid=" + _invoid + "]."); - } - - public void requestFailed (int oid, ObjectAccessException cause) - { - // if for some reason we were unable to create our invocation - // object, we'll end up here - Log.warning("Unable to create invocation object " + - "[reason=" + cause + "]."); - _invoid = -1; - } - // documentation inherited from interface public void eventReceived (DEvent event) { @@ -314,12 +285,6 @@ public class InvocationManager protected HashIntMap _dispatchers = new HashIntMap(); - /** Used to keep track of marshallers registered before we had our - * invocation object so that we can fill their invocation id in - * belatedly. */ - protected ArrayList _lateInitQueue = - new ArrayList(); - /** The text that is appended to the procedure name when automatically * generating a failure response. */ protected static final String FAILED_SUFFIX = "Failed"; diff --git a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java index d6dbf4e1f..8f3dcbb5d 100644 --- a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java +++ b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.logging.Level; import sun.misc.Perf; @@ -39,9 +40,10 @@ import com.samskivert.util.RunQueue; import com.samskivert.util.StringUtil; import com.samskivert.util.Throttle; -import com.threerings.presents.Log; import com.threerings.presents.dobj.*; +import static com.threerings.presents.Log.log; + /** * The presents distributed object manager implements the {@link * DObjectManager} interface, providing an object manager that runs on the @@ -109,22 +111,14 @@ public class PresentsDObjectMgr } } - // documentation inherited from interface + // from interface DObjectManager public boolean isManager (DObject object) { // we are always authoritative in the present implementation return true; } - // inherit documentation from the interface - public void createObject ( - Class dclass, Subscriber target) - { - // queue up a create object event - postEvent(new CreateObjectEvent(dclass, target)); - } - - // inherit documentation from the interface + // from interface DObjectManager public void subscribeToObject ( int oid, Subscriber target) { @@ -138,7 +132,7 @@ public class PresentsDObjectMgr } } - // inherit documentation from the interface + // from interface DObjectManager public void unsubscribeFromObject ( int oid, Subscriber target) { @@ -147,21 +141,14 @@ public class PresentsDObjectMgr oid, target, AccessObjectEvent.UNSUBSCRIBE)); } - // inherit documentation from the interface - public void destroyObject (int oid) - { - // queue up an object destroyed event - postEvent(new ObjectDestroyedEvent(oid)); - } - - // inherit documentation from the interface + // from interface DObjectManager public void postEvent (DEvent event) { // just append it to the queue _evqueue.append(event); } - // inherit documentation from the interface + // from interface DObjectManager public void removedLastSubscriber (DObject obj, boolean deathWish) { // destroy the object if it so desires @@ -170,6 +157,31 @@ public class PresentsDObjectMgr } } + // from interface RootDObjectManager + public T registerObject (T object) + { + int oid = getNextOid(); + + // initialize this object + object.setOid(oid); + object.setManager(PresentsDObjectMgr.this); + object.setAccessController(_defaultController); + + // insert it into the table + _objects.put(oid, object); + +// log.info("Registered object [obj=" + object + "]."); + + return object; + } + + // from interface RootDObjectManager + public void destroyObject (int oid) + { + // queue up an object destroyed event + postEvent(new ObjectDestroyedEvent(oid)); + } + /** * Posts a self-contained unit of code that should be run on the * distributed object manager thread at the next available @@ -186,13 +198,10 @@ public class PresentsDObjectMgr } /** - * Returns the object in the object table with the specified oid or - * null if no object has that oid. Be sure only to call this function - * from the dobjmgr thread and not to do anything funny with the - * object. If subscription is desired, use - * subscribeToObject(). - * - * @see #subscribeToObject + * Returns the object in the object table with the specified oid or null if + * no object has that oid. Be sure only to call this function from the + * dobjmgr thread and not to do anything funny with the object. If + * subscription is desired, use {@link #subscribeToObject}. */ public DObject getObject (int oid) { @@ -227,7 +236,7 @@ public class PresentsDObjectMgr */ public void run () { - Log.info("DOMGR running."); + log.info("DOMGR running."); // make a note of the thread that's processing events synchronized (this) { @@ -239,7 +248,7 @@ public class PresentsDObjectMgr processUnit(_evqueue.get()); } - Log.info("DOMGR exited."); + log.info("DOMGR exited."); } /** @@ -270,8 +279,8 @@ public class PresentsDObjectMgr } } catch (Exception e) { - Log.warning("Execution unit failed [unit=" + unit + "]."); - Log.logStackTrace(e); + log.log(Level.WARNING, + "Execution unit failed [unit=" + unit + "].", e); } catch (Error e) { handleFatalError(unit, e); @@ -283,9 +292,9 @@ public class PresentsDObjectMgr // report excessively long units if (elapsed > 500000) { - Log.warning("Long dobj unit [u=" + StringUtil.safeToString(unit) + - " (" + StringUtil.shortClassName(unit) + ")" + - ", time=" + (elapsed/1000) + "ms]."); + log.warning("Long dobj unit [u=" + StringUtil.safeToString(unit) + + " (" + StringUtil.shortClassName(unit) + ")" + + ", time=" + (elapsed/1000) + "ms]."); } // periodically sample and record the time spent processing a unit @@ -326,8 +335,8 @@ public class PresentsDObjectMgr // look up the target object DObject target = _objects.get(event.getTargetOid()); if (target == null) { - Log.debug("Compound event target no longer exists " + - "[event=" + event + "]."); + log.fine("Compound event target no longer exists " + + "[event=" + event + "]."); return; } @@ -335,8 +344,8 @@ public class PresentsDObjectMgr for (int ii = 0; ii < ecount; ii++) { DEvent sevent = (DEvent)events.get(ii); if (!target.checkPermissions(sevent)) { - Log.warning("Event failed permissions check " + - "[event=" + sevent + ", target=" + target + "]."); + log.warning("Event failed permissions check " + + "[event=" + sevent + ", target=" + target + "]."); return; } } @@ -359,15 +368,14 @@ public class PresentsDObjectMgr // look up the target object DObject target = _objects.get(event.getTargetOid()); if (target == null) { - Log.debug("Event target no longer exists " + - "[event=" + event + "]."); + log.fine("Event target no longer exists [event=" + event + "]."); return; } // check the event's permissions if (!target.checkPermissions(event)) { - Log.warning("Event failed permissions check " + - "[event=" + event + ", target=" + target + "]."); + log.warning("Event failed permissions check " + + "[event=" + event + ", target=" + target + "]."); return; } @@ -410,9 +418,8 @@ public class PresentsDObjectMgr } } catch (Exception e) { - Log.warning("Failure processing event [event=" + event + - ", target=" + target + "]."); - Log.logStackTrace(e); + log.log(Level.WARNING, "Failure processing event [event=" + event + + ", target=" + target + "].", e); } catch (Error e) { handleFatalError(event, e); @@ -433,8 +440,8 @@ public class PresentsDObjectMgr if (_fatalThrottle.throttleOp()) { throw error; } - Log.warning("Fatal error caused by '" + causer + "': " + error); - Log.logStackTrace(error); + log.log(Level.WARNING, + "Fatal error caused by '" + causer + "': " + error, error); } /** @@ -457,7 +464,7 @@ public class PresentsDObjectMgr public void dumpUnitProfiles () { for (Map.Entry entry : _profiles.entrySet()) { - Log.info("P: " + entry.getKey() + " => " + entry.getValue()); + log.info("P: " + entry.getKey() + " => " + entry.getValue()); } } @@ -472,7 +479,7 @@ public class PresentsDObjectMgr { int oid = target.getOid(); -// Log.info("Removing destroyed object from table " + +// log.info("Removing destroyed object from table " + // "[oid=" + oid + "]."); // remove the object from the table @@ -498,10 +505,10 @@ public class PresentsDObjectMgr // post an object removed event to clear the reference postEvent(new ObjectRemovedEvent( ref.reffingOid, ref.field, oid)); -// Log.info("Forcing removal " + ref + "."); +// log.info("Forcing removal " + ref + "."); } else { - Log.info("Dangling reference from inactive object " + + log.info("Dangling reference from inactive object " + ref + "."); } } @@ -534,7 +541,7 @@ public class PresentsDObjectMgr } } catch (Exception e) { - Log.warning("Unable to clean up after oid list field " + + log.warning("Unable to clean up after oid list field " + "[target=" + target + ", field=" + field + "]."); } } @@ -571,13 +578,13 @@ public class PresentsDObjectMgr // object which no longer exists; so we don't complain about non- // existent references if the referree is already destroyed if (ref == null && _objects.containsKey(reffedOid)) { - Log.warning("Requested to clear out non-existent reference " + + log.warning("Requested to clear out non-existent reference " + "[refferOid=" + reffer.getOid() + ", field=" + field + ", reffedOid=" + reffedOid + "]."); // } else { -// Log.info("Cleared out reference " + ref + "."); +// log.info("Cleared out reference " + ref + "."); } } @@ -595,7 +602,7 @@ public class PresentsDObjectMgr // ensure that the target object exists if (!_objects.containsKey(oid)) { - Log.info("Rejecting object added event of non-existent object " + + log.info("Rejecting object added event of non-existent object " + "[refferOid=" + target.getOid() + ", reffedOid=" + oid + "]."); return false; @@ -615,7 +622,7 @@ public class PresentsDObjectMgr int rpos = -1; for (int i = 0; i < refs.length; i++) { if (ref.equals(refs[i])) { - Log.warning("Ignoring request to track existing " + + log.warning("Ignoring request to track existing " + "reference " + ref + "."); return true; } else if (refs[i] == null && rpos == -1) { @@ -634,7 +641,7 @@ public class PresentsDObjectMgr // finally add the reference refs[rpos] = ref; -// Log.info("Tracked reference " + ref + "."); +// log.info("Tracked reference " + ref + "."); return true; } @@ -652,7 +659,7 @@ public class PresentsDObjectMgr int toid = target.getOid(); int oid = ore.getOid(); -// Log.info("Processing object removed [from=" + toid + +// log.info("Processing object removed [from=" + toid + // ", roid=" + toid + "]."); // get the reference vector for the referenced object @@ -663,7 +670,7 @@ public class PresentsDObjectMgr // generate object removed events for all of its referencees. // so we opt not to log anything in this case -// Log.info("Object removed without reference to track it " + +// log.info("Object removed without reference to track it " + // "[toid=" + toid + ", field=" + field + // ", oid=" + oid + "]."); return true; @@ -673,13 +680,13 @@ public class PresentsDObjectMgr for (int i = 0; i < refs.length; i++) { Reference ref = refs[i]; if (ref != null && ref.equals(toid, field)) { -// Log.info("Removed reference " + refs[i] + "."); +// log.info("Removed reference " + refs[i] + "."); refs[i] = null; return true; } } - Log.warning("Unable to locate reference for removal " + + log.warning("Unable to locate reference for removal " + "[reffingOid=" + toid + ", field=" + field + ", reffedOid=" + oid + "]."); return true; @@ -711,7 +718,7 @@ public class PresentsDObjectMgr return _nextOid; } - // documentation inherited from interface PresentsServer.Reporter + // from interface PresentsServer.Reporter public void appendReport ( StringBuilder report, long now, long sinceLast, boolean reset) { @@ -751,85 +758,12 @@ public class PresentsDObjectMgr try { sub.objectAvailable(obj); } catch (Exception e) { - Log.warning("Subscriber choked during object available " + - "[obj=" + StringUtil.safeToString(obj) + - ", sub=" + sub + "]."); - Log.logStackTrace(e); + log.log(Level.WARNING, "Subscriber choked during object " + + "available [obj=" + StringUtil.safeToString(obj) + + ", sub=" + sub + "].", e); } } - /** - * Used to create a distributed object and register it with the - * system. - */ - protected class CreateObjectEvent extends DEvent - { - public CreateObjectEvent (Class clazz, Subscriber target) - { - super(0); // target the fake object - _class = clazz; - _target = target; - } - - public boolean isPrivate () - { - return true; - } - - public boolean applyToObject (DObject target) - throws ObjectAccessException - { - int oid = getNextOid(); - T obj = null; - - try { - // create a new instance of this object - obj = _class.newInstance(); - - // initialize this object - obj.setOid(oid); - obj.setManager(PresentsDObjectMgr.this); - obj.setAccessController(_defaultController); - - // insert it into the table - _objects.put(oid, obj); - -// Log.info("Created object [obj=" + obj + "]."); - - } catch (Exception e) { - Log.warning("Object creation failure " + - "[class=" + _class.getName() + - ", error=" + e + "]."); - - // let the subscriber know shit be fucked - if (_target != null) { - String errmsg = "Object instantiation failed"; - _target.requestFailed( - oid, new ObjectAccessException(errmsg, e)); - } - - return false; - } - - if (_target != null) { - // add the subscriber to this object's subscriber list - obj.addSubscriber(_target); - - // let the target subscriber know that their object is - // available - informObjectAvailable(_target, obj); - } - - // and return false to ensure that this event is not - // dispatched to the fake object's subscriber list (even - // though it's empty) - return false; - } - - protected transient Class _class; - protected transient Subscriber _target; - } - /** * Used to make an object available to a subscriber (with or without * the associated subscription). @@ -916,7 +850,7 @@ public class PresentsDObjectMgr _helpers.put(ObjectRemovedEvent.class, method); } catch (Exception e) { - Log.warning("Unable to register event helpers " + + log.warning("Unable to register event helpers " + "[error=" + e + "]."); } } diff --git a/src/java/com/threerings/presents/server/TimeBaseProvider.java b/src/java/com/threerings/presents/server/TimeBaseProvider.java index 48e1a4a31..c580cef77 100644 --- a/src/java/com/threerings/presents/server/TimeBaseProvider.java +++ b/src/java/com/threerings/presents/server/TimeBaseProvider.java @@ -31,10 +31,7 @@ import com.threerings.presents.data.ClientObject; import com.threerings.presents.data.TimeBaseCodes; import com.threerings.presents.data.TimeBaseObject; -import com.threerings.presents.dobj.DObject; -import com.threerings.presents.dobj.ObjectAccessException; import com.threerings.presents.dobj.RootDObjectManager; -import com.threerings.presents.dobj.Subscriber; /** * Provides the server-side of the time base services. The time base @@ -65,29 +62,14 @@ public class TimeBaseProvider * client and used to send delta times. * * @param timeBase the name of the time base to create. - * @param resl the result listener that will be informed when the time - * base object is created or if the creation fails. + * + * @return the created and registered time base object. */ - public static void createTimeBase ( - final String timeBase, final ResultListener resl) + public static TimeBaseObject createTimeBase (String timeBase) { - _omgr.createObject(TimeBaseObject.class, - new Subscriber () { - public void objectAvailable (TimeBaseObject object) { - // stuff it into our table - _timeBases.put(timeBase, object); - // and notify the listener - resl.requestCompleted(object); - } - - public void requestFailed (int oid, ObjectAccessException cause) { - Log.warning("Ack. Unable to create time base object " + - "[timeBase=" + timeBase + - ", cause=" + cause + "]."); - // notify the listener that we're borked - resl.requestFailed(cause); - } - }); + TimeBaseObject object = _omgr.registerObject(new TimeBaseObject()); + _timeBases.put(timeBase, object); + return object; } /** diff --git a/tests/src/java/com/threerings/crowd/server/JabberServer.java b/tests/src/java/com/threerings/crowd/server/JabberServer.java index 3403a9465..e8282812a 100644 --- a/tests/src/java/com/threerings/crowd/server/JabberServer.java +++ b/tests/src/java/com/threerings/crowd/server/JabberServer.java @@ -20,13 +20,7 @@ public class JabberServer extends CrowdServer super.init(); // create a single location - plreg.createPlace( - new JabberConfig(), new PlaceRegistry.CreationObserver() { - public void placeCreated (PlaceObject place, PlaceManager pmgr) { - Log.info("Created chat room " + pmgr.where() + "."); - _place = pmgr; - } - }); + _pmgr = plreg.createPlace(new JabberConfig()); } public static void main (String[] args) @@ -41,5 +35,5 @@ public class JabberServer extends CrowdServer } } - protected PlaceManager _place; + protected PlaceManager _pmgr; } diff --git a/tests/src/java/com/threerings/presents/client/TestClient.java b/tests/src/java/com/threerings/presents/client/TestClient.java index 445010a19..eaa3d2cf9 100644 --- a/tests/src/java/com/threerings/presents/client/TestClient.java +++ b/tests/src/java/com/threerings/presents/client/TestClient.java @@ -110,14 +110,8 @@ public class TestClient { Log.info("Got event [event=" + event + "]."); - if (event instanceof AttributeChangedEvent) { - // request to destroy the object - _client.getDObjectManager().destroyObject(event.getTargetOid()); - - } else { - // request that we log off - _client.logoff(true); - } + // request that we log off + _client.logoff(true); } // documentation inherited from interface diff --git a/tests/src/java/com/threerings/presents/server/DOMTest.java b/tests/src/java/com/threerings/presents/server/DOMTest.java index 215e3bebb..b2c44f336 100644 --- a/tests/src/java/com/threerings/presents/server/DOMTest.java +++ b/tests/src/java/com/threerings/presents/server/DOMTest.java @@ -31,45 +31,13 @@ import com.threerings.presents.dobj.*; * A simple test case for the dobjmgr. */ public class DOMTest extends TestCase - implements Subscriber, AttributeChangeListener, - ElementUpdateListener + implements AttributeChangeListener, ElementUpdateListener { public DOMTest () { super(DOMTest.class.getName()); } - public void objectAvailable (TestObject object) - { - // add ourselves as a listener - _test = object; - _test.addListener(this); - - // test transactions - _test.startTransaction(); - _test.setFoo(99); - _test.setBar("hoopie"); - _test.commitTransaction(); - - // set some elements - _test.setIntsAt(15, 3); - _test.setIntsAt(5, 2); - _test.setIntsAt(1, 0); - _test.setStringsAt("Hello", 0); - _test.setStringsAt("Goodbye", 1); - _test.setStringsAt(null, 1); - - // now set some values straight up - _test.setFoo(25); - _test.setBar("howdy"); - } - - public void requestFailed (int oid, ObjectAccessException cause) - { - fail("Request failed: " + cause); - _omgr.harshShutdown(); - } - public void attributeChanged (AttributeChangedEvent event) { assertTrue(fields[_fcount] + " == " + values[_fcount], @@ -91,11 +59,29 @@ public class DOMTest extends TestCase public void runTest () { - // request that a new TestObject be created - _omgr.createObject(TestObject.class, this); + // request that a new TestObject be registered + _test = _omgr.registerObject(new TestObject()); - // or for fun you can try this bogus create request - // _omgr.createObject(Integer.class, sub); + // add ourselves as a listener + _test.addListener(this); + + // test transactions + _test.startTransaction(); + _test.setFoo(99); + _test.setBar("hoopie"); + _test.commitTransaction(); + + // set some elements + _test.setIntsAt(15, 3); + _test.setIntsAt(5, 2); + _test.setIntsAt(1, 0); + _test.setStringsAt("Hello", 0); + _test.setStringsAt("Goodbye", 1); + _test.setStringsAt(null, 1); + + // now set some values straight up + _test.setFoo(25); + _test.setBar("howdy"); // and run the object manager _omgr.run(); diff --git a/tests/src/java/com/threerings/presents/server/DestroyedRefTest.java b/tests/src/java/com/threerings/presents/server/DestroyedRefTest.java index f8a8d2572..407c49116 100644 --- a/tests/src/java/com/threerings/presents/server/DestroyedRefTest.java +++ b/tests/src/java/com/threerings/presents/server/DestroyedRefTest.java @@ -33,47 +33,18 @@ import com.threerings.presents.dobj.*; * an oid list. */ public class DestroyedRefTest extends TestCase - implements Subscriber, EventListener + implements EventListener { + public static Test suite () + { + return new DestroyedRefTest(); + } + public DestroyedRefTest () { super(DestroyedRefTest.class.getName()); } - public void objectAvailable (TestObject object) - { - // add ourselves as an event listener - object.addListener(this); - - // keep references to our test objects - if (_objone == null) { - _objone = object; - - } else { - _objtwo = object; - - // add object one to object two twice in a row to make sure - // repeated adds don't result in the object being listed twice - _objtwo.addToList(_objone.getOid()); - Log.info("The following addToList() should be ignored."); - _objtwo.addToList(_objone.getOid()); - - // now that we have both objects, try to set up the reference. - // first we queue up a destroy event for object two, then we - // try to reference it on object one's oid list - _objtwo.destroy(); - _objone.addToList(_objtwo.getOid()); - - // finally dispatch an event on which we can trigger our exit - _objone.setFoo(1); - } - } - - public void requestFailed (int oid, ObjectAccessException cause) - { - fail("Ack. Unable to create object [cause=" + cause + "]."); - } - public void eventReceived (DEvent event) { int toid = event.getTargetOid(); @@ -99,20 +70,31 @@ public class DestroyedRefTest extends TestCase public void runTest () { // create two test objects - _omgr.createObject(TestObject.class, this); - _omgr.createObject(TestObject.class, this); + _objone = _omgr.registerObject(new TestObject()); + _objone.addListener(this); + _objtwo = _omgr.registerObject(new TestObject()); + _objtwo.addListener(this); + + // add object one to object two twice in a row to make sure repeated + // adds don't result in the object being listed twice + _objtwo.addToList(_objone.getOid()); + Log.info("The following addToList() should be ignored."); + _objtwo.addToList(_objone.getOid()); + + // now that we have both objects, try to set up the reference. first + // we queue up a destroy event for object two, then we try to reference + // it on object one's oid list + _objtwo.destroy(); + _objone.addToList(_objtwo.getOid()); + + // finally dispatch an event on which we can trigger our exit + _objone.setFoo(1); // and run the object manager _omgr.run(); } - public static Test suite () - { - return new DestroyedRefTest(); - } - - protected TestObject _objone; - protected TestObject _objtwo; + protected TestObject _objone, _objtwo; protected static PresentsDObjectMgr _omgr = new PresentsDObjectMgr(); } diff --git a/tests/src/java/com/threerings/presents/server/RefTest.java b/tests/src/java/com/threerings/presents/server/RefTest.java index 7eecace3d..250c07e8c 100644 --- a/tests/src/java/com/threerings/presents/server/RefTest.java +++ b/tests/src/java/com/threerings/presents/server/RefTest.java @@ -31,35 +31,18 @@ import com.threerings.presents.dobj.*; * Tests the oid list reference tracking code. */ public class RefTest extends TestCase - implements Subscriber, EventListener + implements EventListener { + public static Test suite () + { + return new RefTest(); + } + public RefTest () { super(RefTest.class.getName()); } - public void objectAvailable (TestObject object) - { - // add ourselves as an event listener to our subscribed object - object.addListener(this); - - // keep references to our test objects - if (_objone == null) { - _objone = object; - - } else { - _objtwo = 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) - { - fail("Ack. Unable to create object [cause=" + cause + "]."); - } - public void eventReceived (DEvent event) { // Log.info("Got event: " + event); @@ -93,18 +76,19 @@ public class RefTest extends TestCase public void runTest () { // create two test objects - _omgr.createObject(TestObject.class, this); - _omgr.createObject(TestObject.class, this); + _objone = _omgr.registerObject(new TestObject()); + _objone.addListener(this); + _objtwo = _omgr.registerObject(new TestObject()); + _objtwo.addListener(this); + + // now that we have both objects, set up the references + _objone.addToList(_objtwo.getOid()); + _objtwo.addToList(_objone.getOid()); // and run the object manager _omgr.run(); } - public static Test suite () - { - return new RefTest(); - } - protected TestObject _objone; protected TestObject _objtwo; diff --git a/tests/src/java/com/threerings/presents/server/TestServer.java b/tests/src/java/com/threerings/presents/server/TestServer.java index 6c9323765..42ce11c57 100644 --- a/tests/src/java/com/threerings/presents/server/TestServer.java +++ b/tests/src/java/com/threerings/presents/server/TestServer.java @@ -38,16 +38,7 @@ public class TestServer extends PresentsServer invmgr.registerDispatcher(new TestDispatcher(new TestProvider()), true); // create a test object - Subscriber sub = new Subscriber() { - public void objectAvailable (TestObject object) { - testobj = object; - } - public void requestFailed (int oid, ObjectAccessException cause) { - Log.warning("Unable to create test object " + - "[error=" + cause + "]."); - } - }; - omgr.createObject(TestObject.class, sub); + testobj = omgr.registerObject(new TestObject()); } public static void main (String[] args)