opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Diagnostics;
32 using System.Reflection;
33 using log4net;
34 using Nini.Config;
35 using OpenMetaverse;
36 using OpenSim.Framework;
37 using Mono.Addins;
38 using OpenSim.Region.Framework.Interfaces;
39 using OpenSim.Region.Framework.Scenes;
40 using OpenSim.Services.Interfaces;
41  
42 namespace OpenSim.Region.CoreModules.World.Land
43 {
44 public class ParcelCounts
45 {
46 public int Owner = 0;
47 public int Group = 0;
48 public int Others = 0;
49 public int Selected = 0;
50 public Dictionary <UUID, int> Users = new Dictionary <UUID, int>();
51 }
52  
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PrimCountModule")]
54 public class PrimCountModule : IPrimCountModule, INonSharedRegionModule
55 {
56 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57  
58 private Scene m_Scene;
59 private Dictionary<UUID, PrimCounts> m_PrimCounts =
60 new Dictionary<UUID, PrimCounts>();
61 private Dictionary<UUID, UUID> m_OwnerMap =
62 new Dictionary<UUID, UUID>();
63 private Dictionary<UUID, int> m_SimwideCounts =
64 new Dictionary<UUID, int>();
65 private Dictionary<UUID, ParcelCounts> m_ParcelCounts =
66 new Dictionary<UUID, ParcelCounts>();
67  
68 /// <value>
69 /// For now, a simple simwide taint to get this up. Later parcel based
70 /// taint to allow recounting a parcel if only ownership has changed
71 /// without recounting the whole sim.
72 ///
73 /// We start out tainted so that the first get call resets the various prim counts.
74 /// </value>
75 private bool m_Tainted = true;
76  
77 private Object m_TaintLock = new Object();
78  
79 public Type ReplaceableInterface
80 {
81 get { return null; }
82 }
83  
84 public void Initialise(IConfigSource source)
85 {
86 }
87  
88 public void AddRegion(Scene scene)
89 {
90 m_Scene = scene;
91  
92 m_Scene.RegisterModuleInterface<IPrimCountModule>(this);
93  
94 m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd;
95 m_Scene.EventManager.OnObjectBeingRemovedFromScene +=
96 OnObjectBeingRemovedFromScene;
97 m_Scene.EventManager.OnParcelPrimCountTainted +=
98 OnParcelPrimCountTainted;
99 m_Scene.EventManager.OnLandObjectAdded += delegate(ILandObject lo) { OnParcelPrimCountTainted(); };
100 }
101  
102 public void RegionLoaded(Scene scene)
103 {
104 }
105  
106 public void RemoveRegion(Scene scene)
107 {
108 }
109  
110 public void Close()
111 {
112 }
113  
114 public string Name
115 {
116 get { return "PrimCountModule"; }
117 }
118  
119 private void OnParcelPrimCountAdd(SceneObjectGroup obj)
120 {
121 // If we're tainted already, don't bother to add. The next
122 // access will cause a recount anyway
123 lock (m_TaintLock)
124 {
125 if (!m_Tainted)
126 AddObject(obj);
127 // else
128 // m_log.DebugFormat(
129 // "[PRIM COUNT MODULE]: Ignoring OnParcelPrimCountAdd() for {0} on {1} since count is tainted",
130 // obj.Name, m_Scene.RegionInfo.RegionName);
131 }
132 }
133  
134 private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj)
135 {
136 // Don't bother to update tainted counts
137 lock (m_TaintLock)
138 {
139 if (!m_Tainted)
140 RemoveObject(obj);
141 // else
142 // m_log.DebugFormat(
143 // "[PRIM COUNT MODULE]: Ignoring OnObjectBeingRemovedFromScene() for {0} on {1} since count is tainted",
144 // obj.Name, m_Scene.RegionInfo.RegionName);
145 }
146 }
147  
148 private void OnParcelPrimCountTainted()
149 {
150 // m_log.DebugFormat(
151 // "[PRIM COUNT MODULE]: OnParcelPrimCountTainted() called on {0}", m_Scene.RegionInfo.RegionName);
152  
153 lock (m_TaintLock)
154 m_Tainted = true;
155 }
156  
157 public void TaintPrimCount(ILandObject land)
158 {
159 lock (m_TaintLock)
160 m_Tainted = true;
161 }
162  
163 public void TaintPrimCount(int x, int y)
164 {
165 lock (m_TaintLock)
166 m_Tainted = true;
167 }
168  
169 public void TaintPrimCount()
170 {
171 lock (m_TaintLock)
172 m_Tainted = true;
173 }
174  
175 // NOTE: Call under Taint Lock
176 private void AddObject(SceneObjectGroup obj)
177 {
178 if (obj.IsAttachment)
179 return;
180 if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0))
181 return;
182  
183 Vector3 pos = obj.AbsolutePosition;
184 ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
185  
186 // If for some reason there is no land object (perhaps the object is out of bounds) then we can't count it
187 if (landObject == null)
188 {
189 // m_log.WarnFormat(
190 // "[PRIM COUNT MODULE]: Found no land object for {0} at position ({1}, {2}) on {3}",
191 // obj.Name, pos.X, pos.Y, m_Scene.RegionInfo.RegionName);
192  
193 return;
194 }
195  
196 LandData landData = landObject.LandData;
197  
198 // m_log.DebugFormat(
199 // "[PRIM COUNT MODULE]: Adding object {0} with {1} parts to prim count for parcel {2} on {3}",
200 // obj.Name, obj.Parts.Length, landData.Name, m_Scene.RegionInfo.RegionName);
201  
202 // m_log.DebugFormat(
203 // "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}",
204 // obj.Name, obj.OwnerID, landData.OwnerID);
205  
206 ParcelCounts parcelCounts;
207 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
208 {
209 UUID landOwner = landData.OwnerID;
210 int partCount = obj.Parts.Length;
211  
212 m_SimwideCounts[landOwner] += partCount;
213 if (parcelCounts.Users.ContainsKey(obj.OwnerID))
214 parcelCounts.Users[obj.OwnerID] += partCount;
215 else
216 parcelCounts.Users[obj.OwnerID] = partCount;
217  
218 if (obj.IsSelected)
219 {
220 parcelCounts.Selected += partCount;
221 }
222 else
223 {
224 if (landData.IsGroupOwned)
225 {
226 if (obj.OwnerID == landData.GroupID)
227 parcelCounts.Owner += partCount;
228 else if (landData.GroupID != UUID.Zero && obj.GroupID == landData.GroupID)
229 parcelCounts.Group += partCount;
230 else
231 parcelCounts.Others += partCount;
232 }
233 else
234 {
235 if (obj.OwnerID == landData.OwnerID)
236 parcelCounts.Owner += partCount;
237 else
238 parcelCounts.Others += partCount;
239 }
240 }
241 }
242 }
243  
244 // NOTE: Call under Taint Lock
245 private void RemoveObject(SceneObjectGroup obj)
246 {
247 // m_log.DebugFormat("[PRIM COUNT MODULE]: Removing object {0} {1} from prim count", obj.Name, obj.UUID);
248  
249 // Currently this is being done by tainting the count instead.
250 }
251  
252 public IPrimCounts GetPrimCounts(UUID parcelID)
253 {
254 // m_log.DebugFormat(
255 // "[PRIM COUNT MODULE]: GetPrimCounts for parcel {0} in {1}", parcelID, m_Scene.RegionInfo.RegionName);
256  
257 PrimCounts primCounts;
258  
259 lock (m_PrimCounts)
260 {
261 if (m_PrimCounts.TryGetValue(parcelID, out primCounts))
262 return primCounts;
263  
264 primCounts = new PrimCounts(parcelID, this);
265 m_PrimCounts[parcelID] = primCounts;
266 }
267 return primCounts;
268 }
269  
270  
271 /// <summary>
272 /// Get the number of prims on the parcel that are owned by the parcel owner.
273 /// </summary>
274 /// <param name="parcelID"></param>
275 /// <returns></returns>
276 public int GetOwnerCount(UUID parcelID)
277 {
278 int count = 0;
279  
280 lock (m_TaintLock)
281 {
282 if (m_Tainted)
283 Recount();
284  
285 ParcelCounts counts;
286 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
287 count = counts.Owner;
288 }
289  
290 // m_log.DebugFormat(
291 // "[PRIM COUNT MODULE]: GetOwnerCount for parcel {0} in {1} returning {2}",
292 // parcelID, m_Scene.RegionInfo.RegionName, count);
293  
294 return count;
295 }
296  
297 /// <summary>
298 /// Get the number of prims on the parcel that have been set to the group that owns the parcel.
299 /// </summary>
300 /// <param name="parcelID"></param>
301 /// <returns></returns>
302 public int GetGroupCount(UUID parcelID)
303 {
304 int count = 0;
305  
306 lock (m_TaintLock)
307 {
308 if (m_Tainted)
309 Recount();
310  
311 ParcelCounts counts;
312 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
313 count = counts.Group;
314 }
315  
316 // m_log.DebugFormat(
317 // "[PRIM COUNT MODULE]: GetGroupCount for parcel {0} in {1} returning {2}",
318 // parcelID, m_Scene.RegionInfo.RegionName, count);
319  
320 return count;
321 }
322  
323 /// <summary>
324 /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group.
325 /// </summary>
326 /// <param name="parcelID"></param>
327 /// <returns></returns>
328 public int GetOthersCount(UUID parcelID)
329 {
330 int count = 0;
331  
332 lock (m_TaintLock)
333 {
334 if (m_Tainted)
335 Recount();
336  
337 ParcelCounts counts;
338 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
339 count = counts.Others;
340 }
341  
342 // m_log.DebugFormat(
343 // "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
344 // parcelID, m_Scene.RegionInfo.RegionName, count);
345  
346 return count;
347 }
348  
349 /// <summary>
350 /// Get the number of selected prims.
351 /// </summary>
352 /// <param name="parcelID"></param>
353 /// <returns></returns>
354 public int GetSelectedCount(UUID parcelID)
355 {
356 int count = 0;
357  
358 lock (m_TaintLock)
359 {
360 if (m_Tainted)
361 Recount();
362  
363 ParcelCounts counts;
364 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
365 count = counts.Selected;
366 }
367  
368 // m_log.DebugFormat(
369 // "[PRIM COUNT MODULE]: GetSelectedCount for parcel {0} in {1} returning {2}",
370 // parcelID, m_Scene.RegionInfo.RegionName, count);
371  
372 return count;
373 }
374  
375 /// <summary>
376 /// Get the total count of owner, group and others prims on the parcel.
377 /// FIXME: Need to do selected prims once this is reimplemented.
378 /// </summary>
379 /// <param name="parcelID"></param>
380 /// <returns></returns>
381 public int GetTotalCount(UUID parcelID)
382 {
383 int count = 0;
384  
385 lock (m_TaintLock)
386 {
387 if (m_Tainted)
388 Recount();
389  
390 ParcelCounts counts;
391 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
392 {
393 count = counts.Owner;
394 count += counts.Group;
395 count += counts.Others;
396 count += counts.Selected;
397 }
398 }
399  
400 // m_log.DebugFormat(
401 // "[PRIM COUNT MODULE]: GetTotalCount for parcel {0} in {1} returning {2}",
402 // parcelID, m_Scene.RegionInfo.RegionName, count);
403  
404 return count;
405 }
406  
407 /// <summary>
408 /// Get the number of prims that are in the entire simulator for the owner of this parcel.
409 /// </summary>
410 /// <param name="parcelID"></param>
411 /// <returns></returns>
412 public int GetSimulatorCount(UUID parcelID)
413 {
414 int count = 0;
415  
416 lock (m_TaintLock)
417 {
418 if (m_Tainted)
419 Recount();
420  
421 UUID owner;
422 if (m_OwnerMap.TryGetValue(parcelID, out owner))
423 {
424 int val;
425 if (m_SimwideCounts.TryGetValue(owner, out val))
426 count = val;
427 }
428 }
429  
430 // m_log.DebugFormat(
431 // "[PRIM COUNT MODULE]: GetOthersCount for parcel {0} in {1} returning {2}",
432 // parcelID, m_Scene.RegionInfo.RegionName, count);
433  
434 return count;
435 }
436  
437 /// <summary>
438 /// Get the number of prims that a particular user owns on this parcel.
439 /// </summary>
440 /// <param name="parcelID"></param>
441 /// <param name="userID"></param>
442 /// <returns></returns>
443 public int GetUserCount(UUID parcelID, UUID userID)
444 {
445 int count = 0;
446  
447 lock (m_TaintLock)
448 {
449 if (m_Tainted)
450 Recount();
451  
452 ParcelCounts counts;
453 if (m_ParcelCounts.TryGetValue(parcelID, out counts))
454 {
455 int val;
456 if (counts.Users.TryGetValue(userID, out val))
457 count = val;
458 }
459 }
460  
461 // m_log.DebugFormat(
462 // "[PRIM COUNT MODULE]: GetUserCount for user {0} in parcel {1} in region {2} returning {3}",
463 // userID, parcelID, m_Scene.RegionInfo.RegionName, count);
464  
465 return count;
466 }
467  
468 // NOTE: This method MUST be called while holding the taint lock!
469 private void Recount()
470 {
471 // m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName);
472  
473 m_OwnerMap.Clear();
474 m_SimwideCounts.Clear();
475 m_ParcelCounts.Clear();
476  
477 List<ILandObject> land = m_Scene.LandChannel.AllParcels();
478  
479 foreach (ILandObject l in land)
480 {
481 LandData landData = l.LandData;
482  
483 m_OwnerMap[landData.GlobalID] = landData.OwnerID;
484 m_SimwideCounts[landData.OwnerID] = 0;
485 // m_log.DebugFormat(
486 // "[PRIM COUNT MODULE]: Initializing parcel count for {0} on {1}",
487 // landData.Name, m_Scene.RegionInfo.RegionName);
488 m_ParcelCounts[landData.GlobalID] = new ParcelCounts();
489 }
490  
491 m_Scene.ForEachSOG(AddObject);
492  
493 lock (m_PrimCounts)
494 {
495 List<UUID> primcountKeys = new List<UUID>(m_PrimCounts.Keys);
496 foreach (UUID k in primcountKeys)
497 {
498 if (!m_OwnerMap.ContainsKey(k))
499 m_PrimCounts.Remove(k);
500 }
501 }
502  
503 m_Tainted = false;
504 }
505 }
506  
507 public class PrimCounts : IPrimCounts
508 {
509 private PrimCountModule m_Parent;
510 private UUID m_ParcelID;
511 private UserPrimCounts m_UserPrimCounts;
512  
513 public PrimCounts (UUID parcelID, PrimCountModule parent)
514 {
515 m_ParcelID = parcelID;
516 m_Parent = parent;
517  
518 m_UserPrimCounts = new UserPrimCounts(this);
519 }
520  
521 public int Owner
522 {
523 get
524 {
525 return m_Parent.GetOwnerCount(m_ParcelID);
526 }
527 }
528  
529 public int Group
530 {
531 get
532 {
533 return m_Parent.GetGroupCount(m_ParcelID);
534 }
535 }
536  
537 public int Others
538 {
539 get
540 {
541 return m_Parent.GetOthersCount(m_ParcelID);
542 }
543 }
544  
545 public int Selected
546 {
547 get
548 {
549 return m_Parent.GetSelectedCount(m_ParcelID);
550 }
551 }
552  
553 public int Total
554 {
555 get
556 {
557 return m_Parent.GetTotalCount(m_ParcelID);
558 }
559 }
560  
561 public int Simulator
562 {
563 get
564 {
565 return m_Parent.GetSimulatorCount(m_ParcelID);
566 }
567 }
568  
569 public IUserPrimCounts Users
570 {
571 get
572 {
573 return m_UserPrimCounts;
574 }
575 }
576  
577 public int GetUserCount(UUID userID)
578 {
579 return m_Parent.GetUserCount(m_ParcelID, userID);
580 }
581 }
582  
583 public class UserPrimCounts : IUserPrimCounts
584 {
585 private PrimCounts m_Parent;
586  
587 public UserPrimCounts(PrimCounts parent)
588 {
589 m_Parent = parent;
590 }
591  
592 public int this[UUID userID]
593 {
594 get
595 {
596 return m_Parent.GetUserCount(userID);
597 }
598 }
599 }
600 }