From 8f008f394d22ada3c1017371cd8fbef06c0846c0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 29 Jan 2011 04:27:20 +0000 Subject: Flash out the prim count module --- .../CoreModules/World/Land/PrimCountModule.cs | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) (limited to 'OpenSim/Region/CoreModules') diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index 9689e04..34ef67f 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -40,6 +40,15 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.World.Land { + public class ParcelCounts + { + public int Owner = 0; + public int Group = 0; + public int Others = 0; + public Dictionary Users = + new Dictionary (); + } + public class PrimCountModule : IPrimCountModule, INonSharedRegionModule { private static readonly ILog m_log = @@ -48,6 +57,18 @@ namespace OpenSim.Region.CoreModules.World.Land private Scene m_Scene; private Dictionary m_PrimCounts = new Dictionary(); + private Dictionary m_OwnerMap = + new Dictionary(); + private Dictionary m_SimwideCounts = + new Dictionary(); + private Dictionary m_ParcelCounts = + new Dictionary(); + + // For now, a simple simwide taint to get this up. Later parcel based + // taint to allow recounting a parcel if only ownership has changed + // without recounting the whole sim. + private bool m_Tainted = true; + private Object m_TaintLock = new Object(); public Type ReplaceableInterface { @@ -89,26 +110,97 @@ namespace OpenSim.Region.CoreModules.World.Land private void OnParcelPrimCountAdd(SceneObjectGroup obj) { + // If we're tainted already, don't bother to add. The next + // access will cause a recount anyway + lock (m_TaintLock) + { + if (!m_Tainted) + AddObject(obj); + } } private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj) { + // Don't bother to update tainted counts + lock (m_TaintLock) + { + if (!m_Tainted) + RemoveObject(obj); + } } private void OnParcelPrimCountTainted() { + lock (m_TaintLock) + m_Tainted = true; } public void TaintPrimCount(ILandObject land) { + lock (m_TaintLock) + m_Tainted = true; } public void TaintPrimCount(int x, int y) { + lock (m_TaintLock) + m_Tainted = true; } public void TaintPrimCount() { + lock (m_TaintLock) + m_Tainted = true; + } + + // NOTE: Call under Taint Lock + private void AddObject(SceneObjectGroup obj) + { + if (obj.IsAttachment) + return; + if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) + return; + + Vector3 pos = obj.AbsolutePosition; + ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); + LandData landData = landObject.LandData; + + ParcelCounts parcelCounts; + if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) + { + UUID landOwner = landData.OwnerID; + int partCount = obj.Parts.Length; + + m_SimwideCounts[landOwner] += partCount; + if (parcelCounts.Users.ContainsKey(obj.OwnerID)) + parcelCounts.Users[obj.OwnerID] += partCount; + else + parcelCounts.Users[obj.OwnerID] = partCount; + + if (landData.IsGroupOwned) + { + if (obj.OwnerID == landData.GroupID) + parcelCounts.Owner += partCount; + else if (obj.GroupID == landData.GroupID) + parcelCounts.Group += partCount; + else + parcelCounts.Others += partCount; + } + else + { + if (obj.OwnerID == landData.OwnerID) + parcelCounts.Owner += partCount; + else if (obj.GroupID == landData.GroupID) + parcelCounts.Group += partCount; + else + parcelCounts.Others += partCount; + } + } + } + + // NOTE: Call under Taint Lock + private void RemoveObject(SceneObjectGroup obj) + { } public IPrimCounts GetPrimCounts(UUID parcelID) @@ -128,28 +220,110 @@ namespace OpenSim.Region.CoreModules.World.Land public int GetOwnerCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Owner; + } return 0; } public int GetGroupCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Group; + } return 0; } public int GetOthersCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Others; + } return 0; } public int GetSimulatorCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + UUID owner; + if (m_OwnerMap.TryGetValue(parcelID, out owner)) + { + int val; + if (m_SimwideCounts.TryGetValue(owner, out val)) + return val; + } + } return 0; } public int GetUserCount(UUID parcelID, UUID userID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + { + int val; + if (counts.Users.TryGetValue(userID, out val)) + return val; + } + } return 0; } + + // NOTE: This method MUST be called while holding the taint lock! + private void Recount() + { + m_OwnerMap.Clear(); + m_SimwideCounts.Clear(); + m_ParcelCounts.Clear(); + + List land = m_Scene.LandChannel.AllParcels(); + + foreach (ILandObject l in land) + { + LandData landData = l.LandData; + + m_OwnerMap[landData.GlobalID] = landData.OwnerID; + m_SimwideCounts[landData.OwnerID] = 0; + m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); + } + + m_Scene.ForEachSOG(AddObject); + + List primcountKeys = new List(m_PrimCounts.Keys); + foreach (UUID k in primcountKeys) + { + if (!m_OwnerMap.ContainsKey(k)) + m_PrimCounts.Remove(k); + } + m_Tainted = false; + } } public class PrimCounts : IPrimCounts -- cgit v1.1