CacheExpires.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. //
  2. // System.Web.Caching
  3. //
  4. // Author:
  5. // Patrik Torstensson ([email protected])
  6. //
  7. // (C) Copyright Patrik Torstensson, 2001
  8. //
  9. namespace System.Web.Caching
  10. {
  11. /// <summary>
  12. /// Class responsible for handling time based flushing of entries in the cache. The class creates
  13. /// and manages 60 buckets each holding every item that expires that minute. The bucket calculated
  14. /// for an entry is one minute more than the timeout just to make sure that the item end up in the
  15. /// bucket where it should be flushed.
  16. /// </summary>
  17. public class CacheExpires : System.IDisposable
  18. {
  19. static int _intFlush;
  20. static long _ticksPerBucket = 600000000;
  21. static long _ticksPerCycle = _ticksPerBucket * 60;
  22. private ExpiresBucket[] _arrBuckets;
  23. private System.Threading.Timer _objTimer;
  24. private Cache _objManager;
  25. /// <summary>
  26. /// Constructor
  27. /// </summary>
  28. /// <param name="objManager">The cache manager, used when flushing items in a bucket.</param>
  29. public CacheExpires(Cache objManager)
  30. {
  31. _objManager = objManager;
  32. Initialize();
  33. }
  34. /// <summary>
  35. /// Initializes the class.
  36. /// </summary>
  37. private void Initialize()
  38. {
  39. // Create one bucket per minute
  40. _arrBuckets = new ExpiresBucket[60];
  41. byte bytePos = 0;
  42. do
  43. {
  44. _arrBuckets[bytePos] = new ExpiresBucket(bytePos, _objManager);
  45. bytePos++;
  46. } while (bytePos < 60);
  47. // GC Bucket controller
  48. _intFlush = System.DateTime.Now.Minute - 1;
  49. _objTimer = new System.Threading.Timer(new System.Threading.TimerCallback(GarbageCleanup), null, 10000, 60000);
  50. }
  51. /// <summary>
  52. /// Adds a Cache entry to the correct flush bucket.
  53. /// </summary>
  54. /// <param name="objEntry">Cache entry to add.</param>
  55. public void Add(CacheEntry objEntry)
  56. {
  57. long ticksNow = System.DateTime.Now.Ticks;
  58. lock(this)
  59. {
  60. // If the entry doesn't have a expires time we assume that the entry is due to expire now.
  61. if (objEntry.Expires == 0)
  62. {
  63. objEntry.Expires = ticksNow;
  64. }
  65. _arrBuckets[GetHashBucket(objEntry.Expires)].Add(objEntry);
  66. }
  67. }
  68. public void Remove(CacheEntry objEntry)
  69. {
  70. long ticksNow = System.DateTime.Now.Ticks;
  71. lock(this)
  72. {
  73. // If the entry doesn't have a expires time we assume that the entry is due to expire now.
  74. if (objEntry.Expires == 0)
  75. {
  76. objEntry.Expires = ticksNow;
  77. }
  78. _arrBuckets[GetHashBucket(objEntry.Expires)].Remove(objEntry);
  79. }
  80. }
  81. public void Update(CacheEntry objEntry, long ticksExpires)
  82. {
  83. long ticksNow = System.DateTime.Now.Ticks;
  84. lock(this)
  85. {
  86. // If the entry doesn't have a expires time we assume that the entry is due to expire now.
  87. if (objEntry.Expires == 0)
  88. {
  89. objEntry.Expires = ticksNow;
  90. }
  91. _arrBuckets[GetHashBucket(objEntry.Expires)].Update(objEntry, ticksExpires);
  92. }
  93. }
  94. public void GarbageCleanup(object State)
  95. {
  96. ExpiresBucket objBucket;
  97. lock(this)
  98. {
  99. // Do cleanup of the bucket
  100. objBucket = _arrBuckets[(++_intFlush) % 60];
  101. }
  102. // Flush expired items in the current bucket (defined by _intFlush)
  103. objBucket.FlushExpiredItems();
  104. }
  105. private int GetHashBucket(long ticks)
  106. {
  107. // Get bucket to add expire item into, add one minute to the bucket just to make sure that we get it in the bucket gc
  108. return (int) (((((ticks + 60000) % _ticksPerCycle) / _ticksPerBucket) + 1) % 60);
  109. }
  110. /// <summary>
  111. /// Called by the cache for cleanup.
  112. /// </summary>
  113. public void Dispose()
  114. {
  115. lock(this)
  116. {
  117. // Cleanup the internal timer
  118. if (_objTimer != null)
  119. {
  120. _objTimer.Dispose();
  121. _objTimer = null;
  122. }
  123. }
  124. }
  125. }
  126. }