diff --git a/src/java/com/threerings/presents/client/ClientDObjectMgr.java b/src/java/com/threerings/presents/client/ClientDObjectMgr.java index 8bb9ee54d..f0fbef970 100644 --- a/src/java/com/threerings/presents/client/ClientDObjectMgr.java +++ b/src/java/com/threerings/presents/client/ClientDObjectMgr.java @@ -1,5 +1,5 @@ // -// $Id: ClientDObjectMgr.java,v 1.20 2003/01/22 02:02:04 mdb Exp $ +// $Id: ClientDObjectMgr.java,v 1.21 2003/03/10 18:29:54 mdb Exp $ package com.threerings.presents.client; @@ -47,6 +47,13 @@ public class ClientDObjectMgr DUMP_OTABLE_MODMASK, DUMP_OTABLE_KEYCODE, DUMP_OTABLE_HOOK); } + // documentation inherited from interface + public boolean isManager (DObject object) + { + // we are never authoritative in the present implementation + return false; + } + // inherit documentation from the interface public void createObject (Class dclass, Subscriber target) { diff --git a/src/java/com/threerings/presents/dobj/DObject.java b/src/java/com/threerings/presents/dobj/DObject.java index 639a821e3..b2c5cd7fc 100644 --- a/src/java/com/threerings/presents/dobj/DObject.java +++ b/src/java/com/threerings/presents/dobj/DObject.java @@ -1,5 +1,5 @@ // -// $Id: DObject.java,v 1.59 2003/02/26 17:54:56 mdb Exp $ +// $Id: DObject.java,v 1.60 2003/03/10 18:29:54 mdb Exp $ package com.threerings.presents.dobj; @@ -775,8 +775,17 @@ public class DObject implements Streamable { try { DSet set = (DSet)getAttribute(name); + // if we're on the authoritative server, we update the set + // immediately + boolean alreadyApplied = false; + if (_omgr.isManager(this)) { +// Log.info("Immediately adding [name=" + name + +// ", entry=" + entry + "]."); + set.add(entry); + alreadyApplied = true; + } // dispatch an entry added event - postEvent(new EntryAddedEvent(_oid, name, entry)); + postEvent(new EntryAddedEvent(_oid, name, entry, alreadyApplied)); } catch (ObjectAccessException oae) { Log.warning("Unable to request entryAdd [name=" + name + @@ -789,8 +798,24 @@ public class DObject implements Streamable */ protected void requestEntryRemove (String name, Comparable key) { - // dispatch an entry removed event - postEvent(new EntryRemovedEvent(_oid, name, key)); + try { + DSet set = (DSet)getAttribute(name); + // if we're on the authoritative server, we update the set + // immediately + DSet.Entry oldEntry = null; + if (_omgr.isManager(this)) { +// Log.info("Immediately removing [name=" + name + +// ", key=" + key + "]."); + oldEntry = set.get(key); + set.removeKey(key); + } + // dispatch an entry removed event + postEvent(new EntryRemovedEvent(_oid, name, key, oldEntry)); + + } catch (ObjectAccessException oae) { + Log.warning("Unable to request entryRemove [name=" + name + + ", key=" + key + ", error=" + oae + "]."); + } } /** @@ -800,8 +825,17 @@ public class DObject implements Streamable { try { DSet set = (DSet)getAttribute(name); + // if we're on the authoritative server, we update the set + // immediately + DSet.Entry oldEntry = null; + if (_omgr.isManager(this)) { +// Log.info("Immediately updating [name=" + name + +// ", entry=" + entry + "]."); + oldEntry = set.get(entry.getKey()); + set.update(entry); + } // dispatch an entry updated event - postEvent(new EntryUpdatedEvent(_oid, name, entry)); + postEvent(new EntryUpdatedEvent(_oid, name, entry, oldEntry)); } catch (ObjectAccessException oae) { Log.warning("Unable to request entryUpdate [name=" + name + diff --git a/src/java/com/threerings/presents/dobj/DObjectManager.java b/src/java/com/threerings/presents/dobj/DObjectManager.java index c82daeaa7..87136b1d3 100644 --- a/src/java/com/threerings/presents/dobj/DObjectManager.java +++ b/src/java/com/threerings/presents/dobj/DObjectManager.java @@ -1,5 +1,5 @@ // -// $Id: DObjectManager.java,v 1.10 2001/10/24 00:36:40 mdb Exp $ +// $Id: DObjectManager.java,v 1.11 2003/03/10 18:29:54 mdb Exp $ package com.threerings.presents.dobj; @@ -14,6 +14,13 @@ package com.threerings.presents.dobj; */ public interface DObjectManager { + /** + * Returns true if this distributed object manager is the + * authoritative manager for the specified distributed object, or fals + * if we are only providing a proxy to the object. + */ + public boolean isManager (DObject object); + /** * Creates a distributed object instance of the supplied class and * notifies the specified subscriber when it becomes available. This diff --git a/src/java/com/threerings/presents/dobj/EntryAddedEvent.java b/src/java/com/threerings/presents/dobj/EntryAddedEvent.java index 8f6191a34..b19033026 100644 --- a/src/java/com/threerings/presents/dobj/EntryAddedEvent.java +++ b/src/java/com/threerings/presents/dobj/EntryAddedEvent.java @@ -1,5 +1,5 @@ // -// $Id: EntryAddedEvent.java,v 1.9 2002/12/20 23:29:04 mdb Exp $ +// $Id: EntryAddedEvent.java,v 1.10 2003/03/10 18:29:54 mdb Exp $ package com.threerings.presents.dobj; @@ -27,9 +27,20 @@ public class EntryAddedEvent extends NamedEvent * @param entry the entry to add to the set attribute. */ public EntryAddedEvent (int targetOid, String name, DSet.Entry entry) + { + this(targetOid, name, entry, false); + } + + /** + * Used when the distributed object already added the entry before + * generating the event. + */ + public EntryAddedEvent (int targetOid, String name, DSet.Entry entry, + boolean alreadyApplied) { super(targetOid, name); _entry = entry; + _alreadyApplied = alreadyApplied; } /** @@ -54,8 +65,10 @@ public class EntryAddedEvent extends NamedEvent public boolean applyToObject (DObject target) throws ObjectAccessException { - DSet set = (DSet)target.getAttribute(_name); - set.add(_entry); + if (!_alreadyApplied) { + DSet set = (DSet)target.getAttribute(_name); + set.add(_entry); + } return true; } @@ -77,4 +90,9 @@ public class EntryAddedEvent extends NamedEvent } protected DSet.Entry _entry; + + /** Used when this event is generated on the authoritative server + * where object changes are made immediately. This lets us know not to + * apply ourselves when we're actually dispatched. */ + protected transient boolean _alreadyApplied; } diff --git a/src/java/com/threerings/presents/dobj/EntryRemovedEvent.java b/src/java/com/threerings/presents/dobj/EntryRemovedEvent.java index 5ecf992e4..ee69b9e76 100644 --- a/src/java/com/threerings/presents/dobj/EntryRemovedEvent.java +++ b/src/java/com/threerings/presents/dobj/EntryRemovedEvent.java @@ -1,5 +1,5 @@ // -// $Id: EntryRemovedEvent.java,v 1.13 2003/02/26 21:41:47 mdb Exp $ +// $Id: EntryRemovedEvent.java,v 1.14 2003/03/10 18:29:54 mdb Exp $ package com.threerings.presents.dobj; @@ -24,9 +24,20 @@ public class EntryRemovedEvent extends NamedEvent * @param key the entry key that identifies the entry to remove. */ public EntryRemovedEvent (int targetOid, String name, Comparable key) + { + this(targetOid, name, key, null); + } + + /** + * Used when the distributed object already removed the entry before + * generating the event. + */ + public EntryRemovedEvent (int targetOid, String name, Comparable key, + DSet.Entry oldEntry) { super(targetOid, name); _key = key; + _oldEntry = oldEntry; } /** @@ -59,11 +70,13 @@ public class EntryRemovedEvent extends NamedEvent public boolean applyToObject (DObject target) throws ObjectAccessException { - DSet set = (DSet)target.getAttribute(_name); - // fetch the previous value for interested callers - _oldEntry = set.get(_key); - // remove it from the set - set.removeKey(_key); + if (_oldEntry == null) { + DSet set = (DSet)target.getAttribute(_name); + // fetch the previous value for interested callers + _oldEntry = set.get(_key); + // remove it from the set + set.removeKey(_key); + } return true; } diff --git a/src/java/com/threerings/presents/dobj/EntryUpdatedEvent.java b/src/java/com/threerings/presents/dobj/EntryUpdatedEvent.java index 8e7632412..21fb46231 100644 --- a/src/java/com/threerings/presents/dobj/EntryUpdatedEvent.java +++ b/src/java/com/threerings/presents/dobj/EntryUpdatedEvent.java @@ -1,5 +1,5 @@ // -// $Id: EntryUpdatedEvent.java,v 1.9 2002/12/20 23:29:04 mdb Exp $ +// $Id: EntryUpdatedEvent.java,v 1.10 2003/03/10 18:29:54 mdb Exp $ package com.threerings.presents.dobj; @@ -27,9 +27,20 @@ public class EntryUpdatedEvent extends NamedEvent * @param entry the entry to update. */ public EntryUpdatedEvent (int targetOid, String name, DSet.Entry entry) + { + this(targetOid, name, entry, null); + } + + /** + * Used when the distributed object already updated the entry before + * generating the event. + */ + public EntryUpdatedEvent (int targetOid, String name, DSet.Entry entry, + DSet.Entry oldEntry) { super(targetOid, name); _entry = entry; + _oldEntry = oldEntry; } /** @@ -62,19 +73,20 @@ public class EntryUpdatedEvent extends NamedEvent public boolean applyToObject (DObject target) throws ObjectAccessException { - DSet set = (DSet)target.getAttribute(_name); + if (_oldEntry == null) { + DSet set = (DSet)target.getAttribute(_name); - // fetch the previous value for interested callers - _oldEntry = set.get(_entry.getKey()); + // fetch the previous value for interested callers + _oldEntry = set.get(_entry.getKey()); - // update the entry - if (!set.update(_entry)) { - // complain if we didn't update anything - Log.warning("No matching entry to update [entry=" + this + - ", set=" + set + "]."); - return false; + // update the entry + if (!set.update(_entry)) { + // complain if we didn't update anything + Log.warning("No matching entry to update [entry=" + this + + ", set=" + set + "]."); + return false; + } } - return true; } diff --git a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java index d62063580..d9b6ad4f3 100644 --- a/src/java/com/threerings/presents/server/PresentsDObjectMgr.java +++ b/src/java/com/threerings/presents/server/PresentsDObjectMgr.java @@ -1,5 +1,5 @@ // -// $Id: PresentsDObjectMgr.java,v 1.28 2003/01/27 22:56:29 mdb Exp $ +// $Id: PresentsDObjectMgr.java,v 1.29 2003/03/10 18:29:54 mdb Exp $ package com.threerings.presents.server; @@ -60,6 +60,13 @@ public class PresentsDObjectMgr _defaultController = controller; } + // documentation inherited from interface + 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) {