aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Cache.cs
diff options
context:
space:
mode:
authorJeff Ames2008-08-08 06:39:35 +0000
committerJeff Ames2008-08-08 06:39:35 +0000
commit657af5e61108b9acc6f9097362e5ebeea7d69a92 (patch)
tree950fcf7cf2d85ba69e28540c45b622b816e25348 /OpenSim/Framework/Cache.cs
parentRemove FunSL client stack as it's under development and often won't compile. (diff)
downloadopensim-SC-657af5e61108b9acc6f9097362e5ebeea7d69a92.zip
opensim-SC-657af5e61108b9acc6f9097362e5ebeea7d69a92.tar.gz
opensim-SC-657af5e61108b9acc6f9097362e5ebeea7d69a92.tar.bz2
opensim-SC-657af5e61108b9acc6f9097362e5ebeea7d69a92.tar.xz
Update svn properties, minor formatting cleanup.
Diffstat (limited to 'OpenSim/Framework/Cache.cs')
-rw-r--r--OpenSim/Framework/Cache.cs920
1 files changed, 460 insertions, 460 deletions
diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs
index 88b86a3..780e262 100644
--- a/OpenSim/Framework/Cache.cs
+++ b/OpenSim/Framework/Cache.cs
@@ -4,464 +4,464 @@ using libsecondlife;
4 4
5namespace Opensim.Framework 5namespace Opensim.Framework
6{ 6{
7 // The delegate we will use for performing fetch from backing store 7 // The delegate we will use for performing fetch from backing store
8 // 8 //
9 public delegate Object FetchDelegate(LLUUID index); 9 public delegate Object FetchDelegate(LLUUID index);
10 public delegate bool ExpireDelegate(LLUUID index); 10 public delegate bool ExpireDelegate(LLUUID index);
11 11
12 // Strategy 12 // Strategy
13 // 13 //
14 // Conservative = Minimize memory. Expire items quickly. 14 // Conservative = Minimize memory. Expire items quickly.
15 // Balanced = Expire items with few hits quickly. 15 // Balanced = Expire items with few hits quickly.
16 // Aggressive = Keep cache full. Expire only when over 90% and adding 16 // Aggressive = Keep cache full. Expire only when over 90% and adding
17 // 17 //
18 public enum CacheStrategy 18 public enum CacheStrategy
19 { 19 {
20 Conservative = 0, 20 Conservative = 0,
21 Balanced = 1, 21 Balanced = 1,
22 Aggressive = 2 22 Aggressive = 2
23 } 23 }
24 24
25 // Select classes to store data on different media 25 // Select classes to store data on different media
26 // 26 //
27 public enum CacheMedium 27 public enum CacheMedium
28 { 28 {
29 Memory = 0, 29 Memory = 0,
30 File = 1 30 File = 1
31 } 31 }
32 32
33 public enum CacheFlags 33 public enum CacheFlags
34 { 34 {
35 CacheMissing = 1, 35 CacheMissing = 1,
36 AllowUpdate = 2 36 AllowUpdate = 2
37 } 37 }
38 38
39 // The base class of all cache objects. Implements comparison and sorting 39 // The base class of all cache objects. Implements comparison and sorting
40 // by the LLUUID member. 40 // by the LLUUID member.
41 // 41 //
42 // This is not abstract because we need to instantiate it briefly as a 42 // This is not abstract because we need to instantiate it briefly as a
43 // method parameter 43 // method parameter
44 // 44 //
45 public class CacheItemBase : IEquatable<CacheItemBase>, IComparable<CacheItemBase> 45 public class CacheItemBase : IEquatable<CacheItemBase>, IComparable<CacheItemBase>
46 { 46 {
47 public LLUUID uuid; 47 public LLUUID uuid;
48 public DateTime entered; 48 public DateTime entered;
49 public DateTime lastUsed; 49 public DateTime lastUsed;
50 public DateTime expires = new DateTime(0); 50 public DateTime expires = new DateTime(0);
51 public int hits = 0; 51 public int hits = 0;
52 52
53 public virtual Object Retrieve() 53 public virtual Object Retrieve()
54 { 54 {
55 return null; 55 return null;
56 } 56 }
57 57
58 public virtual void Store(Object data) 58 public virtual void Store(Object data)
59 { 59 {
60 } 60 }
61 61
62 public CacheItemBase(LLUUID index) 62 public CacheItemBase(LLUUID index)
63 { 63 {
64 uuid = index; 64 uuid = index;
65 entered = DateTime.Now; 65 entered = DateTime.Now;
66 lastUsed = entered; 66 lastUsed = entered;
67 } 67 }
68 68
69 public CacheItemBase(LLUUID index, DateTime ttl) 69 public CacheItemBase(LLUUID index, DateTime ttl)
70 { 70 {
71 uuid = index; 71 uuid = index;
72 entered = DateTime.Now; 72 entered = DateTime.Now;
73 lastUsed = entered; 73 lastUsed = entered;
74 expires = ttl; 74 expires = ttl;
75 } 75 }
76 76
77 public virtual bool Equals(CacheItemBase item) 77 public virtual bool Equals(CacheItemBase item)
78 { 78 {
79 return uuid == item.uuid; 79 return uuid == item.uuid;
80 } 80 }
81 81
82 public virtual int CompareTo(CacheItemBase item) 82 public virtual int CompareTo(CacheItemBase item)
83 { 83 {
84 return uuid.CompareTo(item.uuid); 84 return uuid.CompareTo(item.uuid);
85 } 85 }
86 86
87 public virtual bool IsLocked() 87 public virtual bool IsLocked()
88 { 88 {
89 return false; 89 return false;
90 } 90 }
91 } 91 }
92 92
93 // Simple in-memory storage. Boxes the object and stores it in a variable 93 // Simple in-memory storage. Boxes the object and stores it in a variable
94 // 94 //
95 public class MemoryCacheItem : CacheItemBase 95 public class MemoryCacheItem : CacheItemBase
96 { 96 {
97 private Object m_Data; 97 private Object m_Data;
98 98
99 public MemoryCacheItem(LLUUID index) : 99 public MemoryCacheItem(LLUUID index) :
100 base(index) 100 base(index)
101 { 101 {
102 } 102 }
103 103
104 public MemoryCacheItem(LLUUID index, DateTime ttl) : 104 public MemoryCacheItem(LLUUID index, DateTime ttl) :
105 base(index, ttl) 105 base(index, ttl)
106 { 106 {
107 } 107 }
108 108
109 public MemoryCacheItem(LLUUID index, Object data) : 109 public MemoryCacheItem(LLUUID index, Object data) :
110 base(index) 110 base(index)
111 { 111 {
112 Store(data); 112 Store(data);
113 } 113 }
114 114
115 public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) : 115 public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) :
116 base(index, ttl) 116 base(index, ttl)
117 { 117 {
118 Store(data); 118 Store(data);
119 } 119 }
120 120
121 public override Object Retrieve() 121 public override Object Retrieve()
122 { 122 {
123 return m_Data; 123 return m_Data;
124 } 124 }
125 125
126 public override void Store(Object data) 126 public override void Store(Object data)
127 { 127 {
128 m_Data = data; 128 m_Data = data;
129 } 129 }
130 } 130 }
131 131
132 // Simple persistent file storage 132 // Simple persistent file storage
133 // 133 //
134 public class FileCacheItem : CacheItemBase 134 public class FileCacheItem : CacheItemBase
135 { 135 {
136 public FileCacheItem(LLUUID index) : 136 public FileCacheItem(LLUUID index) :
137 base(index) 137 base(index)
138 { 138 {
139 } 139 }
140 140
141 public FileCacheItem(LLUUID index, DateTime ttl) : 141 public FileCacheItem(LLUUID index, DateTime ttl) :
142 base(index, ttl) 142 base(index, ttl)
143 { 143 {
144 } 144 }
145 145
146 public FileCacheItem(LLUUID index, Object data) : 146 public FileCacheItem(LLUUID index, Object data) :
147 base(index) 147 base(index)
148 { 148 {
149 Store(data); 149 Store(data);
150 } 150 }
151 151
152 public FileCacheItem(LLUUID index, DateTime ttl, Object data) : 152 public FileCacheItem(LLUUID index, DateTime ttl, Object data) :
153 base(index, ttl) 153 base(index, ttl)
154 { 154 {
155 Store(data); 155 Store(data);
156 } 156 }
157 157
158 public override Object Retrieve() 158 public override Object Retrieve()
159 { 159 {
160 //TODO: Add file access code 160 //TODO: Add file access code
161 return null; 161 return null;
162 } 162 }
163 163
164 public override void Store(Object data) 164 public override void Store(Object data)
165 { 165 {
166 //TODO: Add file access code 166 //TODO: Add file access code
167 } 167 }
168 } 168 }
169 169
170 // The main cache class. This is the class you instantiate to create 170 // The main cache class. This is the class you instantiate to create
171 // a cache 171 // a cache
172 // 172 //
173 public class Cache 173 public class Cache
174 { 174 {
175 private List<CacheItemBase> m_Index = new List<CacheItemBase>(); 175 private List<CacheItemBase> m_Index = new List<CacheItemBase>();
176 176
177 private CacheStrategy m_Strategy; 177 private CacheStrategy m_Strategy;
178 private CacheMedium m_Medium; 178 private CacheMedium m_Medium;
179 private CacheFlags m_Flags = 0; 179 private CacheFlags m_Flags = 0;
180 private int m_Size = 1024; 180 private int m_Size = 1024;
181 private TimeSpan m_DefaultTTL = new TimeSpan(0); 181 private TimeSpan m_DefaultTTL = new TimeSpan(0);
182 public ExpireDelegate OnExpire; 182 public ExpireDelegate OnExpire;
183 183
184 // Comparison interfaces 184 // Comparison interfaces
185 // 185 //
186 private class SortLRU : IComparer<CacheItemBase> 186 private class SortLRU : IComparer<CacheItemBase>
187 { 187 {
188 public int Compare(CacheItemBase a, CacheItemBase b) 188 public int Compare(CacheItemBase a, CacheItemBase b)
189 { 189 {
190 if(a == null && b == null) 190 if (a == null && b == null)
191 return 0; 191 return 0;
192 if(a == null) 192 if (a == null)
193 return -1; 193 return -1;
194 if(b == null) 194 if (b == null)
195 return 1; 195 return 1;
196 196
197 return(a.lastUsed.CompareTo(b.lastUsed)); 197 return(a.lastUsed.CompareTo(b.lastUsed));
198 } 198 }
199 } 199 }
200 200
201 // Convenience constructors 201 // Convenience constructors
202 // 202 //
203 public Cache() 203 public Cache()
204 { 204 {
205 m_Strategy = CacheStrategy.Balanced; 205 m_Strategy = CacheStrategy.Balanced;
206 m_Medium = CacheMedium.Memory; 206 m_Medium = CacheMedium.Memory;
207 m_Flags = 0; 207 m_Flags = 0;
208 } 208 }
209 209
210 public Cache(CacheMedium medium) : 210 public Cache(CacheMedium medium) :
211 this(medium, CacheStrategy.Balanced) 211 this(medium, CacheStrategy.Balanced)
212 { 212 {
213 } 213 }
214 214
215 public Cache(CacheMedium medium, CacheFlags flags) : 215 public Cache(CacheMedium medium, CacheFlags flags) :
216 this(medium, CacheStrategy.Balanced, flags) 216 this(medium, CacheStrategy.Balanced, flags)
217 { 217 {
218 } 218 }
219 219
220 public Cache(CacheMedium medium, CacheStrategy strategy) : 220 public Cache(CacheMedium medium, CacheStrategy strategy) :
221 this(medium, strategy, 0) 221 this(medium, strategy, 0)
222 { 222 {
223 } 223 }
224 224
225 public Cache(CacheStrategy strategy, CacheFlags flags) : 225 public Cache(CacheStrategy strategy, CacheFlags flags) :
226 this(CacheMedium.Memory, strategy, flags) 226 this(CacheMedium.Memory, strategy, flags)
227 { 227 {
228 } 228 }
229 229
230 public Cache(CacheFlags flags) : 230 public Cache(CacheFlags flags) :
231 this(CacheMedium.Memory, CacheStrategy.Balanced, flags) 231 this(CacheMedium.Memory, CacheStrategy.Balanced, flags)
232 { 232 {
233 } 233 }
234 234
235 public Cache(CacheMedium medium, CacheStrategy strategy, 235 public Cache(CacheMedium medium, CacheStrategy strategy,
236 CacheFlags flags) 236 CacheFlags flags)
237 { 237 {
238 m_Strategy = strategy; 238 m_Strategy = strategy;
239 m_Medium = medium; 239 m_Medium = medium;
240 m_Flags = flags; 240 m_Flags = flags;
241 } 241 }
242 242
243 // Count of the items currently in cache 243 // Count of the items currently in cache
244 // 244 //
245 public int Count 245 public int Count
246 { 246 {
247 get { lock(m_Index) { return m_Index.Count; } } 247 get { lock (m_Index) { return m_Index.Count; } }
248 } 248 }
249 249
250 // Maximum number of items this cache will hold 250 // Maximum number of items this cache will hold
251 // 251 //
252 public int Size 252 public int Size
253 { 253 {
254 get { return m_Size; } 254 get { return m_Size; }
255 set { SetSize(value); } 255 set { SetSize(value); }
256 } 256 }
257 257
258 private void SetSize(int newSize) 258 private void SetSize(int newSize)
259 { 259 {
260 lock(m_Index) 260 lock (m_Index)
261 { 261 {
262 if(Count <= Size) 262 if (Count <= Size)
263 return; 263 return;
264 264
265 m_Index.Sort(new SortLRU()); 265 m_Index.Sort(new SortLRU());
266 m_Index.Reverse(); 266 m_Index.Reverse();
267 267
268 m_Index.RemoveRange(newSize, Count - newSize); 268 m_Index.RemoveRange(newSize, Count - newSize);
269 m_Size = newSize; 269 m_Size = newSize;
270 } 270 }
271 } 271 }
272 272
273 public TimeSpan DefaultTTL 273 public TimeSpan DefaultTTL
274 { 274 {
275 get { return m_DefaultTTL; } 275 get { return m_DefaultTTL; }
276 set { m_DefaultTTL = value; } 276 set { m_DefaultTTL = value; }
277 } 277 }
278 278
279 // Get an item from cache. Return the raw item, not it's data 279 // Get an item from cache. Return the raw item, not it's data
280 // 280 //
281 protected virtual CacheItemBase GetItem(LLUUID index) 281 protected virtual CacheItemBase GetItem(LLUUID index)
282 { 282 {
283 CacheItemBase item = null; 283 CacheItemBase item = null;
284 284
285 lock(m_Index) 285 lock (m_Index)
286 { 286 {
287 item = m_Index.Find(delegate(CacheItemBase i) 287 item = m_Index.Find(delegate(CacheItemBase i)
288 { 288 {
289 if(i.uuid == index) 289 if (i.uuid == index)
290 return true; 290 return true;
291 return false; 291 return false;
292 }); 292 });
293 } 293 }
294 294
295 if(item == null) 295 if (item == null)
296 { 296 {
297 Expire(true); 297 Expire(true);
298 return null; 298 return null;
299 } 299 }
300 300
301 item.hits++; 301 item.hits++;
302 item.lastUsed = DateTime.Now; 302 item.lastUsed = DateTime.Now;
303 303
304 Expire(true); 304 Expire(true);
305 305
306 return item; 306 return item;
307 } 307 }
308 308
309 // Get an item from cache. Do not try to fetch from source if not 309 // Get an item from cache. Do not try to fetch from source if not
310 // present. Just return null 310 // present. Just return null
311 // 311 //
312 public virtual Object Get(LLUUID index) 312 public virtual Object Get(LLUUID index)
313 { 313 {
314 CacheItemBase item = GetItem(index); 314 CacheItemBase item = GetItem(index);
315 315
316 if(item == null) 316 if (item == null)
317 return null; 317 return null;
318 318
319 return item.Retrieve(); 319 return item.Retrieve();
320 } 320 }
321 321
322 // Fetch an object from backing store if not cached, serve from 322 // Fetch an object from backing store if not cached, serve from
323 // cache if it is. 323 // cache if it is.
324 // 324 //
325 public virtual Object Get(LLUUID index, FetchDelegate fetch) 325 public virtual Object Get(LLUUID index, FetchDelegate fetch)
326 { 326 {
327 Object item = Get(index); 327 Object item = Get(index);
328 if(item != null) 328 if (item != null)
329 return item; 329 return item;
330 330
331 Object data = fetch(index); 331 Object data = fetch(index);
332 if(data == null) 332 if (data == null)
333 { 333 {
334 if((m_Flags & CacheFlags.CacheMissing) != 0) 334 if ((m_Flags & CacheFlags.CacheMissing) != 0)
335 { 335 {
336 lock(m_Index) 336 lock (m_Index)
337 { 337 {
338 CacheItemBase missing = new CacheItemBase(index); 338 CacheItemBase missing = new CacheItemBase(index);
339 if(!m_Index.Contains(missing)) 339 if (!m_Index.Contains(missing))
340 m_Index.Add(missing); 340 m_Index.Add(missing);
341 } 341 }
342 } 342 }
343 return null; 343 return null;
344 } 344 }
345 345
346 Store(index, data); 346 Store(index, data);
347 347
348 return data; 348 return data;
349 } 349 }
350 350
351 351
352 public virtual void Store(LLUUID index, Object data) 352 public virtual void Store(LLUUID index, Object data)
353 { 353 {
354 Type container; 354 Type container;
355 355
356 switch(m_Medium) 356 switch (m_Medium)
357 { 357 {
358 case CacheMedium.Memory: 358 case CacheMedium.Memory:
359 container = typeof(MemoryCacheItem); 359 container = typeof(MemoryCacheItem);
360 break; 360 break;
361 case CacheMedium.File: 361 case CacheMedium.File:
362 return; 362 return;
363 default: 363 default:
364 return; 364 return;
365 } 365 }
366 366
367 Store(index, data, container); 367 Store(index, data, container);
368 } 368 }
369 369
370 public virtual void Store(LLUUID index, Object data, Type container) 370 public virtual void Store(LLUUID index, Object data, Type container)
371 { 371 {
372 Store(index, data, container, new Object[] { index }); 372 Store(index, data, container, new Object[] { index });
373 } 373 }
374 374
375 public virtual void Store(LLUUID index, Object data, Type container, 375 public virtual void Store(LLUUID index, Object data, Type container,
376 Object[] parameters) 376 Object[] parameters)
377 { 377 {
378 Expire(false); 378 Expire(false);
379 379
380 CacheItemBase item; 380 CacheItemBase item;
381 381
382 lock(m_Index) 382 lock (m_Index)
383 { 383 {
384 if(m_Index.Contains(new CacheItemBase(index))) 384 if (m_Index.Contains(new CacheItemBase(index)))
385 { 385 {
386 if((m_Flags & CacheFlags.AllowUpdate) != 0) 386 if ((m_Flags & CacheFlags.AllowUpdate) != 0)
387 { 387 {
388 item = GetItem(index); 388 item = GetItem(index);
389 389
390 item.hits++; 390 item.hits++;
391 item.lastUsed = DateTime.Now; 391 item.lastUsed = DateTime.Now;
392 if(m_DefaultTTL.Ticks != 0) 392 if (m_DefaultTTL.Ticks != 0)
393 item.expires = DateTime.Now + m_DefaultTTL; 393 item.expires = DateTime.Now + m_DefaultTTL;
394 394
395 item.Store(data); 395 item.Store(data);
396 } 396 }
397 return; 397 return;
398 } 398 }
399 399
400 item = (CacheItemBase)Activator.CreateInstance(container, 400 item = (CacheItemBase)Activator.CreateInstance(container,
401 parameters); 401 parameters);
402 402
403 if(m_DefaultTTL.Ticks != 0) 403 if (m_DefaultTTL.Ticks != 0)
404 item.expires = DateTime.Now + m_DefaultTTL; 404 item.expires = DateTime.Now + m_DefaultTTL;
405 405
406 m_Index.Add(item); 406 m_Index.Add(item);
407 } 407 }
408 item.Store(data); 408 item.Store(data);
409 } 409 }
410 410
411 protected virtual void Expire(bool getting) 411 protected virtual void Expire(bool getting)
412 { 412 {
413 if(getting && (m_Strategy == CacheStrategy.Aggressive)) 413 if (getting && (m_Strategy == CacheStrategy.Aggressive))
414 return; 414 return;
415 415
416 if(m_DefaultTTL.Ticks != 0) 416 if (m_DefaultTTL.Ticks != 0)
417 { 417 {
418 DateTime now= System.DateTime.Now; 418 DateTime now= System.DateTime.Now;
419 419
420 foreach (CacheItemBase item in new List<CacheItemBase>(m_Index)) 420 foreach (CacheItemBase item in new List<CacheItemBase>(m_Index))
421 { 421 {
422 if(item.expires.Ticks == 0 || 422 if (item.expires.Ticks == 0 ||
423 item.expires <= now) 423 item.expires <= now)
424 m_Index.Remove(item); 424 m_Index.Remove(item);
425 } 425 }
426 } 426 }
427 427
428 switch (m_Strategy) 428 switch (m_Strategy)
429 { 429 {
430 case CacheStrategy.Aggressive: 430 case CacheStrategy.Aggressive:
431 if(Count < Size) 431 if (Count < Size)
432 return; 432 return;
433 433
434 lock(m_Index) 434 lock (m_Index)
435 { 435 {
436 m_Index.Sort(new SortLRU()); 436 m_Index.Sort(new SortLRU());
437 m_Index.Reverse(); 437 m_Index.Reverse();
438 438
439 int target = (int)((float)Size * 0.9); 439 int target = (int)((float)Size * 0.9);
440 if(target == Count) // Cover ridiculous cache sizes 440 if (target == Count) // Cover ridiculous cache sizes
441 return; 441 return;
442 442
443 ExpireDelegate doExpire = OnExpire; 443 ExpireDelegate doExpire = OnExpire;
444 444
445 if(doExpire != null) 445 if (doExpire != null)
446 { 446 {
447 List<CacheItemBase> candidates = 447 List<CacheItemBase> candidates =
448 m_Index.GetRange(target, Count - target); 448 m_Index.GetRange(target, Count - target);
449 449
450 foreach (CacheItemBase i in candidates) 450 foreach (CacheItemBase i in candidates)
451 { 451 {
452 if(doExpire(i.uuid)) 452 if (doExpire(i.uuid))
453 m_Index.Remove(i); 453 m_Index.Remove(i);
454 } 454 }
455 } 455 }
456 else 456 else
457 { 457 {
458 m_Index.RemoveRange(target, Count - target); 458 m_Index.RemoveRange(target, Count - target);
459 } 459 }
460 } 460 }
461 break; 461 break;
462 default: 462 default:
463 break; 463 break;
464 } 464 }
465 } 465 }
466 } 466 }
467} 467}