com.threerings.presents.server
Class PresentsDObjectMgr

java.lang.Object
  extended by com.threerings.presents.server.PresentsDObjectMgr
All Implemented Interfaces:
Interval.Factory, RunQueue, DObjectManager, RootDObjectManager, Executor
Direct Known Subclasses:
LocalDObjectMgr

public class PresentsDObjectMgr
extends Object
implements RootDObjectManager

The presents distributed object manager implements the DObjectManager interface, providing an object manager that runs on the server. By virtue of running on the server, it manages its objects directly rather than managing proxies of objects which is what is done on the client. Thus it simply queues up events and dispatches them to listeners.

The server object manager is meant to run on the main thread of the server application and thus provides a method to be invoked by the application main thread which won't return until the manager has been requested to shut down.


Nested Class Summary
protected  class PresentsDObjectMgr.AccessObjectEvent<T extends DObject>
          Used to make an object available to a subscriber (with or without the associated subscription).
protected static interface PresentsDObjectMgr.EventHelper
          Does some helpy bits for certain events.
static interface PresentsDObjectMgr.LongRunnable
          Post instances of these if you know you're going to tie up the distributed object thread for a long time and don't want a spurious warning.
protected static class PresentsDObjectMgr.ProxyReference
          Tracks necessary information on a proxy distributed object.
protected static class PresentsDObjectMgr.Reference
          Used to track references of objects in oid lists.
static class PresentsDObjectMgr.Stats
          Returned by getStats(boolean).
protected static class PresentsDObjectMgr.UnitProfile
          Used to profile time spent invoking units and processing events if such profiling is enabled.
 
Nested classes/interfaces inherited from interface com.samskivert.util.RunQueue
RunQueue.AsExecutor
 
Field Summary
protected  PresentsDObjectMgr.Stats _current
          Used to track runtime statistics.
protected  AccessController _defaultController
          The default access controller to use when creating distributed objects.
protected  Thread _dobjThread
          keeps Track of which thread is executing the event loop so that other services can enforce restrictions on code that should or should not be called from the event dispatch thread.
protected  long _eventCount
          Used to track the number of events dispatched over time.
protected  Queue<Object> _evqueue
          The event queue via which all events are processed.
protected  Throttle _fatalThrottle
          Track fatal errors so that we can stick a fork in ourselves if things get too far out of hand.
protected  Map<Class<?>,PresentsDObjectMgr.EventHelper> _helpers
          Maps event classes to helpers that perform additional processing for particular events.
protected  InvocationManager _invmgr
          Used to resolve unit names when profiling.
protected  long _nextEventId
          A monotonically increasing counter used to assign an id to all dispatched events.
protected  int _nextOid
          Used to assign a unique oid to each distributed object.
protected  IntMap<DObject> _objects
          The managed distributed objects table.
protected  Map<String,PresentsDObjectMgr.UnitProfile> _profiles
          Used to profile our events and runnable units.
protected  IntMap<PresentsDObjectMgr.ProxyReference> _proxies
          Maintains proxy information for any proxied distributed objects.
protected  PresentsDObjectMgr.Stats _recent
          Used to track runtime statistics.
protected  IntMap<PresentsDObjectMgr.Reference[]> _refs
          Used to track oid list references of distributed objects.
protected  boolean _running
          A flag indicating that the event dispatcher is still running.
protected  int _unitProfInterval
          The frequency at which we take a profiling sample.
protected static int DEFREFVEC_SIZE
          The default size of an oid list refs vector.
protected static int DUMMY_OID
          The oid of the DOject created during object manager startup that isn't actually distributed.
protected static boolean UNIT_PROF_ENABLED
          Whether or not unit profiling is enabled.
 
Fields inherited from interface com.samskivert.util.RunQueue
AWT
 
Constructor Summary
PresentsDObjectMgr(ReportManager repmgr)
          Creates the dobjmgr and prepares it for operation.
 
Method Summary
 void clearProxyObject(int origObjectId, DObject object)
          Clears a proxy object reference from our local distributed object space.
protected  void clearReference(DObject reffer, String field, int reffedOid)
          Called by objectDestroyed; clears out the tracking info for a reference by the supplied object to the specified oid via the specified field.
 void clearUnitProfiles()
          Clears the current set of unit profiles.
 void destroyObject(int oid)
          Requests that the specified object be destroyed.
protected  boolean dispatchEvent(DEvent event, DObject target)
          Dispatches an event after the target object has been resolved and the permissions have been checked.
 void dumpUnitProfiles()
          Dumps collected profiling information to the system log.
 void execute(Runnable command)
           
 long getNextEventId(boolean increment)
          Returns the id to be assigned to the next event posted to the event queue.
protected  int getNextOid()
           
 DObject getObject(int oid)
          Returns the object in the object table with the specified oid or null if no object has that oid.
 PresentsDObjectMgr.Stats getStats(boolean snapshot)
          Returns a recent snapshot of runtime statistics tracked by the distributed object manager.
 int getUnitProfInterval()
          Returns the profiling sample frequency.
protected  void handleFatalError(Object causer, Error error)
          Attempts to recover from fatal errors but rethrows if things are freaking out too frequently.
 void harshShutdown()
          Requests that the dobjmgr shut itself down directly.
protected static
<T extends DObject>
void
informObjectAvailable(Subscriber<T> sub, T obj)
          Calls Subscriber.objectAvailable(T) and catches and logs any exception thrown by the subscriber during the call.
 boolean isDispatchThread()
          Returns true if the thread invoking this method is the same thread that is doing distributed object event dispatch.
 boolean isManager(DObject object)
          Returns true if this distributed object manager is the authoritative manager for the specified distributed object, or false if we are only providing a proxy to the object.
 boolean isRunning()
          Tests if the event processing thread is still running.
 Interval newInterval(Runnable action)
          Creates an Interval that runs the supplied runnable.
 boolean objectAdded(DEvent event, DObject target)
          Called as a helper for ObjectAddedEvent events.
 boolean objectDestroyed(DEvent event, DObject target)
          Called as a helper for ObjectDestroyedEvent events.
 boolean objectRemoved(DEvent event, DObject target)
          Called as a helper for ObjectRemovedEvent events.
 void postEvent(DEvent event)
          Posts a distributed object event into the system.
 void postRunnable(Runnable unit)
          Posts a self-contained unit of code that should be run on the distributed object manager thread at the next available opportunity.
protected  void processCompoundEvent(CompoundEvent event)
          Performs the processing associated with a compound event, notifying listeners and the like.
protected  void processEvent(DEvent event)
          Performs the processing associated with an event, notifying listeners and the like.
protected  void processUnit(Object unit)
          Processes a single unit from the queue.
 boolean queueIsEmpty()
          Should not need to be called except by the invoker during shutdown to ensure that things are proceeding smoothly.
 void refuseEventThread()
          Ensures that the calling thread is not the distributed object event dispatch thread, throwing an IllegalStateException if it is.
protected  void registerEventHelpers()
          Registers our event helper methods.
<T extends DObject>
T
registerObject(T object)
          Registers a distributed object instance of the supplied class with the system and assigns it an oid.
 void registerProxyObject(DObject object, DObjectManager omgr)
          Registers an object managed by another distributed object manager (probably on another server).
 void removedLastSubscriber(DObject obj, boolean deathWish)
          When a distributed object removes its last subscriber, it will call this function to let the object manager know.
 void requireEventThread()
          Ensures that the calling thread is the distributed object event dispatch thread, throwing an IllegalStateException if it is not.
 void run()
          Runs the dobjmgr event loop until it is requested to exit.
 void setDefaultAccessController(AccessController controller)
          Sets up an access controller that will be provided to any distributed objects created on the server.
 void setUnitProfInterval(int interval)
          Sets the frequency at which we take profiling samples.
<T extends DObject>
void
subscribeToObject(int oid, Subscriber<T> target)
          Requests that the specified subscriber be subscribed to the object identified by the supplied object id.
<T extends DObject>
void
unsubscribeFromObject(int oid, Subscriber<T> target)
          Requests that the specified subscriber be unsubscribed from the object identified by the supplied object id.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

_running

protected boolean _running
A flag indicating that the event dispatcher is still running.


_evqueue

protected Queue<Object> _evqueue
The event queue via which all events are processed.


_objects

protected IntMap<DObject> _objects
The managed distributed objects table.


_nextOid

protected int _nextOid
Used to assign a unique oid to each distributed object.


_eventCount

protected long _eventCount
Used to track the number of events dispatched over time.


_fatalThrottle

protected Throttle _fatalThrottle
Track fatal errors so that we can stick a fork in ourselves if things get too far out of hand. More than 30 fatal errors in the span of a minute and we throw in the towel.


_refs

protected IntMap<PresentsDObjectMgr.Reference[]> _refs
Used to track oid list references of distributed objects.


_defaultController

protected AccessController _defaultController
The default access controller to use when creating distributed objects.


_proxies

protected IntMap<PresentsDObjectMgr.ProxyReference> _proxies
Maintains proxy information for any proxied distributed objects.


_dobjThread

protected Thread _dobjThread
keeps Track of which thread is executing the event loop so that other services can enforce restrictions on code that should or should not be called from the event dispatch thread.


_nextEventId

protected long _nextEventId
A monotonically increasing counter used to assign an id to all dispatched events.


_profiles

protected Map<String,PresentsDObjectMgr.UnitProfile> _profiles
Used to profile our events and runnable units.


_recent

protected PresentsDObjectMgr.Stats _recent
Used to track runtime statistics.


_current

protected PresentsDObjectMgr.Stats _current
Used to track runtime statistics.


_helpers

protected Map<Class<?>,PresentsDObjectMgr.EventHelper> _helpers
Maps event classes to helpers that perform additional processing for particular events.


_invmgr

protected InvocationManager _invmgr
Used to resolve unit names when profiling. Injected by the invmgr when it's created.


_unitProfInterval

protected int _unitProfInterval
The frequency at which we take a profiling sample.


UNIT_PROF_ENABLED

protected static final boolean UNIT_PROF_ENABLED
Whether or not unit profiling is enabled.

See Also:
Constant Field Values

DEFREFVEC_SIZE

protected static final int DEFREFVEC_SIZE
The default size of an oid list refs vector.

See Also:
Constant Field Values

DUMMY_OID

protected static final int DUMMY_OID
The oid of the DOject created during object manager startup that isn't actually distributed.

See Also:
Constant Field Values
Constructor Detail

PresentsDObjectMgr

@Inject
public PresentsDObjectMgr(ReportManager repmgr)
Creates the dobjmgr and prepares it for operation.

Method Detail

getNextEventId

public long getNextEventId(boolean increment)
Returns the id to be assigned to the next event posted to the event queue.

Parameters:
increment - if true, the event id will be incremented so that the caller can "claim" the returned event id.

setDefaultAccessController

public void setDefaultAccessController(AccessController controller)
Sets up an access controller that will be provided to any distributed objects created on the server. The controllers can subsequently be overridden if desired, but a default controller is useful for implementing basic access control policies.


registerProxyObject

public void registerProxyObject(DObject object,
                                DObjectManager omgr)
Registers an object managed by another distributed object manager (probably on another server). The local server will assign the object a proxy oid, and any events that come in on this object will be rewritten from their proxy oid to their original id before forwarding on to the originating object manager.


clearProxyObject

public void clearProxyObject(int origObjectId,
                             DObject object)
Clears a proxy object reference from our local distributed object space. This merely removes it from our internal tables, the caller is responsible for coordinating the deregistration of the object with the proxying client.


isManager

public boolean isManager(DObject object)
Description copied from interface: DObjectManager
Returns true if this distributed object manager is the authoritative manager for the specified distributed object, or false if we are only providing a proxy to the object.

Specified by:
isManager in interface DObjectManager

subscribeToObject

public <T extends DObject> void subscribeToObject(int oid,
                                                  Subscriber<T> target)
Description copied from interface: DObjectManager
Requests that the specified subscriber be subscribed to the object identified by the supplied object id. That subscriber will be notified when the object is available or if the subscription request failed.

Specified by:
subscribeToObject in interface DObjectManager
Parameters:
oid - The object id of the distributed object to which subscription is desired.
target - The subscriber to be subscribed.
See Also:
Subscriber.objectAvailable(T), Subscriber.requestFailed(int, com.threerings.presents.dobj.ObjectAccessException)

unsubscribeFromObject

public <T extends DObject> void unsubscribeFromObject(int oid,
                                                      Subscriber<T> target)
Description copied from interface: DObjectManager
Requests that the specified subscriber be unsubscribed from the object identified by the supplied object id.

Specified by:
unsubscribeFromObject in interface DObjectManager
Parameters:
oid - The object id of the distributed object from which unsubscription is desired.
target - The subscriber to be unsubscribed.

postEvent

public void postEvent(DEvent event)
Description copied from interface: DObjectManager
Posts a distributed object event into the system. Instead of requesting the modification of a distributed object attribute by calling the setter for that attribute on the object itself, an AttributeChangedEvent can be constructed and posted directly. This is true for all event types and is useful for situations where one doesn't have access to the object in question, but needs to affect some event.

This event will be forwarded to the ultimate manager of the object (on the client, this means it will be forwarded to the server) where it will be checked for validity and then applied to the object and dispatched to all its subscribers.

Specified by:
postEvent in interface DObjectManager
Parameters:
event - The event to be dispatched.

removedLastSubscriber

public void removedLastSubscriber(DObject obj,
                                  boolean deathWish)
Description copied from interface: DObjectManager
When a distributed object removes its last subscriber, it will call this function to let the object manager know. The manager might then choose to flush this object from the system or unregister from some upstream manager whose object it was proxying, for example.

Specified by:
removedLastSubscriber in interface DObjectManager

registerObject

public <T extends DObject> T registerObject(T object)
Description copied from interface: RootDObjectManager
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.

Specified by:
registerObject in interface RootDObjectManager
Returns:
the registered object for the caller's convenience.

destroyObject

public void destroyObject(int oid)
Description copied from interface: RootDObjectManager
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.

Specified by:
destroyObject in interface RootDObjectManager
Parameters:
oid - The object id of the distributed object to be destroyed.

newInterval

public Interval newInterval(Runnable action)
Description copied from interface: RootDObjectManager
Creates an Interval that runs the supplied runnable. If the root omgr is shutdown before the interval expires (or if the interval is scheduled to repeat), it will be automatically cancelled. This makes it easy to schedule fire-and-forget intervals:
 _omgr.newInterval(someRunnable).schedule(500); // one shot
 Interval ival = _omgr.newInterval(someRunnable).schedule(500, true); // repeater
 

Specified by:
newInterval in interface Interval.Factory
Specified by:
newInterval in interface RootDObjectManager

getObject

public DObject getObject(int oid)
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(int, com.threerings.presents.dobj.Subscriber).

Specified by:
getObject in interface RootDObjectManager

getStats

public PresentsDObjectMgr.Stats getStats(boolean snapshot)
Returns a recent snapshot of runtime statistics tracked by the distributed object manager.

Parameters:
snapshot - if true, the current stats will be snapshotted and reset and the new snapshot will be returned. If false, the previous snapshot will be returned. If no snapshot has ever been taken, the current stats that have been accumulting since the JVM start will be returned.

execute

public void execute(Runnable command)
Specified by:
execute in interface Executor

postRunnable

public void postRunnable(Runnable unit)
Posts a self-contained unit of code that should be run on the distributed object manager thread at the next available opportunity. The code will be queued up with the rest of the events and invoked in turn. Like event processing code, the code should not take long to complete and should definitely not block. From interface RunQueue

Specified by:
postRunnable in interface RunQueue

isDispatchThread

public boolean isDispatchThread()
Returns true if the thread invoking this method is the same thread that is doing distributed object event dispatch. Code that wishes to enforce that it is either always or never called on the event dispatch thread will want to make use of this method. From interface RunQueue

Specified by:
isDispatchThread in interface RunQueue

requireEventThread

public void requireEventThread()
Ensures that the calling thread is the distributed object event dispatch thread, throwing an IllegalStateException if it is not. Note: before the manager is started up, all calls to this method will succeed, as things that take place during server initialization are considered safe and only after the distributed object manager is started (and the event thread is established) will we require it.


refuseEventThread

public void refuseEventThread()
Ensures that the calling thread is not the distributed object event dispatch thread, throwing an IllegalStateException if it is.


run

public void run()
Runs the dobjmgr event loop until it is requested to exit. This should be called from the main application thread.


harshShutdown

public void harshShutdown()
Requests that the dobjmgr shut itself down directly. You may want to try using PresentsInvoker.shutdown() which will make sure that both the Invoker and DObjectMgr are empty and then shut them both down.


setUnitProfInterval

public void setUnitProfInterval(int interval)
Sets the frequency at which we take profiling samples.


getUnitProfInterval

public int getUnitProfInterval()
Returns the profiling sample frequency.


dumpUnitProfiles

public void dumpUnitProfiles()
Dumps collected profiling information to the system log.


clearUnitProfiles

public void clearUnitProfiles()
Clears the current set of unit profiles.


objectDestroyed

public boolean objectDestroyed(DEvent event,
                               DObject target)
Called as a helper for ObjectDestroyedEvent events. It removes the object from the object table.

Returns:
true if the event should be dispatched, false if it should be aborted.

objectAdded

public boolean objectAdded(DEvent event,
                           DObject target)
Called as a helper for ObjectAddedEvent events. It updates the object/oid list tracking structures.

Returns:
true if the event should be dispatched, false if it should be aborted.

objectRemoved

public boolean objectRemoved(DEvent event,
                             DObject target)
Called as a helper for ObjectRemovedEvent events. It updates the object/oid list tracking structures.

Returns:
true if the event should be dispatched, false if it should be aborted.

queueIsEmpty

public boolean queueIsEmpty()
Should not need to be called except by the invoker during shutdown to ensure that things are proceeding smoothly.


isRunning

public boolean isRunning()
Tests if the event processing thread is still running. This is required by the ConnectionManager to ensure messages posted just before or during shutdown are sent.

Specified by:
isRunning in interface RunQueue

processUnit

protected void processUnit(Object unit)
Processes a single unit from the queue.


processCompoundEvent

protected void processCompoundEvent(CompoundEvent event)
Performs the processing associated with a compound event, notifying listeners and the like.


processEvent

protected void processEvent(DEvent event)
Performs the processing associated with an event, notifying listeners and the like.


dispatchEvent

protected boolean dispatchEvent(DEvent event,
                                DObject target)
Dispatches an event after the target object has been resolved and the permissions have been checked. This is used by processEvent(com.threerings.presents.dobj.DEvent) and processCompoundEvent(com.threerings.presents.dobj.CompoundEvent).

Returns:
the value returned by DEvent.applyToObject(com.threerings.presents.dobj.DObject).

handleFatalError

protected void handleFatalError(Object causer,
                                Error error)
Attempts to recover from fatal errors but rethrows if things are freaking out too frequently.


clearReference

protected void clearReference(DObject reffer,
                              String field,
                              int reffedOid)
Called by objectDestroyed; clears out the tracking info for a reference by the supplied object to the specified oid via the specified field.


getNextOid

protected int getNextOid()

registerEventHelpers

protected void registerEventHelpers()
Registers our event helper methods.


informObjectAvailable

protected static <T extends DObject> void informObjectAvailable(Subscriber<T> sub,
                                                                T obj)
Calls Subscriber.objectAvailable(T) and catches and logs any exception thrown by the subscriber during the call.