aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs965
1 files changed, 897 insertions, 68 deletions
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
index be8a9a2..f6fff58 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
@@ -26,6 +26,8 @@
26 */ 26 */
27using System; 27using System;
28using System.Reflection; 28using System.Reflection;
29using System.Threading;
30using System.Runtime.InteropServices;
29using System.Collections.Generic; 31using System.Collections.Generic;
30using OpenSim.Framework; 32using OpenSim.Framework;
31using OpenSim.Services.Interfaces; 33using OpenSim.Services.Interfaces;
@@ -37,82 +39,68 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
37{ 39{
38 public class RegionInfoCache 40 public class RegionInfoCache
39 { 41 {
40 private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes 42 private const float CACHE_EXPIRATION_SECONDS = 120; // 2 minutes opensim regions change a lot
41 43
42// private static readonly ILog m_log = 44// private static readonly ILog m_log =
43// LogManager.GetLogger( 45// LogManager.GetLogger(
44// MethodBase.GetCurrentMethod().DeclaringType); 46// MethodBase.GetCurrentMethod().DeclaringType);
45 47
46 internal struct ScopedRegionUUID 48 private static RegionsExpiringCache m_Cache;
49 private int numberInstances;
50
51 public RegionInfoCache()
47 { 52 {
48 public UUID m_scopeID; 53 if(m_Cache == null)
49 public UUID m_regionID; 54 m_Cache = new RegionsExpiringCache();
50 public ScopedRegionUUID(UUID scopeID, UUID regionID) 55 numberInstances++;
51 {
52 m_scopeID = scopeID;
53 m_regionID = regionID;
54 }
55 } 56 }
56 57
57 internal struct ScopedRegionName 58 public void Cache(GridRegion rinfo)
58 { 59 {
59 public UUID m_scopeID; 60 if (rinfo != null)
60 public string m_name; 61 this.Cache(rinfo.ScopeID, rinfo);
61 public ScopedRegionName(UUID scopeID, string name)
62 {
63 m_scopeID = scopeID;
64 m_name = name;
65 }
66 } 62 }
67 63
68 internal struct ScopedRegionPosition 64 public void Cache(UUID scopeID, GridRegion rinfo)
69 { 65 {
70 public UUID m_scopeID; 66 if (rinfo == null)
71 public ulong m_regionHandle; 67 return;
72 public ScopedRegionPosition(UUID scopeID, ulong handle)
73 {
74 m_scopeID = scopeID;
75 m_regionHandle = handle;
76 }
77 }
78 68
79 private ExpiringCache<ScopedRegionUUID, GridRegion> m_UUIDCache; 69 m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
80 private ExpiringCache<ScopedRegionName, ScopedRegionUUID> m_NameCache; 70 }
81 private ExpiringCache<ScopedRegionPosition, GridRegion> m_PositionCache;
82 71
83 public RegionInfoCache() 72 public void CacheLocal(GridRegion rinfo)
84 { 73 {
85 m_UUIDCache = new ExpiringCache<ScopedRegionUUID, GridRegion>(); 74 if (rinfo == null)
86 m_NameCache = new ExpiringCache<ScopedRegionName, ScopedRegionUUID>(); 75 return;
87 m_PositionCache = new ExpiringCache<ScopedRegionPosition, GridRegion>(); 76
77 m_Cache.AddOrUpdate(rinfo.ScopeID, rinfo, 1e7f);
88 } 78 }
89 79
90 public void Cache(GridRegion rinfo) 80 public void CacheNearNeighbour(UUID scopeID, GridRegion rinfo)
91 { 81 {
92 if (rinfo != null) 82 if (rinfo == null)
93 this.Cache(rinfo.ScopeID,rinfo.RegionID,rinfo); 83 return;
84
85 m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
94 } 86 }
95 87
96 public void Cache(UUID scopeID, UUID regionID, GridRegion rinfo) 88 public void Cache(UUID scopeID, GridRegion rinfo, float expireSeconds)
97 { 89 {
98 // for now, do not cache negative results; this is because
99 // we need to figure out how to handle regions coming online
100 // in a timely way
101 if (rinfo == null) 90 if (rinfo == null)
102 return; 91 return;
103
104 ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID);
105
106 // Cache even null accounts
107 m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS);
108 if (rinfo != null)
109 {
110 ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName);
111 m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS);
112 92
113 ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, rinfo.RegionHandle); 93 m_Cache.AddOrUpdate(scopeID, rinfo, expireSeconds);
114 m_PositionCache.AddOrUpdate(pos, rinfo, CACHE_EXPIRATION_SECONDS); 94 }
115 } 95
96 public void Remove(UUID scopeID, GridRegion rinfo)
97 {
98 m_Cache.Remove(scopeID, rinfo);
99 }
100
101 public void Remove(UUID scopeID, ulong regionHandle)
102 {
103 m_Cache.Remove(scopeID, regionHandle);
116 } 104 }
117 105
118 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache) 106 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
@@ -120,8 +108,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
120 inCache = false; 108 inCache = false;
121 109
122 GridRegion rinfo = null; 110 GridRegion rinfo = null;
123 ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID); 111 if (m_Cache.TryGetValue(scopeID, regionID, out rinfo))
124 if (m_UUIDCache.TryGetValue(id, out rinfo))
125 { 112 {
126 inCache = true; 113 inCache = true;
127 return rinfo; 114 return rinfo;
@@ -135,8 +122,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
135 inCache = false; 122 inCache = false;
136 123
137 GridRegion rinfo = null; 124 GridRegion rinfo = null;
138 ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, handle); 125 if (m_Cache.TryGetValue(scopeID, handle, out rinfo))
139 if (m_PositionCache.TryGetValue(pos, out rinfo))
140 { 126 {
141 inCache = true; 127 inCache = true;
142 return rinfo; 128 return rinfo;
@@ -145,25 +131,868 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
145 return null; 131 return null;
146 } 132 }
147 133
148
149 public GridRegion Get(UUID scopeID, string name, out bool inCache) 134 public GridRegion Get(UUID scopeID, string name, out bool inCache)
150 { 135 {
151 inCache = false; 136 inCache = false;
152 137
153 ScopedRegionName sname = new ScopedRegionName(scopeID,name); 138 GridRegion rinfo = null;
139 if (m_Cache.TryGetValue(scopeID, name, out rinfo))
140 {
141 inCache = true;
142 return rinfo;
143 }
144
145 return null;
146 }
147
148 public GridRegion Get(UUID scopeID, uint x, uint y, out bool inCache)
149 {
150 inCache = false;
151
152 GridRegion rinfo = null;
153 if (m_Cache.TryGetValue(scopeID, x, y, out rinfo))
154 {
155 inCache = true;
156 return rinfo;
157 }
158
159 return null;
160 }
161 }
162
163 // dont care about endianess
164 [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)]
165 public class fastRegionHandle
166 {
167 [FieldOffset(0)] public ulong handle;
168 [FieldOffset(0)] public uint y;
169 [FieldOffset(4)] public uint x;
170
171 public fastRegionHandle(ulong h)
172 {
173 handle = h;
174 }
175
176 public fastRegionHandle(uint px, uint py)
177 {
178 y = py & 0xffffff00;
179 x = px & 0xffffff00;
180 }
181 // actually do care
182 public ulong toHandle()
183 {
184 if(BitConverter.IsLittleEndian)
185 return handle;
186 return (ulong) x << 32 | (ulong)y ;
187 }
188
189 public static bool operator ==(fastRegionHandle value1, fastRegionHandle value2)
190 {
191 return value1.handle == value2.handle;
192 }
193 public static bool operator !=(fastRegionHandle value1, fastRegionHandle value2)
194 {
195 return value1.handle != value2.handle;
196 }
197 public override int GetHashCode()
198 {
199 return handle.GetHashCode();
200 }
201 public override bool Equals(Object obj)
202 {
203 if(obj == null)
204 return false;
205 fastRegionHandle p = obj as fastRegionHandle;
206 return p.handle == handle;
207 }
208 }
209
210/*
211 [StructLayout(LayoutKind.Explicit, Size = 8, Pack = 8)]
212 public class regionHandle
213 {
214 [FieldOffset(0)] private ulong handle;
215 [FieldOffset(0)] public uint a;
216 [FieldOffset(4)] public uint b;
217
218 public regionHandle(ulong h)
219 {
220 handle = h;
221 }
222
223 public regionHandle(uint px, uint py)
224 {
225 if(BitConverter.IsLittleEndian)
226 {
227 a = py & 0xffffff00;
228 b = px & 0xffffff00;
229 }
230 else
231 {
232 a = px & 0xffffff00;
233 b = py & 0xffffff00;
234 }
235 }
236
237 public uint x
238 {
239 get
240 {
241 if(BitConverter.IsLittleEndian)
242 return b;
243 return a;
244 }
245 set
246 {
247 if(BitConverter.IsLittleEndian)
248 b = value & 0xffffff00;
249 else
250 a = value & 0xffffff00;
251 }
252 }
253
254 public uint y
255 {
256 get
257 {
258 if(BitConverter.IsLittleEndian)
259 return a;
260 return b;
261 }
262 set
263 {
264 if(BitConverter.IsLittleEndian)
265 a = value;
266 else
267 b = value;
268 }
269 }
270
271 public static bool operator ==(regionHandle value1, regionHandle value2)
272 {
273 return value1.handle == value2.handle;
274 }
275 public static bool operator !=(regionHandle value1, regionHandle value2)
276 {
277 return value1.handle != value2.handle;
278 }
279 public override int GetHashCode()
280 {
281 return handle.GetHashCode();
282 }
283 public override bool Equals(Object obj)
284 {
285 if(obj == null)
286 return false;
287 regionHandle p = obj as regionHandle;
288 return p.handle == handle;
289 }
290 }
291*/
292
293 public class RegionInfoForScope
294 {
295 public const ulong HANDLEMASK = 0xffffff00ffffff00ul;
296 public const ulong HANDLECOORDMASK = 0xffffff00ul;
297
298 private Dictionary<ulong, GridRegion> storage;
299 private Dictionary<ulong, DateTime> expires;
300 private Dictionary<string, ulong> byname;
301 private Dictionary<UUID, ulong> byuuid;
302 // includes handles to the inside of large regions
303 private Dictionary<ulong, ulong> innerHandles = new Dictionary<ulong, ulong>();
304
305 public RegionInfoForScope()
306 {
307 storage = new Dictionary<ulong, GridRegion>();
308 expires = new Dictionary<ulong, DateTime>();
309 byname = new Dictionary<string, ulong>();
310 byuuid = new Dictionary<UUID, ulong>();
311 }
312
313 public RegionInfoForScope(GridRegion region, DateTime expire)
314 {
315 storage = new Dictionary<ulong, GridRegion>();
316 expires = new Dictionary<ulong, DateTime>();
317 byname = new Dictionary<string, ulong>();
318 byuuid = new Dictionary<UUID, ulong>();
319
320 ulong handle = region.RegionHandle & HANDLEMASK;
321 storage[handle] = region;
322 expires[handle] = expire;
323 byname[region.RegionName] = handle;
324 byuuid[region.RegionID] = handle;
325 addToInner(region);
326 }
327
328 public void Add(GridRegion region, DateTime expire)
329 {
330 ulong handle = region.RegionHandle & HANDLEMASK;
331
332 if(storage != null && storage.ContainsKey(handle))
333 return;
334
335 if(storage == null)
336 storage = new Dictionary<ulong, GridRegion>();
337 if(expires == null)
338 expires = new Dictionary<ulong, DateTime>();
339 if(byname == null)
340 byname = new Dictionary<string, ulong>();
341 if(byuuid == null)
342 byuuid = new Dictionary<UUID, ulong>();
343
344 storage[handle] = region;
345 expires[handle] = expire;
346 byname[region.RegionName] = handle;
347 byuuid[region.RegionID] = handle;
348
349 addToInner(region);
350 }
351
352 public void AddUpdate(GridRegion region, DateTime expire)
353 {
354 if(storage == null)
355 storage = new Dictionary<ulong, GridRegion>();
356 if(expires == null)
357 expires = new Dictionary<ulong, DateTime>();
358 if(byname == null)
359 byname = new Dictionary<string, ulong>();
360 if(byuuid == null)
361 byuuid = new Dictionary<UUID, ulong>();
362
363 ulong handle = region.RegionHandle & HANDLEMASK;
154 364
155 ScopedRegionUUID id; 365 if(expires.ContainsKey(handle))
156 if (m_NameCache.TryGetValue(sname, out id))
157 { 366 {
158 GridRegion rinfo = null; 367 if(expires[handle] < expire)
159 if (m_UUIDCache.TryGetValue(id, out rinfo)) 368 expires[handle] = expire;
369 if(storage.ContainsKey(handle))
160 { 370 {
161 inCache = true; 371 GridRegion oldr = storage[handle];
162 return rinfo; 372 if (oldr.RegionSizeX != region.RegionSizeX
373 || oldr.RegionSizeY != region.RegionSizeY)
374 {
375 removeFromInner(oldr);
376 addToInner(region);
377 }
163 } 378 }
164 } 379 }
165 380 else
381 {
382 expires[handle] = expire;
383 addToInner(region);
384 }
385 storage[handle] = region;
386 byname[region.RegionName] = handle;
387 byuuid[region.RegionID] = handle;
388 }
389
390 public void Remove(GridRegion region)
391 {
392 if(region == null)
393 return;
394
395 if(byname != null)
396 byname.Remove(region.RegionName);
397 if(byuuid != null)
398 byuuid.Remove(region.RegionID);
399
400 ulong handle = region.RegionHandle & HANDLEMASK;
401 if(storage != null)
402 {
403 if(storage.ContainsKey(handle))
404 {
405 storage[handle] = null;
406 storage.Remove(handle);
407 }
408 }
409 removeFromInner(region);
410 if(expires != null)
411 {
412 expires.Remove(handle);
413 if(expires.Count == 0)
414 Clear();
415 }
416 }
417
418 public void Remove(ulong handle)
419 {
420 handle &= HANDLEMASK;
421
422 if(storage != null)
423 {
424 if(storage.ContainsKey(handle))
425 {
426 GridRegion r = storage[handle];
427 if(byname != null)
428 byname.Remove(r.RegionName);
429 if(byuuid != null)
430 byuuid.Remove(r.RegionID);
431 removeFromInner(r);
432 storage[handle] = null;
433 }
434 storage.Remove(handle);
435 }
436 if(expires != null)
437 {
438 expires.Remove(handle);
439 if(expires.Count == 0)
440 Clear();
441 }
442 }
443
444 public void Clear()
445 {
446 if(expires != null)
447 expires.Clear();
448 if(storage != null)
449 storage.Clear();
450 if(byname != null)
451 byname.Clear();
452 if(byuuid != null)
453 byuuid.Clear();
454 byname = null;
455 byuuid = null;
456 storage = null;
457 expires = null;
458 innerHandles.Clear();
459 }
460
461 public bool Contains(GridRegion region)
462 {
463 if(storage == null)
464 return false;
465 if(region == null)
466 return false;
467
468 ulong handle = region.RegionHandle & HANDLEMASK;
469 return storage.ContainsKey(handle);
470 }
471
472 public bool Contains(ulong handle)
473 {
474 if(storage == null)
475 return false;
476
477 handle &= HANDLEMASK;
478 return storage.ContainsKey(handle);
479 }
480
481 public GridRegion get(ulong handle)
482 {
483 if(storage == null)
484 return null;
485
486 handle &= HANDLEMASK;
487 if(storage.ContainsKey(handle))
488 return storage[handle];
489
490 if(!innerHandles.ContainsKey(handle))
491 return null;
492
493 ulong rhandle = innerHandles[handle];
494 if(storage.ContainsKey(rhandle))
495 return storage[rhandle];
496
166 return null; 497 return null;
167 } 498 }
499
500 public GridRegion get(string name)
501 {
502 if(byname == null || !byname.ContainsKey(name))
503 return null;
504
505 ulong handle = byname[name];
506 if(storage.ContainsKey(handle))
507 return storage[handle];
508 return null;
509 }
510
511 public GridRegion get(UUID id)
512 {
513 if(byuuid == null || !byuuid.ContainsKey(id))
514 return null;
515
516 ulong handle = byuuid[id];
517 if(storage.ContainsKey(handle))
518 return storage[handle];
519 return null;
520 }
521
522 public GridRegion get(uint x, uint y)
523 {
524 if(storage == null)
525 return null;
526
527 // look for a handle first this should find normal size regions
528 ulong handle = (ulong)x & HANDLECOORDMASK;
529 handle <<= 32;
530 handle |= ((ulong)y & HANDLECOORDMASK);
531
532 if(storage.ContainsKey(handle))
533 return storage[handle];
534
535 if(!innerHandles.ContainsKey(handle))
536 return null;
537
538 ulong rhandle = innerHandles[handle];
539 if(!storage.ContainsKey(rhandle))
540 return null;
541
542 GridRegion r = storage[rhandle];
543 if(r == null)
544 return null;
545
546 // extra check, possible redundant
547
548 int test = r.RegionLocX;
549 if(x < test)
550 return null;
551 test += r.RegionSizeX;
552 if(x >= test)
553 return null;
554 test = r.RegionLocY;
555 if (y < test)
556 return null;
557 test += r.RegionSizeY;
558 if (y < test)
559 return r;
560
561/*
562 // next do the harder work
563 foreach(KeyValuePair<ulong, GridRegion> kvp in storage)
564 {
565 GridRegion r = kvp.Value;
566 if(r == null) // ??
567 continue;
568
569 int test = r.RegionLocX;
570 if(x < test)
571 continue;
572 test += r.RegionSizeX;
573 if(x >= test)
574 continue;
575 test = r.RegionLocY;
576 if (y < test)
577 continue;
578 test += r.RegionSizeY;
579 if (y < test)
580 return r;
581 }
582*/
583 return null;
584 }
585
586 public int expire(DateTime now )
587 {
588 if(expires == null || expires.Count == 0)
589 return 0;
590
591 int expiresCount = expires.Count;
592 List<ulong> toexpire = new List<ulong>();
593
594 foreach(KeyValuePair<ulong, DateTime> kvp in expires)
595 {
596 if(kvp.Value < now)
597 toexpire.Add(kvp.Key);
598 }
599
600 int toexpireCount = toexpire.Count;
601 if(toexpireCount == 0)
602 return expiresCount;
603
604 if(toexpireCount == expiresCount)
605 {
606 Clear();
607 return 0;
608 }
609
610 if(storage != null)
611 {
612 ulong h;
613 for(int i = 0; i < toexpireCount; i++)
614 {
615 h = toexpire[i];
616 if(storage.ContainsKey(h))
617 {
618 GridRegion r = storage[h];
619 if(byname != null)
620 byname.Remove(r.RegionName);
621 if(byuuid != null)
622 byuuid.Remove(r.RegionID);
623 removeFromInner(r);
624
625 storage[h] = null;
626 storage.Remove(h);
627 }
628 if(expires != null)
629 expires.Remove(h);
630 }
631 }
632 else
633 {
634 Clear();
635 return 0;
636 }
637
638 expiresCount = expires.Count;
639 if(expiresCount == 0)
640 {
641 byname = null;
642 byuuid = null;
643 storage = null;
644 expires = null;
645 return 0;
646 }
647
648 return expiresCount;
649 }
650
651 public int Count()
652 {
653 if(byname == null)
654 return 0;
655 else
656 return byname.Count;
657 }
658
659 private void addToInner(GridRegion region)
660 {
661 int rsx = region.RegionSizeX;
662 int rsy = region.RegionSizeY;
663
664 if(rsx < 512 && rsy < 512)
665 return;
666
667 rsx >>= 8;
668 rsy >>= 8;
669
670 ulong handle = region.RegionHandle & HANDLEMASK;
671 fastRegionHandle fh = new fastRegionHandle(handle);
672 uint startY = fh.y;
673 for(int i = 0; i < rsx; i++)
674 {
675 for(int j = 0; j < rsy ; j++)
676 {
677 innerHandles[fh.toHandle()] = handle;
678 fh.y += 256;
679 }
680
681 fh.y = startY;
682 fh.x += 256;
683 }
684 }
685
686 private void removeFromInner(GridRegion region)
687 {
688 int rsx = region.RegionSizeX;
689 int rsy = region.RegionSizeY;
690
691 if(rsx < 512 && rsy < 512)
692 return;
693
694 rsx >>= 8;
695 rsy >>= 8;
696 ulong handle = region.RegionHandle & HANDLEMASK;
697 fastRegionHandle fh = new fastRegionHandle(handle);
698 uint startY = fh.y;
699 for(int i = 0; i < rsx; i++)
700 {
701 for(int j = 0; j < rsy ; j++)
702 {
703 innerHandles.Remove(fh.toHandle());
704 fh.y += 256;
705 }
706
707 fh.y = startY;
708 fh.x += 256;
709 }
710 }
711 }
712
713 public class RegionsExpiringCache
714 {
715 const double CACHE_PURGE_TIME = 60000; // milliseconds
716 const int MAX_LOCK_WAIT = 10000; // milliseconds
717
718 /// <summary>For thread safety</summary>
719 object syncRoot = new object();
720 /// <summary>For thread safety</summary>
721 object isPurging = new object();
722
723 Dictionary<UUID, RegionInfoForScope> InfobyScope = new Dictionary<UUID, RegionInfoForScope>();
724 private System.Timers.Timer timer = new System.Timers.Timer(CACHE_PURGE_TIME);
725
726 public RegionsExpiringCache()
727 {
728 timer.Elapsed += PurgeCache;
729 timer.Start();
730 }
731
732 public bool AddOrUpdate(UUID scope, GridRegion region, float expirationSeconds)
733 {
734 if(region == null)
735 return false;
736
737 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
738 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
739
740 try
741 {
742 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
743
744 RegionInfoForScope ris = null;
745 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
746 {
747 ris = new RegionInfoForScope(region, expire);
748 InfobyScope[scope] = ris;
749 }
750 else
751 ris.AddUpdate(region, expire);
752
753 return true;
754 }
755 finally { Monitor.Exit(syncRoot); }
756 }
757
758 public void Clear()
759 {
760 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
761 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
762 try
763 {
764 foreach(RegionInfoForScope ris in InfobyScope.Values)
765 ris.Clear();
766 InfobyScope.Clear();
767 }
768 finally { Monitor.Exit(syncRoot); }
769 }
770
771 public bool Contains(UUID scope, GridRegion region)
772 {
773 if(region == null)
774 return false;
775
776 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
777 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
778
779 try
780 {
781 RegionInfoForScope ris = null;
782 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
783 return false;
784
785 return ris.Contains(region);
786 }
787 finally { Monitor.Exit(syncRoot); }
788 }
789
790 public bool Contains(UUID scope, ulong handle)
791 {
792 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
793 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
794
795 try
796 {
797 RegionInfoForScope ris = null;
798 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
799 return false;
800
801 return ris.Contains(handle);
802 }
803 finally { Monitor.Exit(syncRoot); }
804 }
805
806 public int Count()
807 {
808 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
809 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
810
811 try
812 {
813 int count = 0;
814 foreach(RegionInfoForScope ris in InfobyScope.Values)
815 count += ris.Count();
816 return count;
817 }
818 finally { Monitor.Exit(syncRoot); }
819 }
820
821 public bool Remove(UUID scope, ulong handle)
822 {
823 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
824 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
825 try
826 {
827 RegionInfoForScope ris = null;
828 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
829 return false;
830
831 ris.Remove(handle);
832 if(ris.Count() == 0)
833 InfobyScope.Remove(scope);
834 return true;
835 }
836 finally { Monitor.Exit(syncRoot); }
837 }
838
839 public bool Remove(UUID scope, GridRegion region)
840 {
841 if(region == null)
842 return false;
843
844 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
845 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
846 try
847 {
848 RegionInfoForScope ris = null;
849 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
850 return false;
851
852 ris.Remove(region);
853 if(ris.Count() == 0)
854 InfobyScope.Remove(scope);
855 return true;
856 }
857 finally { Monitor.Exit(syncRoot); }
858 }
859
860 public bool TryGetValue(UUID scope, ulong handle, out GridRegion value)
861 {
862 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
863 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
864
865 value = null;
866 try
867 {
868 RegionInfoForScope ris = null;
869 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
870 return false;
871 value = ris.get(handle);
872 }
873 finally { Monitor.Exit(syncRoot); }
874
875 return value != null;
876 }
877
878 public bool TryGetValue(UUID scope, string name, out GridRegion value)
879 {
880 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
881 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
882
883 value = null;
884 try
885 {
886 RegionInfoForScope ris = null;
887 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
888 return false;
889 value = ris.get(name);
890 }
891 finally { Monitor.Exit(syncRoot); }
892
893 return value != null;
894 }
895
896 public bool TryGetValue(UUID scope, UUID id, out GridRegion value)
897 {
898 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
899 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
900
901 value = null;
902 try
903 {
904 RegionInfoForScope ris = null;
905 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
906 return false;
907 value = ris.get(id);
908 }
909 finally { Monitor.Exit(syncRoot); }
910
911 return value != null;
912 }
913
914 // gets a region that contains world position (x,y)
915 // hopefull will not take ages
916 public bool TryGetValue(UUID scope, uint x, uint y, out GridRegion value)
917 {
918 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
919 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
920
921 value = null;
922 try
923 {
924 RegionInfoForScope ris = null;
925 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
926 return false;
927
928 value = ris.get(x, y);
929 }
930 finally { Monitor.Exit(syncRoot); }
931
932 return value != null;
933 }
934
935 public bool Update(UUID scope, GridRegion region, double expirationSeconds)
936 {
937 if(region == null)
938 return false;
939
940 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
941 throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
942
943 try
944 {
945 RegionInfoForScope ris = null;
946 if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
947 return false;
948
949 DateTime expire = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
950 ris.AddUpdate(region,expire);
951 return true;
952 }
953 finally { Monitor.Exit(syncRoot); }
954 }
955
956 /// <summary>
957 /// Purges expired objects from the cache. Called automatically by the purge timer.
958 /// </summary>
959 private void PurgeCache(object sender, System.Timers.ElapsedEventArgs e)
960 {
961 // Only let one thread purge at once - a buildup could cause a crash
962 // This could cause the purge to be delayed while there are lots of read/write ops
963 // happening on the cache
964 if (!Monitor.TryEnter(isPurging))
965 return;
966
967 DateTime now = DateTime.UtcNow;
968
969 try
970 {
971 // If we fail to acquire a lock on the synchronization root after MAX_LOCK_WAIT, skip this purge cycle
972 if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
973 return;
974 try
975 {
976 List<UUID> expiredscopes = new List<UUID>();
977
978 foreach (KeyValuePair<UUID, RegionInfoForScope> kvp in InfobyScope)
979 {
980 if (kvp.Value.expire(now) == 0)
981 expiredscopes.Add(kvp.Key);
982 }
983
984 if (expiredscopes.Count > 0)
985 {
986 foreach (UUID sid in expiredscopes)
987 {
988 InfobyScope[sid] = null;
989 InfobyScope.Remove(sid);
990 }
991 }
992 }
993 finally { Monitor.Exit(syncRoot); }
994 }
995 finally { Monitor.Exit(isPurging); }
996 }
168 } 997 }
169} 998}