Welcome to mirror list, hosted at ThFree Co, Russian Federation.

CacheExpires.cs « System.Web.Caching « System.Web « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: cad44c36af1e3616232540d6f8d57b8587ffd67c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// 
// System.Web.Caching
//
// Author:
//   Patrik Torstensson (Patrik.Torstensson@labs2.com)
// Changes:
//   Daniel Cazzulino [DHC] (dcazzulino@users.sf.net)
//
// (C) Copyright Patrik Torstensson, 2001
//
namespace System.Web.Caching
{
	/// <summary>
	/// Class responsible for handling time based flushing of entries in the cache. The class creates
	/// and manages 60 buckets each holding every item that expires that minute. The bucket calculated
	/// for an entry is one minute more than the timeout just to make sure that the item end up in the
	/// bucket where it should be flushed.
	/// </summary>
	public class CacheExpires : System.IDisposable
	{
		static int	_intFlush;
		/// <summary>
		/// 1 bucket == 1 minute == 10M ticks (1 second) * 60
		/// </summary>
		static long _ticksPerBucket = 600000000;
		/// <summary>
		/// 1 cycle == 1 hour
		/// </summary>
		static long _ticksPerCycle = _ticksPerBucket * 60;

		private ExpiresBucket[] _arrBuckets;
		private System.Threading.Timer _objTimer;
		private Cache _objManager;

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="objManager">The cache manager, used when flushing items in a bucket.</param>
		public CacheExpires(Cache objManager)
		{
			_objManager = objManager;
			Initialize();
		}

		/// <summary>
		/// Initializes the class.
		/// </summary>
		private void Initialize()
		{
			// Create one bucket per minute
			_arrBuckets = new ExpiresBucket[60];

			byte bytePos = 0;
			do 
			{
				_arrBuckets[bytePos] = new ExpiresBucket(bytePos, _objManager);
				bytePos++;
			} while (bytePos < 60);

			// GC Bucket controller
			_intFlush = System.DateTime.Now.Minute - 1;
			_objTimer = new System.Threading.Timer(new System.Threading.TimerCallback(GarbageCleanup), null, 10000, 60000);
		}

		/// <summary>
		/// Adds a Cache entry to the correct flush bucket.
		/// </summary>
		/// <param name="objEntry">Cache entry to add.</param>
		public void Add(CacheEntry objEntry)
		{
			lock(this) 
			{
				// If the entry doesn't have a expires time we assume that the entry is due to expire now.
				if (objEntry.Expires == 0) 
				{
					objEntry.Expires = System.DateTime.Now.Ticks;
				}

                _arrBuckets[GetHashBucket(objEntry.Expires)].Add(objEntry);
			}
		}

		public void Remove(CacheEntry objEntry)
		{
			lock(this) 
			{
				// If the entry doesn't have a expires time we assume that the entry is due to expire now.
				if (objEntry.Expires == 0) 
				{
					objEntry.Expires = System.DateTime.Now.Ticks;
				}

				_arrBuckets[GetHashBucket(objEntry.Expires)].Remove(objEntry);
			}
		}

		public void Update(CacheEntry objEntry, long ticksExpires)
		{
			lock(this) 
			{
				// If the entry doesn't have a expires time we assume that the entry is due to expire now.
				if (objEntry.Expires == 0) 
				{
					objEntry.Expires = System.DateTime.Now.Ticks;
				}

				_arrBuckets[GetHashBucket(objEntry.Expires)].Update(objEntry, ticksExpires);
			}		
		}

		public void GarbageCleanup(object State)
		{
			ExpiresBucket	objBucket;

			lock(this)
			{
				// Do cleanup of the bucket 
				objBucket = _arrBuckets[(++_intFlush) % 60];
			}	

			// Flush expired items in the current bucket (defined by _intFlush)
			objBucket.FlushExpiredItems();
		}

		private int GetHashBucket(long ticks)
		{
			// 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
			return (int) (((((ticks + 60000) % _ticksPerCycle) / _ticksPerBucket) + 1) % 60);
		}

		/// <summary>
		/// Called by the cache for cleanup.
		/// </summary>
		public void Dispose()
		{
			lock(this)
			{
				// Cleanup the internal timer
				if (_objTimer != null)
				{
					_objTimer.Dispose();
					_objTimer = null;
				}
			}
		}
	}
}