From 335ef8eb05600e7f79c65b8718a337c9238a7b66 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Fri, 13 Sep 2002 00:20:43 +0000 Subject: [PATCH] New occupant info handling facilities that prevent rapid fire modifiers from stepping on one anothers' toes. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1676 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../threerings/crowd/data/PlaceObject.dobj | 10 ++- .../threerings/crowd/data/PlaceObject.java | 10 ++- .../crowd/server/LocationProvider.java | 11 ++-- .../threerings/crowd/server/PlaceManager.java | 63 ++++++++++++++++--- .../whirled/spot/server/SpotSceneManager.java | 7 +-- 5 files changed, 79 insertions(+), 22 deletions(-) diff --git a/src/java/com/threerings/crowd/data/PlaceObject.dobj b/src/java/com/threerings/crowd/data/PlaceObject.dobj index 6ef3aaa09..b3caaf62e 100644 --- a/src/java/com/threerings/crowd/data/PlaceObject.dobj +++ b/src/java/com/threerings/crowd/data/PlaceObject.dobj @@ -1,5 +1,5 @@ // -// $Id: PlaceObject.dobj,v 1.10 2002/08/14 19:07:49 mdb Exp $ +// $Id: PlaceObject.dobj,v 1.11 2002/09/13 00:20:43 mdb Exp $ package com.threerings.crowd.data; @@ -20,7 +20,13 @@ public class PlaceObject extends DObject /** * Contains an info record (of type {@link OccupantInfo}) for each * occupant that contains information about that occupant that needs - * to be known by everyone in the place. + * to be known by everyone in the place. Note: Don't obtain + * occupant info records directly from this set when on the server, + * use PlaceManager.getOccupantInfo() instead (along with + * PlaceManager.updateOccupantInfo()) because it does + * some special processing to ensure that readers and updaters don't + * step on one another even if they make rapid fire changes to a + * user's occupant info. */ public DSet occupantInfo = new DSet(); diff --git a/src/java/com/threerings/crowd/data/PlaceObject.java b/src/java/com/threerings/crowd/data/PlaceObject.java index 181a07d70..9b790338f 100644 --- a/src/java/com/threerings/crowd/data/PlaceObject.java +++ b/src/java/com/threerings/crowd/data/PlaceObject.java @@ -1,5 +1,5 @@ // -// $Id: PlaceObject.java,v 1.7 2002/08/14 19:07:49 mdb Exp $ +// $Id: PlaceObject.java,v 1.8 2002/09/13 00:20:43 mdb Exp $ package com.threerings.crowd.data; @@ -29,7 +29,13 @@ public class PlaceObject extends DObject /** * Contains an info record (of type {@link OccupantInfo}) for each * occupant that contains information about that occupant that needs - * to be known by everyone in the place. + * to be known by everyone in the place. Note: Don't obtain + * occupant info records directly from this set when on the server, + * use PlaceManager.getOccupantInfo() instead (along with + * PlaceManager.updateOccupantInfo()) because it does + * some special processing to ensure that readers and updaters don't + * step on one another even if they make rapid fire changes to a + * user's occupant info. */ public DSet occupantInfo = new DSet(); diff --git a/src/java/com/threerings/crowd/server/LocationProvider.java b/src/java/com/threerings/crowd/server/LocationProvider.java index be6005240..fcca2317b 100644 --- a/src/java/com/threerings/crowd/server/LocationProvider.java +++ b/src/java/com/threerings/crowd/server/LocationProvider.java @@ -1,5 +1,5 @@ // -// $Id: LocationProvider.java,v 1.16 2002/08/14 19:07:49 mdb Exp $ +// $Id: LocationProvider.java,v 1.17 2002/09/13 00:20:43 mdb Exp $ package com.threerings.crowd.server; @@ -107,12 +107,9 @@ public class LocationProvider // remove them from any previous location leaveOccupiedPlace(source); - // generate a new occupant info record and add it to the - // target location - OccupantInfo info = pmgr.buildOccupantInfo(source); - if (info != null) { - place.addToOccupantInfo(info); - } + // generate a new occupant info record (which will add it + // to the target location) + pmgr.buildOccupantInfo(source); // set the body's new location source.setLocation(place.getOid()); diff --git a/src/java/com/threerings/crowd/server/PlaceManager.java b/src/java/com/threerings/crowd/server/PlaceManager.java index 75fb599f0..d27f25417 100644 --- a/src/java/com/threerings/crowd/server/PlaceManager.java +++ b/src/java/com/threerings/crowd/server/PlaceManager.java @@ -1,5 +1,5 @@ // -// $Id: PlaceManager.java,v 1.32 2002/08/14 19:07:49 mdb Exp $ +// $Id: PlaceManager.java,v 1.33 2002/09/13 00:20:43 mdb Exp $ package com.threerings.crowd.server; @@ -7,6 +7,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Properties; +import com.samskivert.util.HashIntMap; + import com.threerings.presents.data.ClientObject; import com.threerings.presents.server.InvocationManager; @@ -86,6 +88,38 @@ public class PlaceManager return _plobj; } + /** + * Returns the occupant info record for the user with the specified + * body oid, if they are an occupant of this room. Returns null + * otherwise. + */ + public OccupantInfo getOccupantInfo (int bodyOid) + { + return (OccupantInfo)_occInfo.get(bodyOid); + } + + /** + * Updates the occupant info for this room occupant. Note: + * This must be used rather than setting the occupant info directly to + * avoid possible complications due to rapid fire changes to a user's + * occupant info. The occupant info record supplied to this method + * must be one returned from {@link #getOccupantInfo}. For example: + * + *
+     * OccupantInfo info = _plmgr.getOccupantInfo(bodyOid);
+     * // ... modifications made to 'info'
+     * _plmgr.updateOccupantInfo(info);
+     * 
+ */ + public void updateOccupantInfo (OccupantInfo occInfo) + { + // update the canonical copy + _occInfo.put(occInfo.getBodyOid(), occInfo); + // clone the canonical copy and send out an event updating the + // distributed set with that clone + _plobj.updateOccupantInfo((OccupantInfo)occInfo.clone()); + } + /** * A place manager derived class is likely to have a corresponding * derived class of {@link com.threerings.crowd.data.PlaceObject} that @@ -216,19 +250,28 @@ public class PlaceManager } /** - * Builds an occupant info record for the specified body object. This - * is called by the location services when a body enters a place. It - * should not be overridden by derived classes, they should override - * {@link #populateOccupantInfo}, which is set up for that sort of - * thing. + * Builds an occupant info record for the specified body object and + * inserts it into our place object. This is called by the location + * services when a body enters a place. It should not be overridden by + * derived classes, they should override {@link + * #populateOccupantInfo}, which is set up for that sort of thing. */ public OccupantInfo buildOccupantInfo (BodyObject body) { - // create a new occupant info instance try { + // create a new occupant info instance OccupantInfo info = (OccupantInfo) getOccupantInfoClass(body).newInstance(); + + // configure it with the appropriate values populateOccupantInfo(info, body); + + // insert the occupant info into our canonical table + _occInfo.put(info.getBodyOid(), info); + + // and insert it into the place object + _plobj.addToOccupantInfo(info); + return info; } catch (Exception e) { @@ -294,6 +337,9 @@ public class PlaceManager _plobj.removeFromOccupantInfo(key); } + // clear out their canonical (local) occupant info record + _occInfo.remove(bodyOid); + // let our delegates know what's up applyToDelegates(new DelegateOp() { public void apply (PlaceManagerDelegate delegate) { @@ -484,4 +530,7 @@ public class PlaceManager /** A list of the delegates in use by this manager. */ protected ArrayList _delegates; + + /** Used to keep a canonical copy of the occupant info records. */ + protected HashIntMap _occInfo = new HashIntMap(); } diff --git a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java index 13637df6d..55b51b5a1 100644 --- a/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java +++ b/src/java/com/threerings/whirled/spot/server/SpotSceneManager.java @@ -1,5 +1,5 @@ // -// $Id: SpotSceneManager.java,v 1.19 2002/09/12 23:04:04 ray Exp $ +// $Id: SpotSceneManager.java,v 1.20 2002/09/13 00:20:43 mdb Exp $ package com.threerings.whirled.spot.server; @@ -203,8 +203,7 @@ public class SpotSceneManager extends SceneManager // make sure they have an occupant info object in the place int bodyOid = source.getOid(); - SpotOccupantInfo soi = (SpotOccupantInfo) - _plobj.occupantInfo.get(new Integer(bodyOid)); + SpotOccupantInfo soi = (SpotOccupantInfo)getOccupantInfo(bodyOid); if (soi == null) { Log.warning("Aiya! Can't update non-existent occupant info " + "with new location [where=" + where() + @@ -231,7 +230,7 @@ public class SpotSceneManager extends SceneManager // update the location and broadcast to the place soi.locationId = locationId; - _plobj.updateOccupantInfo(soi); + updateOccupantInfo(soi); // figure out the cluster chat oid int clusterIdx = _sscene.getClusterIndex(locidx);