diff options
author | Justin Clark-Casey (justincc) | 2012-08-20 20:55:58 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-08-24 21:52:30 +0100 |
commit | 132d701b3ea287c3ec0a9a4d9f852bb3b3a075f2 (patch) | |
tree | e869856296c5b6d7c3f58d606d39e2f0760a82bb | |
parent | Add --force flag to "kick user" console command to allow bypassing of recent ... (diff) | |
download | opensim-SC_OLD-132d701b3ea287c3ec0a9a4d9f852bb3b3a075f2.zip opensim-SC_OLD-132d701b3ea287c3ec0a9a4d9f852bb3b3a075f2.tar.gz opensim-SC_OLD-132d701b3ea287c3ec0a9a4d9f852bb3b3a075f2.tar.bz2 opensim-SC_OLD-132d701b3ea287c3ec0a9a4d9f852bb3b3a075f2.tar.xz |
Tighten up OpenSim.Framework.Cache locking to avoid race conditions.
This is to resolve a reported issue in http://opensimulator.org/mantis/view.php?id=6232
Here, the land management module is using OpenSim.Framework.Cache (the only code to currently do so apart from the non-default CoreAssetCache).
-rw-r--r-- | OpenSim/Framework/Cache.cs | 83 |
1 files changed, 53 insertions, 30 deletions
diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 79e20fc..31cab4a 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs | |||
@@ -199,7 +199,14 @@ namespace OpenSim.Framework | |||
199 | // | 199 | // |
200 | public class Cache | 200 | public class Cache |
201 | { | 201 | { |
202 | /// <summary> | ||
203 | /// Must only be accessed under lock. | ||
204 | /// </summary> | ||
202 | private List<CacheItemBase> m_Index = new List<CacheItemBase>(); | 205 | private List<CacheItemBase> m_Index = new List<CacheItemBase>(); |
206 | |||
207 | /// <summary> | ||
208 | /// Must only be accessed under m_Index lock. | ||
209 | /// </summary> | ||
203 | private Dictionary<string, CacheItemBase> m_Lookup = | 210 | private Dictionary<string, CacheItemBase> m_Lookup = |
204 | new Dictionary<string, CacheItemBase>(); | 211 | new Dictionary<string, CacheItemBase>(); |
205 | 212 | ||
@@ -320,19 +327,19 @@ namespace OpenSim.Framework | |||
320 | { | 327 | { |
321 | if (m_Lookup.ContainsKey(index)) | 328 | if (m_Lookup.ContainsKey(index)) |
322 | item = m_Lookup[index]; | 329 | item = m_Lookup[index]; |
323 | } | ||
324 | 330 | ||
325 | if (item == null) | 331 | if (item == null) |
326 | { | 332 | { |
333 | Expire(true); | ||
334 | return null; | ||
335 | } | ||
336 | |||
337 | item.hits++; | ||
338 | item.lastUsed = DateTime.Now; | ||
339 | |||
327 | Expire(true); | 340 | Expire(true); |
328 | return null; | ||
329 | } | 341 | } |
330 | 342 | ||
331 | item.hits++; | ||
332 | item.lastUsed = DateTime.Now; | ||
333 | |||
334 | Expire(true); | ||
335 | |||
336 | return item; | 343 | return item; |
337 | } | 344 | } |
338 | 345 | ||
@@ -385,7 +392,10 @@ namespace OpenSim.Framework | |||
385 | // | 392 | // |
386 | public Object Find(Predicate<CacheItemBase> d) | 393 | public Object Find(Predicate<CacheItemBase> d) |
387 | { | 394 | { |
388 | CacheItemBase item = m_Index.Find(d); | 395 | CacheItemBase item; |
396 | |||
397 | lock (m_Index) | ||
398 | item = m_Index.Find(d); | ||
389 | 399 | ||
390 | if (item == null) | 400 | if (item == null) |
391 | return null; | 401 | return null; |
@@ -419,12 +429,12 @@ namespace OpenSim.Framework | |||
419 | public virtual void Store(string index, Object data, Type container, | 429 | public virtual void Store(string index, Object data, Type container, |
420 | Object[] parameters) | 430 | Object[] parameters) |
421 | { | 431 | { |
422 | Expire(false); | ||
423 | |||
424 | CacheItemBase item; | 432 | CacheItemBase item; |
425 | 433 | ||
426 | lock (m_Index) | 434 | lock (m_Index) |
427 | { | 435 | { |
436 | Expire(false); | ||
437 | |||
428 | if (m_Index.Contains(new CacheItemBase(index))) | 438 | if (m_Index.Contains(new CacheItemBase(index))) |
429 | { | 439 | { |
430 | if ((m_Flags & CacheFlags.AllowUpdate) != 0) | 440 | if ((m_Flags & CacheFlags.AllowUpdate) != 0) |
@@ -450,9 +460,17 @@ namespace OpenSim.Framework | |||
450 | m_Index.Add(item); | 460 | m_Index.Add(item); |
451 | m_Lookup[index] = item; | 461 | m_Lookup[index] = item; |
452 | } | 462 | } |
463 | |||
453 | item.Store(data); | 464 | item.Store(data); |
454 | } | 465 | } |
455 | 466 | ||
467 | /// <summary> | ||
468 | /// Expire items as appropriate. | ||
469 | /// </summary> | ||
470 | /// <remarks> | ||
471 | /// Callers must lock m_Index. | ||
472 | /// </remarks> | ||
473 | /// <param name='getting'></param> | ||
456 | protected virtual void Expire(bool getting) | 474 | protected virtual void Expire(bool getting) |
457 | { | 475 | { |
458 | if (getting && (m_Strategy == CacheStrategy.Aggressive)) | 476 | if (getting && (m_Strategy == CacheStrategy.Aggressive)) |
@@ -475,12 +493,10 @@ namespace OpenSim.Framework | |||
475 | 493 | ||
476 | switch (m_Strategy) | 494 | switch (m_Strategy) |
477 | { | 495 | { |
478 | case CacheStrategy.Aggressive: | 496 | case CacheStrategy.Aggressive: |
479 | if (Count < Size) | 497 | if (Count < Size) |
480 | return; | 498 | return; |
481 | 499 | ||
482 | lock (m_Index) | ||
483 | { | ||
484 | m_Index.Sort(new SortLRU()); | 500 | m_Index.Sort(new SortLRU()); |
485 | m_Index.Reverse(); | 501 | m_Index.Reverse(); |
486 | 502 | ||
@@ -490,7 +506,7 @@ namespace OpenSim.Framework | |||
490 | 506 | ||
491 | ExpireDelegate doExpire = OnExpire; | 507 | ExpireDelegate doExpire = OnExpire; |
492 | 508 | ||
493 | if (doExpire != null) | 509 | if (doExpire != null) |
494 | { | 510 | { |
495 | List<CacheItemBase> candidates = | 511 | List<CacheItemBase> candidates = |
496 | m_Index.GetRange(target, Count - target); | 512 | m_Index.GetRange(target, Count - target); |
@@ -513,27 +529,34 @@ namespace OpenSim.Framework | |||
513 | foreach (CacheItemBase item in m_Index) | 529 | foreach (CacheItemBase item in m_Index) |
514 | m_Lookup[item.uuid] = item; | 530 | m_Lookup[item.uuid] = item; |
515 | } | 531 | } |
516 | } | 532 | |
517 | break; | 533 | break; |
518 | default: | 534 | |
519 | break; | 535 | default: |
536 | break; | ||
520 | } | 537 | } |
521 | } | 538 | } |
522 | 539 | ||
523 | public void Invalidate(string uuid) | 540 | public void Invalidate(string uuid) |
524 | { | 541 | { |
525 | if (!m_Lookup.ContainsKey(uuid)) | 542 | lock (m_Index) |
526 | return; | 543 | { |
544 | if (!m_Lookup.ContainsKey(uuid)) | ||
545 | return; | ||
527 | 546 | ||
528 | CacheItemBase item = m_Lookup[uuid]; | 547 | CacheItemBase item = m_Lookup[uuid]; |
529 | m_Lookup.Remove(uuid); | 548 | m_Lookup.Remove(uuid); |
530 | m_Index.Remove(item); | 549 | m_Index.Remove(item); |
550 | } | ||
531 | } | 551 | } |
532 | 552 | ||
533 | public void Clear() | 553 | public void Clear() |
534 | { | 554 | { |
535 | m_Index.Clear(); | 555 | lock (m_Index) |
536 | m_Lookup.Clear(); | 556 | { |
557 | m_Index.Clear(); | ||
558 | m_Lookup.Clear(); | ||
559 | } | ||
537 | } | 560 | } |
538 | } | 561 | } |
539 | } | 562 | } \ No newline at end of file |