2 // System.Web.Caching
\r
5 // Patrik Torstensson (Patrik.Torstensson@labs2.com)
\r
7 // (C) Copyright Patrik Torstensson, 2001
\r
9 namespace System.Web.Caching
\r
12 /// Responsible for holding a cache entry in the linked list bucket.
\r
14 public struct ExpiresEntry
\r
16 public CacheEntry _objEntry;
\r
17 public long _ticksExpires;
\r
18 public int _intNext;
\r
22 /// Holds cache entries that has a expiration in a bucket list.
\r
24 public class ExpiresBucket
\r
26 private static int MIN_ENTRIES = 16;
\r
28 private byte _byteID;
\r
29 private int _intSize;
\r
30 private int _intCount;
\r
31 private int _intNext;
\r
33 private Cache _objManager;
\r
35 private ExpiresEntry [] _arrEntries;
\r
38 /// Constructs a new bucket.
\r
40 /// <param name="bucket">Current bucket ID.</param>
\r
41 /// <param name="objManager">Cache manager reponsible for the item(s) in the expires bucket.</param>
\r
42 public ExpiresBucket(byte bucket, Cache objManager)
\r
44 _objManager = objManager;
\r
49 /// Initializes the expires bucket, creates a linked list of MIN_ENTRIES.
\r
51 /// <param name="bucket">Bucket ID.</param>
\r
52 private void Initialize(byte bucket)
\r
58 _arrEntries = new ExpiresEntry[MIN_ENTRIES];
\r
59 _intSize = MIN_ENTRIES;
\r
64 _arrEntries[intPos]._intNext = intPos + 1;
\r
65 _arrEntries[intPos]._ticksExpires = System.DateTime.MaxValue.Ticks;
\r
68 } while (intPos < _intSize);
\r
70 _arrEntries[_intSize - 1]._intNext = -1;
\r
74 /// Expands the bucket linked array list.
\r
76 private void Expand()
\r
78 ExpiresEntry [] arrData;
\r
84 intOldSize = _intSize;
\r
87 // Create a new array and copy the old data into the new array
\r
88 arrData = new ExpiresEntry[_intSize];
\r
91 arrData[intPos] = _arrEntries[intPos];
\r
93 } while (intPos < intOldSize);
\r
97 // Initialize the "new" positions.
\r
100 arrData[intPos]._intNext = intPos + 1;
\r
102 } while (intPos < _intSize);
\r
104 arrData[_intSize - 1]._intNext = -1;
\r
106 _arrEntries = arrData;
\r
111 /// Adds a cache entry into the expires bucket.
\r
113 /// <param name="objEntry">Cache Entry object to be added.</param>
\r
114 public void Add(CacheEntry objEntry)
\r
116 if (_intNext == -1)
\r
123 _arrEntries[_intNext]._ticksExpires = objEntry.Expires;
\r
124 _arrEntries[_intNext]._objEntry = objEntry;
\r
126 _intNext = _arrEntries[_intNext]._intNext;
\r
133 /// Removes a cache entry from the expires bucket.
\r
135 /// <param name="objEntry">Cache entry to be removed.</param>
\r
136 public void Remove(CacheEntry objEntry)
\r
140 // Check if this is our bucket
\r
141 if (objEntry.ExpiresIndex != _byteID) return;
\r
142 if (objEntry.ExpiresIndex == System.Int32.MaxValue) return;
\r
143 if (_arrEntries.Length < objEntry.ExpiresIndex) return;
\r
147 _arrEntries[objEntry.ExpiresIndex]._objEntry.ExpiresBucket = byte.MaxValue;
\r
148 _arrEntries[objEntry.ExpiresIndex]._objEntry.ExpiresIndex = int.MaxValue;
\r
149 _arrEntries[objEntry.ExpiresIndex]._objEntry = null;
\r
150 _intNext = _arrEntries[objEntry.ExpiresIndex]._intNext;
\r
155 /// Updates a cache entry in the expires bucket, this is called during a hit of an item if the
\r
156 /// cache item has a sliding expiration. The function is responsible for updating the cache
\r
159 /// <param name="objEntry">Cache entry to update.</param>
\r
160 /// <param name="ticksExpires">New expiration value for the cache entry.</param>
\r
161 public void Update(CacheEntry objEntry, long ticksExpires)
\r
165 // Check if this is our bucket
\r
166 if (objEntry.ExpiresIndex != _byteID) return;
\r
167 if (objEntry.ExpiresIndex == System.Int32.MaxValue) return;
\r
168 if (_arrEntries.Length < objEntry.ExpiresIndex) return;
\r
170 _arrEntries[objEntry.ExpiresIndex]._ticksExpires = ticksExpires;
\r
171 _arrEntries[objEntry.ExpiresIndex]._objEntry.Expires = ticksExpires;
\r
176 /// Flushes all cache entries that has expired and removes them from the cache manager.
\r
178 public void FlushExpiredItems()
\r
180 ExpiresEntry objEntry;
\r
181 CacheEntry [] arrCacheEntries;
\r
187 ticksNow = System.DateTime.Now.Ticks;
\r
191 // Lookup all items that needs to be removed, this is done in a two part
\r
192 // operation to minimize the locking time.
\r
195 arrCacheEntries = new CacheEntry[_intSize];
\r
200 objEntry = _arrEntries[intPos];
\r
201 if (objEntry._objEntry != null)
\r
203 if (objEntry._ticksExpires < ticksNow)
\r
205 arrCacheEntries[intCachePos++] = objEntry._objEntry;
\r
207 objEntry._objEntry.ExpiresBucket = byte.MaxValue;
\r
208 objEntry._objEntry.ExpiresIndex = int.MaxValue;
\r
209 objEntry._objEntry = null;
\r
210 _intNext = objEntry._intNext;
\r
215 } while (intPos < _intSize);
\r
218 // If we have any entries to remove, go ahead and call the cache manager remove.
\r
219 if (intCachePos > 0)
\r
224 _objManager.Remove(arrCacheEntries[intPos].Key, CacheItemRemovedReason.Expired);
\r
227 } while (intPos < intCachePos);
\r
232 /// Returns the current size of the expires bucket.
\r
238 return _arrEntries.Length;
\r
243 /// Returns number of items in the bucket.
\r