CacheExpires.cs 3.8 KB

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