Revamped distributed object creation. There was no particular reason to create

distributed objects by reflection since we don't allow clients to create
objects, furthermore we needn't do it asynchronously. The object creation
methods were moved into the server-side only interface and made "immediate", so
the caller creates a derived instance of DObject and registers it with the
system instead of creating it with a Subscriber callback.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4342 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2006-08-23 23:46:48 +00:00
parent 1f204669c4
commit bc9f53396c
19 changed files with 304 additions and 589 deletions
@@ -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<? extends NodeObject> 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);
}
}
@@ -32,9 +32,9 @@ import com.threerings.crowd.data.BodyObject;
public class CrowdClientResolver extends ClientResolver
{
// documentation inherited
public Class<? extends ClientObject> getClientObjectClass ()
public ClientObject createClientObject ()
{
return BodyObject.class;
return new BodyObject();
}
// documentation inherited
@@ -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<? extends PlaceObject> getPlaceObjectClass ()
{
@@ -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<PlaceObject>
{
/**
* 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<PlaceManager,CreationObserver>(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<PlaceObject> pclass =
(Class<PlaceObject>)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<PlaceManager,CreationObserver> 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<PlaceManager,CreationObserver> 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<Tuple<PlaceManager,CreationObserver>> _createq =
new Queue<Tuple<PlaceManager,CreationObserver>>();
/** A mapping from place object id to place manager. */
protected HashIntMap<PlaceManager> _pmgrs = new HashIntMap<PlaceManager>();
}
@@ -82,14 +82,6 @@ public class ClientDObjectMgr
return false;
}
// inherit documentation from the interface
public <T extends DObject> void createObject (
Class<T> dclass, Subscriber<T> target)
{
// not presently supported
throw new RuntimeException("createObject() not supported");
}
// inherit documentation from the interface
public <T extends DObject> void subscribeToObject (
int oid, Subscriber<T> 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)
{
@@ -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
* <code>DObject</code> (or <code>DObject.class</code> 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 <T extends DObject> void createObject (
Class<T> dclass, Subscriber<T> 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 <T extends DObject> void unsubscribeFromObject (
int oid, Subscriber<T> 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
@@ -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 extends DObject> 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);
}
@@ -116,16 +116,36 @@ public class PeerManager
this, PresentsServer.clmgr.getClientFactory()));
// create our node object
@SuppressWarnings("unchecked") Class<NodeObject> clazz =
(Class<NodeObject>)getNodeObjectClass();
PresentsServer.omgr.createObject(clazz, new Subscriber<NodeObject>() {
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<? extends NodeObject> getNodeObjectClass ()
protected NodeObject createNodeObject ()
{
return NodeObject.class;
return new NodeObject();
}
/**
@@ -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<ClientObject> cclass =
(Class<ClientObject>)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
@@ -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<ClientObject>
{
/**
* 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<? extends ClientObject> 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
@@ -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<DObject>, 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<InvocationDispatcher> _dispatchers =
new HashIntMap<InvocationDispatcher>();
/** 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<InvocationMarshaller> _lateInitQueue =
new ArrayList<InvocationMarshaller>();
/** The text that is appended to the procedure name when automatically
* generating a failure response. */
protected static final String FAILED_SUFFIX = "Failed";
@@ -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 <T extends DObject> void createObject (
Class<T> dclass, Subscriber<T> target)
{
// queue up a create object event
postEvent(new CreateObjectEvent<T>(dclass, target));
}
// inherit documentation from the interface
// from interface DObjectManager
public <T extends DObject> void subscribeToObject (
int oid, Subscriber<T> target)
{
@@ -138,7 +132,7 @@ public class PresentsDObjectMgr
}
}
// inherit documentation from the interface
// from interface DObjectManager
public <T extends DObject> void unsubscribeFromObject (
int oid, Subscriber<T> 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 extends DObject> 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
* <code>subscribeToObject()</code>.
*
* @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<String,UnitProfile> 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<T extends DObject> extends DEvent
{
public CreateObjectEvent (Class<T> clazz, Subscriber<T> 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<T> _class;
protected transient Subscriber<T> _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 + "].");
}
}
@@ -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<TimeBaseObject> resl)
public static TimeBaseObject createTimeBase (String timeBase)
{
_omgr.createObject(TimeBaseObject.class,
new Subscriber<TimeBaseObject> () {
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;
}
/**