2 // System.Web.Caching
\r
5 // Patrik Torstensson
\r
6 // Daniel Cazzulino (dcazzulino@users.sf.net)
\r
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
\r
32 using System.Threading;
\r
34 namespace System.Web.Caching {
\r
36 /// Class responsible for handling time based flushing of entries in the cache. The class creates
\r
37 /// and manages 60 buckets each holding every item that expires that minute. The bucket calculated
\r
38 /// for an entry is one minute more than the timeout just to make sure that the item end up in the
\r
39 /// bucket where it should be flushed.
\r
41 internal class CacheExpires : IDisposable {
\r
42 static int _intFlush;
\r
44 /// 1 bucket == 1 minute == 10M ticks (1 second) * 60
\r
46 static long _ticksPerBucket = 600000000;
\r
48 /// 1 cycle == 1 hour
\r
50 static long _ticksPerCycle = _ticksPerBucket * 60;
\r
52 private ExpiresBucket[] _arrBuckets;
\r
53 private Timer _objTimer;
\r
54 private Cache _objManager;
\r
56 private object _lockObj = new object ();
\r
58 internal CacheExpires (Cache objManager) {
\r
59 _objManager = objManager;
\r
63 private void Initialize () {
\r
64 // Create one bucket per minute
\r
65 _arrBuckets = new ExpiresBucket [60];
\r
69 _arrBuckets [bytePos] = new ExpiresBucket (bytePos, _objManager);
\r
71 } while (bytePos < 60);
\r
73 // GC Bucket controller
\r
74 _intFlush = System.DateTime.UtcNow.Minute - 1;
\r
75 _objTimer = new System.Threading.Timer (new System.Threading.TimerCallback (GarbageCleanup), null, 10000, 60000);
\r
79 internal void Close()
\r
82 _objTimer.Dispose();
\r
87 /// Adds a Cache entry to the correct flush bucket.
\r
89 /// <param name="objEntry">Cache entry to add.</param>
\r
90 internal void Add (CacheEntry objEntry) {
\r
91 long now = DateTime.UtcNow.Ticks;
\r
92 if (objEntry.Expires < now)
\r
93 objEntry.Expires = now;
\r
95 _arrBuckets [GetHashBucket (objEntry.Expires)].Add (objEntry);
\r
98 internal void Remove (CacheEntry objEntry) {
\r
99 if (objEntry.ExpiresBucket != CacheEntry.NoBucketHash)
\r
100 _arrBuckets [objEntry.ExpiresBucket].Remove (objEntry);
\r
103 internal void GarbageCleanup (object State) {
\r
106 // We lock here if FlushExpiredItems take time
\r
108 bucket = (++_intFlush) % 60;
\r
111 // Flush expired items in the current bucket (defined by _intFlush)
\r
112 _arrBuckets [bucket].FlushExpiredItems ();
\r
115 private int GetHashBucket (long ticks) {
\r
116 // 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
\r
117 return (int) (((((ticks + 60000) % _ticksPerCycle) / _ticksPerBucket) + 1) % 60);
\r
121 /// Called by the cache for cleanup.
\r
123 public void Dispose () {
\r
124 // Cleanup the internal timer
\r
125 if (_objTimer != null) {
\r
126 _objTimer.Dispose();
\r