diff options
-rw-r--r-- | OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs | 174 |
1 files changed, 174 insertions, 0 deletions
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; | |||
40 | 40 | ||
41 | namespace OpenSim.Region.CoreModules.World.Land | 41 | namespace OpenSim.Region.CoreModules.World.Land |
42 | { | 42 | { |
43 | public class ParcelCounts | ||
44 | { | ||
45 | public int Owner = 0; | ||
46 | public int Group = 0; | ||
47 | public int Others = 0; | ||
48 | public Dictionary <UUID, int> Users = | ||
49 | new Dictionary <UUID, int>(); | ||
50 | } | ||
51 | |||
43 | public class PrimCountModule : IPrimCountModule, INonSharedRegionModule | 52 | public class PrimCountModule : IPrimCountModule, INonSharedRegionModule |
44 | { | 53 | { |
45 | private static readonly ILog m_log = | 54 | private static readonly ILog m_log = |
@@ -48,6 +57,18 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
48 | private Scene m_Scene; | 57 | private Scene m_Scene; |
49 | private Dictionary<UUID, PrimCounts> m_PrimCounts = | 58 | private Dictionary<UUID, PrimCounts> m_PrimCounts = |
50 | new Dictionary<UUID, PrimCounts>(); | 59 | new Dictionary<UUID, PrimCounts>(); |
60 | private Dictionary<UUID, UUID> m_OwnerMap = | ||
61 | new Dictionary<UUID, UUID>(); | ||
62 | private Dictionary<UUID, int> m_SimwideCounts = | ||
63 | new Dictionary<UUID, int>(); | ||
64 | private Dictionary<UUID, ParcelCounts> m_ParcelCounts = | ||
65 | new Dictionary<UUID, ParcelCounts>(); | ||
66 | |||
67 | // For now, a simple simwide taint to get this up. Later parcel based | ||
68 | // taint to allow recounting a parcel if only ownership has changed | ||
69 | // without recounting the whole sim. | ||
70 | private bool m_Tainted = true; | ||
71 | private Object m_TaintLock = new Object(); | ||
51 | 72 | ||
52 | public Type ReplaceableInterface | 73 | public Type ReplaceableInterface |
53 | { | 74 | { |
@@ -89,26 +110,97 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
89 | 110 | ||
90 | private void OnParcelPrimCountAdd(SceneObjectGroup obj) | 111 | private void OnParcelPrimCountAdd(SceneObjectGroup obj) |
91 | { | 112 | { |
113 | // If we're tainted already, don't bother to add. The next | ||
114 | // access will cause a recount anyway | ||
115 | lock (m_TaintLock) | ||
116 | { | ||
117 | if (!m_Tainted) | ||
118 | AddObject(obj); | ||
119 | } | ||
92 | } | 120 | } |
93 | 121 | ||
94 | private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj) | 122 | private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj) |
95 | { | 123 | { |
124 | // Don't bother to update tainted counts | ||
125 | lock (m_TaintLock) | ||
126 | { | ||
127 | if (!m_Tainted) | ||
128 | RemoveObject(obj); | ||
129 | } | ||
96 | } | 130 | } |
97 | 131 | ||
98 | private void OnParcelPrimCountTainted() | 132 | private void OnParcelPrimCountTainted() |
99 | { | 133 | { |
134 | lock (m_TaintLock) | ||
135 | m_Tainted = true; | ||
100 | } | 136 | } |
101 | 137 | ||
102 | public void TaintPrimCount(ILandObject land) | 138 | public void TaintPrimCount(ILandObject land) |
103 | { | 139 | { |
140 | lock (m_TaintLock) | ||
141 | m_Tainted = true; | ||
104 | } | 142 | } |
105 | 143 | ||
106 | public void TaintPrimCount(int x, int y) | 144 | public void TaintPrimCount(int x, int y) |
107 | { | 145 | { |
146 | lock (m_TaintLock) | ||
147 | m_Tainted = true; | ||
108 | } | 148 | } |
109 | 149 | ||
110 | public void TaintPrimCount() | 150 | public void TaintPrimCount() |
111 | { | 151 | { |
152 | lock (m_TaintLock) | ||
153 | m_Tainted = true; | ||
154 | } | ||
155 | |||
156 | // NOTE: Call under Taint Lock | ||
157 | private void AddObject(SceneObjectGroup obj) | ||
158 | { | ||
159 | if (obj.IsAttachment) | ||
160 | return; | ||
161 | if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) | ||
162 | return; | ||
163 | |||
164 | Vector3 pos = obj.AbsolutePosition; | ||
165 | ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); | ||
166 | LandData landData = landObject.LandData; | ||
167 | |||
168 | ParcelCounts parcelCounts; | ||
169 | if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) | ||
170 | { | ||
171 | UUID landOwner = landData.OwnerID; | ||
172 | int partCount = obj.Parts.Length; | ||
173 | |||
174 | m_SimwideCounts[landOwner] += partCount; | ||
175 | if (parcelCounts.Users.ContainsKey(obj.OwnerID)) | ||
176 | parcelCounts.Users[obj.OwnerID] += partCount; | ||
177 | else | ||
178 | parcelCounts.Users[obj.OwnerID] = partCount; | ||
179 | |||
180 | if (landData.IsGroupOwned) | ||
181 | { | ||
182 | if (obj.OwnerID == landData.GroupID) | ||
183 | parcelCounts.Owner += partCount; | ||
184 | else if (obj.GroupID == landData.GroupID) | ||
185 | parcelCounts.Group += partCount; | ||
186 | else | ||
187 | parcelCounts.Others += partCount; | ||
188 | } | ||
189 | else | ||
190 | { | ||
191 | if (obj.OwnerID == landData.OwnerID) | ||
192 | parcelCounts.Owner += partCount; | ||
193 | else if (obj.GroupID == landData.GroupID) | ||
194 | parcelCounts.Group += partCount; | ||
195 | else | ||
196 | parcelCounts.Others += partCount; | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | |||
201 | // NOTE: Call under Taint Lock | ||
202 | private void RemoveObject(SceneObjectGroup obj) | ||
203 | { | ||
112 | } | 204 | } |
113 | 205 | ||
114 | public IPrimCounts GetPrimCounts(UUID parcelID) | 206 | public IPrimCounts GetPrimCounts(UUID parcelID) |
@@ -128,28 +220,110 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
128 | 220 | ||
129 | public int GetOwnerCount(UUID parcelID) | 221 | public int GetOwnerCount(UUID parcelID) |
130 | { | 222 | { |
223 | lock (m_TaintLock) | ||
224 | { | ||
225 | if (m_Tainted) | ||
226 | Recount(); | ||
227 | |||
228 | ParcelCounts counts; | ||
229 | if (m_ParcelCounts.TryGetValue(parcelID, out counts)) | ||
230 | return counts.Owner; | ||
231 | } | ||
131 | return 0; | 232 | return 0; |
132 | } | 233 | } |
133 | 234 | ||
134 | public int GetGroupCount(UUID parcelID) | 235 | public int GetGroupCount(UUID parcelID) |
135 | { | 236 | { |
237 | lock (m_TaintLock) | ||
238 | { | ||
239 | if (m_Tainted) | ||
240 | Recount(); | ||
241 | |||
242 | ParcelCounts counts; | ||
243 | if (m_ParcelCounts.TryGetValue(parcelID, out counts)) | ||
244 | return counts.Group; | ||
245 | } | ||
136 | return 0; | 246 | return 0; |
137 | } | 247 | } |
138 | 248 | ||
139 | public int GetOthersCount(UUID parcelID) | 249 | public int GetOthersCount(UUID parcelID) |
140 | { | 250 | { |
251 | lock (m_TaintLock) | ||
252 | { | ||
253 | if (m_Tainted) | ||
254 | Recount(); | ||
255 | |||
256 | ParcelCounts counts; | ||
257 | if (m_ParcelCounts.TryGetValue(parcelID, out counts)) | ||
258 | return counts.Others; | ||
259 | } | ||
141 | return 0; | 260 | return 0; |
142 | } | 261 | } |
143 | 262 | ||
144 | public int GetSimulatorCount(UUID parcelID) | 263 | public int GetSimulatorCount(UUID parcelID) |
145 | { | 264 | { |
265 | lock (m_TaintLock) | ||
266 | { | ||
267 | if (m_Tainted) | ||
268 | Recount(); | ||
269 | |||
270 | UUID owner; | ||
271 | if (m_OwnerMap.TryGetValue(parcelID, out owner)) | ||
272 | { | ||
273 | int val; | ||
274 | if (m_SimwideCounts.TryGetValue(owner, out val)) | ||
275 | return val; | ||
276 | } | ||
277 | } | ||
146 | return 0; | 278 | return 0; |
147 | } | 279 | } |
148 | 280 | ||
149 | public int GetUserCount(UUID parcelID, UUID userID) | 281 | public int GetUserCount(UUID parcelID, UUID userID) |
150 | { | 282 | { |
283 | lock (m_TaintLock) | ||
284 | { | ||
285 | if (m_Tainted) | ||
286 | Recount(); | ||
287 | |||
288 | ParcelCounts counts; | ||
289 | if (m_ParcelCounts.TryGetValue(parcelID, out counts)) | ||
290 | { | ||
291 | int val; | ||
292 | if (counts.Users.TryGetValue(userID, out val)) | ||
293 | return val; | ||
294 | } | ||
295 | } | ||
151 | return 0; | 296 | return 0; |
152 | } | 297 | } |
298 | |||
299 | // NOTE: This method MUST be called while holding the taint lock! | ||
300 | private void Recount() | ||
301 | { | ||
302 | m_OwnerMap.Clear(); | ||
303 | m_SimwideCounts.Clear(); | ||
304 | m_ParcelCounts.Clear(); | ||
305 | |||
306 | List<ILandObject> land = m_Scene.LandChannel.AllParcels(); | ||
307 | |||
308 | foreach (ILandObject l in land) | ||
309 | { | ||
310 | LandData landData = l.LandData; | ||
311 | |||
312 | m_OwnerMap[landData.GlobalID] = landData.OwnerID; | ||
313 | m_SimwideCounts[landData.OwnerID] = 0; | ||
314 | m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); | ||
315 | } | ||
316 | |||
317 | m_Scene.ForEachSOG(AddObject); | ||
318 | |||
319 | List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys); | ||
320 | foreach (UUID k in primcountKeys) | ||
321 | { | ||
322 | if (!m_OwnerMap.ContainsKey(k)) | ||
323 | m_PrimCounts.Remove(k); | ||
324 | } | ||
325 | m_Tainted = false; | ||
326 | } | ||
153 | } | 327 | } |
154 | 328 | ||
155 | public class PrimCounts : IPrimCounts | 329 | public class PrimCounts : IPrimCounts |