123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Reflection;
- using log4net;
- using Nini.Config;
- using OpenMetaverse;
- using OpenSim.Framework;
- using Mono.Addins;
- using OpenSim.Region.Framework.Interfaces;
- using OpenSim.Region.Framework.Scenes;
- 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 int Selected = 0;
- public Dictionary <UUID, int> Users = new Dictionary <UUID, int>();
- }
- [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PrimCountModule")]
- public class PrimCountModule : IPrimCountModule, INonSharedRegionModule
- {
- // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private Scene m_Scene;
- private Dictionary<UUID, PrimCounts> m_PrimCounts =
- new Dictionary<UUID, PrimCounts>();
- private Dictionary<UUID, UUID> m_OwnerMap =
- new Dictionary<UUID, UUID>();
- private Dictionary<UUID, int> m_SimwideCounts =
- new Dictionary<UUID, int>();
- private Dictionary<UUID, ParcelCounts> m_ParcelCounts =
- new Dictionary<UUID, ParcelCounts>();
- /// <value>
- /// 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.
- ///
- /// We start out tainted so that the first get call resets the various prim counts.
- /// </value>
- private bool m_Tainted = true;
- private Object m_TaintLock = new Object();
- public Type ReplaceableInterface
- {
- get { return null; }
- }
- public void Initialise(IConfigSource source)
- {
- }
- public void AddRegion(Scene scene)
- {
- m_Scene = scene;
- m_Scene.RegisterModuleInterface<IPrimCountModule>(this);
- m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd;
- m_Scene.EventManager.OnObjectBeingRemovedFromScene += OnObjectBeingRemovedFromScene;
- m_Scene.EventManager.OnParcelPrimCountTainted += OnParcelPrimCountTainted;
- m_Scene.EventManager.OnLandObjectAdded += delegate(ILandObject lo) { OnParcelPrimCountTainted(); };
- }
- public void RegionLoaded(Scene scene)
- {
- }
- public void RemoveRegion(Scene scene)
- {
- }
- public void Close()
- {
- }
- public string Name
- {
- get { return "PrimCountModule"; }
- }
- 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);
- // else
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted",
- // obj.Name, m_Scene.RegionInfo.RegionName);
- }
- }
- private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj)
- {
- // Don't bother to update tainted counts
- lock (m_TaintLock)
- {
- if (!m_Tainted)
- RemoveObject(obj);
- // else
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: Ignoring OnObjectBeingRemovedFromScene() for {0} on {1} since count is tainted",
- // obj.Name, m_Scene.RegionInfo.RegionName);
- }
- }
- private void OnParcelPrimCountTainted()
- {
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: OnParcelPrimCountTainted() called on {0}", m_Scene.RegionInfo.RegionName);
- 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);
- // If for some reason there is no land object (perhaps the object is out of bounds) then we can't count it
- if (landObject == null)
- {
- // m_log.WarnFormat(
- // "[PRIM COUNT MODULE]: Found no land object for {0} at position ({1}, {2}) on {3}",
- // obj.Name, pos.X, pos.Y, m_Scene.RegionInfo.RegionName);
- return;
- }
- LandData landData = landObject.LandData;
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: Adding object {0} with {1} parts to prim count for parcel {2} on {3}",
- // obj.Name, obj.Parts.Length, landData.Name, m_Scene.RegionInfo.RegionName);
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}",
- // obj.Name, obj.OwnerID, landData.OwnerID);
- ParcelCounts parcelCounts;
- if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
- {
- UUID landOwner = landData.OwnerID;
- int partCount = obj.GetPartCount();
- m_SimwideCounts[landOwner] += partCount;
- if (parcelCounts.Users.ContainsKey(obj.OwnerID))
- parcelCounts.Users[obj.OwnerID] += partCount;
- else
- parcelCounts.Users[obj.OwnerID] = partCount;
- if (obj.IsSelected || obj.GetSittingAvatarsCount() > 0)
- parcelCounts.Selected += partCount;
- if (obj.OwnerID.Equals(landData.OwnerID))
- parcelCounts.Owner += partCount;
- else if (!landData.GroupID.IsZero() && obj.GroupID.Equals(landData.GroupID))
- parcelCounts.Group += partCount;
- else
- parcelCounts.Others += partCount;
- }
- }
- // NOTE: Call under Taint Lock
- private void RemoveObject(SceneObjectGroup obj)
- {
- // m_log.DebugFormat("[PRIM COUNT MODULE]: Removing object {0} {1} from prim count", obj.Name, obj.UUID);
- // Currently this is being done by tainting the count instead.
- }
- public IPrimCounts GetPrimCounts(UUID parcelID)
- {
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetPrimCounts for parcel {0} in {1}", parcelID, m_Scene.RegionInfo.RegionName);
- PrimCounts primCounts;
- lock (m_PrimCounts)
- {
- if (m_PrimCounts.TryGetValue(parcelID, out primCounts))
- return primCounts;
- primCounts = new PrimCounts(parcelID, this);
- m_PrimCounts[parcelID] = primCounts;
- }
- return primCounts;
- }
- /// <summary>
- /// Get the number of prims on the parcel that are owned by the parcel owner.
- /// </summary>
- /// <param name="parcelID"></param>
- /// <returns></returns>
- public int GetOwnerCount(UUID parcelID)
- {
- int count = 0;
- lock (m_TaintLock)
- {
- if (m_Tainted)
- Recount();
- ParcelCounts counts;
- if (m_ParcelCounts.TryGetValue(parcelID, out counts))
- count = counts.Owner;
- }
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetOwnerCount for parcel {0} in {1} returning {2}",
- // parcelID, m_Scene.RegionInfo.RegionName, count);
- return count;
- }
- /// <summary>
- /// Get the number of prims on the parcel that have been set to the group that owns the parcel.
- /// </summary>
- /// <param name="parcelID"></param>
- /// <returns></returns>
- public int GetGroupCount(UUID parcelID)
- {
- int count = 0;
- lock (m_TaintLock)
- {
- if (m_Tainted)
- Recount();
- ParcelCounts counts;
- if (m_ParcelCounts.TryGetValue(parcelID, out counts))
- count = counts.Group;
- }
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetGroupCount for parcel {0} in {1} returning {2}",
- // parcelID, m_Scene.RegionInfo.RegionName, count);
- return count;
- }
- /// <summary>
- /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group.
- /// </summary>
- /// <param name="parcelID"></param>
- /// <returns></returns>
- public int GetOthersCount(UUID parcelID)
- {
- int count = 0;
- lock (m_TaintLock)
- {
- if (m_Tainted)
- Recount();
- ParcelCounts counts;
- if (m_ParcelCounts.TryGetValue(parcelID, out counts))
- count = counts.Others;
- }
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
- // parcelID, m_Scene.RegionInfo.RegionName, count);
- return count;
- }
- /// <summary>
- /// Get the number of selected prims.
- /// </summary>
- /// <param name="parcelID"></param>
- /// <returns></returns>
- public int GetSelectedCount(UUID parcelID)
- {
- int count = 0;
- lock (m_TaintLock)
- {
- if (m_Tainted)
- Recount();
- ParcelCounts counts;
- if (m_ParcelCounts.TryGetValue(parcelID, out counts))
- count = counts.Selected;
- }
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetSelectedCount for parcel {0} in {1} returning {2}",
- // parcelID, m_Scene.RegionInfo.RegionName, count);
- return count;
- }
- /// <summary>
- /// Get the total count of owner, group and others prims on the parcel.
- /// FIXME: Need to do selected prims once this is reimplemented.
- /// </summary>
- /// <param name="parcelID"></param>
- /// <returns></returns>
- public int GetTotalCount(UUID parcelID)
- {
- int count = 0;
- lock (m_TaintLock)
- {
- if (m_Tainted)
- Recount();
- ParcelCounts counts;
- if (m_ParcelCounts.TryGetValue(parcelID, out counts))
- {
- count = counts.Owner;
- count += counts.Group;
- count += counts.Others;
- }
- }
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetTotalCount for parcel {0} in {1} returning {2}",
- // parcelID, m_Scene.RegionInfo.RegionName, count);
- return count;
- }
- /// <summary>
- /// Get the number of prims that are in the entire simulator for the owner of this parcel.
- /// </summary>
- /// <param name="parcelID"></param>
- /// <returns></returns>
- public int GetSimulatorCount(UUID parcelID)
- {
- int count = 0;
- 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))
- count = val;
- }
- }
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
- // parcelID, m_Scene.RegionInfo.RegionName, count);
- return count;
- }
- /// <summary>
- /// Get the number of prims that a particular user owns on this parcel.
- /// </summary>
- /// <param name="parcelID"></param>
- /// <param name="userID"></param>
- /// <returns></returns>
- public int GetUserCount(UUID parcelID, UUID userID)
- {
- int count = 0;
- 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))
- count = val;
- }
- }
- // m_log.DebugFormat(
- // "[PRIM COUNT MODULE]: GetUserCount for user {0} in parcel {1} in region {2} returning {3}",
- // userID, parcelID, m_Scene.RegionInfo.RegionName, count);
- return count;
- }
- // NOTE: This method MUST be called while holding the taint lock!
- private void Recount()
- {
- // m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName);
- m_OwnerMap.Clear();
- m_SimwideCounts.Clear();
- m_ParcelCounts.Clear();
- List<ILandObject> 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_log.DebugFormat(
- // "[PRIM COUNT MODULE]: Initializing parcel count for {0} on {1}",
- // landData.Name, m_Scene.RegionInfo.RegionName);
- m_ParcelCounts[landData.GlobalID] = new ParcelCounts();
- }
- m_Scene.ForEachSOG(AddObject);
- lock (m_PrimCounts)
- {
- List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys);
- foreach (UUID k in primcountKeys)
- {
- if (!m_OwnerMap.ContainsKey(k))
- m_PrimCounts.Remove(k);
- }
- }
- m_Tainted = false;
- }
- }
- public class PrimCounts : IPrimCounts
- {
- private PrimCountModule m_Parent;
- private UUID m_ParcelID;
- private UserPrimCounts m_UserPrimCounts;
- public PrimCounts (UUID parcelID, PrimCountModule parent)
- {
- m_ParcelID = parcelID;
- m_Parent = parent;
- m_UserPrimCounts = new UserPrimCounts(this);
- }
- public int Owner
- {
- get
- {
- return m_Parent.GetOwnerCount(m_ParcelID);
- }
- }
- public int Group
- {
- get
- {
- return m_Parent.GetGroupCount(m_ParcelID);
- }
- }
- public int Others
- {
- get
- {
- return m_Parent.GetOthersCount(m_ParcelID);
- }
- }
- public int Selected
- {
- get
- {
- return m_Parent.GetSelectedCount(m_ParcelID);
- }
- }
- public int Total
- {
- get
- {
- return m_Parent.GetTotalCount(m_ParcelID);
- }
- }
- public int Simulator
- {
- get
- {
- return m_Parent.GetSimulatorCount(m_ParcelID);
- }
- }
- public IUserPrimCounts Users
- {
- get
- {
- return m_UserPrimCounts;
- }
- }
- public int GetUserCount(UUID userID)
- {
- return m_Parent.GetUserCount(m_ParcelID, userID);
- }
- }
- public class UserPrimCounts : IUserPrimCounts
- {
- private PrimCounts m_Parent;
- public UserPrimCounts(PrimCounts parent)
- {
- m_Parent = parent;
- }
- public int this[UUID userID]
- {
- get
- {
- return m_Parent.GetUserCount(userID);
- }
- }
- }
- }
|