diff options
-rw-r--r-- | OpenSim/Framework/Cache.cs | 101 |
1 files changed, 61 insertions, 40 deletions
diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 31cab4a..80f5ff4 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs | |||
@@ -89,14 +89,14 @@ namespace OpenSim.Framework | |||
89 | public CacheItemBase(string index) | 89 | public CacheItemBase(string index) |
90 | { | 90 | { |
91 | uuid = index; | 91 | uuid = index; |
92 | entered = DateTime.Now; | 92 | entered = DateTime.UtcNow; |
93 | lastUsed = entered; | 93 | lastUsed = entered; |
94 | } | 94 | } |
95 | 95 | ||
96 | public CacheItemBase(string index, DateTime ttl) | 96 | public CacheItemBase(string index, DateTime ttl) |
97 | { | 97 | { |
98 | uuid = index; | 98 | uuid = index; |
99 | entered = DateTime.Now; | 99 | entered = DateTime.UtcNow; |
100 | lastUsed = entered; | 100 | lastUsed = entered; |
101 | expires = ttl; | 101 | expires = ttl; |
102 | } | 102 | } |
@@ -215,6 +215,8 @@ namespace OpenSim.Framework | |||
215 | private CacheFlags m_Flags = 0; | 215 | private CacheFlags m_Flags = 0; |
216 | private int m_Size = 1024; | 216 | private int m_Size = 1024; |
217 | private TimeSpan m_DefaultTTL = new TimeSpan(0); | 217 | private TimeSpan m_DefaultTTL = new TimeSpan(0); |
218 | private DateTime m_nextExpire; | ||
219 | private TimeSpan m_expiresTime = new TimeSpan(0,0,30); | ||
218 | public ExpireDelegate OnExpire; | 220 | public ExpireDelegate OnExpire; |
219 | 221 | ||
220 | // Comparison interfaces | 222 | // Comparison interfaces |
@@ -233,6 +235,21 @@ namespace OpenSim.Framework | |||
233 | return(a.lastUsed.CompareTo(b.lastUsed)); | 235 | return(a.lastUsed.CompareTo(b.lastUsed)); |
234 | } | 236 | } |
235 | } | 237 | } |
238 | // same as above, reverse order | ||
239 | private class SortLRUrev : IComparer<CacheItemBase> | ||
240 | { | ||
241 | public int Compare(CacheItemBase a, CacheItemBase b) | ||
242 | { | ||
243 | if (a == null && b == null) | ||
244 | return 0; | ||
245 | if (a == null) | ||
246 | return -1; | ||
247 | if (b == null) | ||
248 | return 1; | ||
249 | |||
250 | return(b.lastUsed.CompareTo(a.lastUsed)); | ||
251 | } | ||
252 | } | ||
236 | 253 | ||
237 | // Convenience constructors | 254 | // Convenience constructors |
238 | // | 255 | // |
@@ -241,6 +258,8 @@ namespace OpenSim.Framework | |||
241 | m_Strategy = CacheStrategy.Balanced; | 258 | m_Strategy = CacheStrategy.Balanced; |
242 | m_Medium = CacheMedium.Memory; | 259 | m_Medium = CacheMedium.Memory; |
243 | m_Flags = 0; | 260 | m_Flags = 0; |
261 | m_nextExpire = DateTime.UtcNow + m_expiresTime; | ||
262 | m_Strategy = CacheStrategy.Aggressive; | ||
244 | } | 263 | } |
245 | 264 | ||
246 | public Cache(CacheMedium medium) : | 265 | public Cache(CacheMedium medium) : |
@@ -295,19 +314,23 @@ namespace OpenSim.Framework | |||
295 | { | 314 | { |
296 | lock (m_Index) | 315 | lock (m_Index) |
297 | { | 316 | { |
298 | if (Count <= Size) | 317 | int target = newSize; |
299 | return; | 318 | if(m_Strategy == CacheStrategy.Aggressive) |
319 | target = (int)(newSize * 0.9); | ||
300 | 320 | ||
301 | m_Index.Sort(new SortLRU()); | 321 | if(Count > target) |
302 | m_Index.Reverse(); | 322 | { |
323 | m_Index.Sort(new SortLRUrev()); | ||
303 | 324 | ||
304 | m_Index.RemoveRange(newSize, Count - newSize); | 325 | m_Index.RemoveRange(newSize, Count - target); |
305 | m_Size = newSize; | ||
306 | 326 | ||
307 | m_Lookup.Clear(); | 327 | m_Lookup.Clear(); |
328 | |||
329 | foreach (CacheItemBase item in m_Index) | ||
330 | m_Lookup[item.uuid] = item; | ||
331 | } | ||
332 | m_Size = newSize; | ||
308 | 333 | ||
309 | foreach (CacheItemBase item in m_Index) | ||
310 | m_Lookup[item.uuid] = item; | ||
311 | } | 334 | } |
312 | } | 335 | } |
313 | 336 | ||
@@ -335,7 +358,7 @@ namespace OpenSim.Framework | |||
335 | } | 358 | } |
336 | 359 | ||
337 | item.hits++; | 360 | item.hits++; |
338 | item.lastUsed = DateTime.Now; | 361 | item.lastUsed = DateTime.UtcNow; |
339 | 362 | ||
340 | Expire(true); | 363 | Expire(true); |
341 | } | 364 | } |
@@ -361,30 +384,26 @@ namespace OpenSim.Framework | |||
361 | // | 384 | // |
362 | public virtual Object Get(string index, FetchDelegate fetch) | 385 | public virtual Object Get(string index, FetchDelegate fetch) |
363 | { | 386 | { |
364 | Object item = Get(index); | 387 | CacheItemBase item = GetItem(index); |
365 | if (item != null) | 388 | if (item != null) |
366 | return item; | 389 | return item.Retrieve(); |
367 | 390 | ||
368 | Object data = fetch(index); | 391 | Object data = fetch(index); |
369 | if (data == null) | 392 | |
370 | { | 393 | if (data == null && (m_Flags & CacheFlags.CacheMissing) == 0) |
371 | if ((m_Flags & CacheFlags.CacheMissing) != 0) | ||
372 | { | ||
373 | lock (m_Index) | ||
374 | { | ||
375 | CacheItemBase missing = new CacheItemBase(index); | ||
376 | if (!m_Index.Contains(missing)) | ||
377 | { | ||
378 | m_Index.Add(missing); | ||
379 | m_Lookup[index] = missing; | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | return null; | 394 | return null; |
395 | |||
396 | lock (m_Index) | ||
397 | { | ||
398 | CacheItemBase missing = new CacheItemBase(index); | ||
399 | if (!m_Index.Contains(missing)) | ||
400 | { | ||
401 | m_Index.Add(missing); | ||
402 | m_Lookup[index] = missing; | ||
403 | } | ||
384 | } | 404 | } |
385 | 405 | ||
386 | Store(index, data); | 406 | Store(index, data); |
387 | |||
388 | return data; | 407 | return data; |
389 | } | 408 | } |
390 | 409 | ||
@@ -442,9 +461,9 @@ namespace OpenSim.Framework | |||
442 | item = GetItem(index); | 461 | item = GetItem(index); |
443 | 462 | ||
444 | item.hits++; | 463 | item.hits++; |
445 | item.lastUsed = DateTime.Now; | 464 | item.lastUsed = DateTime.UtcNow; |
446 | if (m_DefaultTTL.Ticks != 0) | 465 | if (m_DefaultTTL.Ticks != 0) |
447 | item.expires = DateTime.Now + m_DefaultTTL; | 466 | item.expires = DateTime.UtcNow + m_DefaultTTL; |
448 | 467 | ||
449 | item.Store(data); | 468 | item.Store(data); |
450 | } | 469 | } |
@@ -455,7 +474,7 @@ namespace OpenSim.Framework | |||
455 | parameters); | 474 | parameters); |
456 | 475 | ||
457 | if (m_DefaultTTL.Ticks != 0) | 476 | if (m_DefaultTTL.Ticks != 0) |
458 | item.expires = DateTime.Now + m_DefaultTTL; | 477 | item.expires = DateTime.UtcNow + m_DefaultTTL; |
459 | 478 | ||
460 | m_Index.Add(item); | 479 | m_Index.Add(item); |
461 | m_Lookup[index] = item; | 480 | m_Lookup[index] = item; |
@@ -476,10 +495,14 @@ namespace OpenSim.Framework | |||
476 | if (getting && (m_Strategy == CacheStrategy.Aggressive)) | 495 | if (getting && (m_Strategy == CacheStrategy.Aggressive)) |
477 | return; | 496 | return; |
478 | 497 | ||
498 | DateTime now = DateTime.UtcNow; | ||
499 | if(now < m_nextExpire) | ||
500 | return; | ||
501 | |||
502 | m_nextExpire = now + m_expiresTime; | ||
503 | |||
479 | if (m_DefaultTTL.Ticks != 0) | 504 | if (m_DefaultTTL.Ticks != 0) |
480 | { | 505 | { |
481 | DateTime now= DateTime.Now; | ||
482 | |||
483 | foreach (CacheItemBase item in new List<CacheItemBase>(m_Index)) | 506 | foreach (CacheItemBase item in new List<CacheItemBase>(m_Index)) |
484 | { | 507 | { |
485 | if (item.expires.Ticks == 0 || | 508 | if (item.expires.Ticks == 0 || |
@@ -494,15 +517,13 @@ namespace OpenSim.Framework | |||
494 | switch (m_Strategy) | 517 | switch (m_Strategy) |
495 | { | 518 | { |
496 | case CacheStrategy.Aggressive: | 519 | case CacheStrategy.Aggressive: |
497 | if (Count < Size) | 520 | int target = (int)((float)Size * 0.9); |
521 | if (Count < target) // Cover ridiculous cache sizes | ||
498 | return; | 522 | return; |
499 | 523 | ||
500 | m_Index.Sort(new SortLRU()); | 524 | target = (int)((float)Size * 0.8); |
501 | m_Index.Reverse(); | ||
502 | 525 | ||
503 | int target = (int)((float)Size * 0.9); | 526 | m_Index.Sort(new SortLRUrev()); |
504 | if (target == Count) // Cover ridiculous cache sizes | ||
505 | return; | ||
506 | 527 | ||
507 | ExpireDelegate doExpire = OnExpire; | 528 | ExpireDelegate doExpire = OnExpire; |
508 | 529 | ||