Update svn properties, minor formatting cleanup.
parent
1040f3f454
commit
657af5e611
|
@ -4,464 +4,464 @@ using libsecondlife;
|
|||
|
||||
namespace Opensim.Framework
|
||||
{
|
||||
// The delegate we will use for performing fetch from backing store
|
||||
//
|
||||
public delegate Object FetchDelegate(LLUUID index);
|
||||
public delegate bool ExpireDelegate(LLUUID index);
|
||||
|
||||
// Strategy
|
||||
//
|
||||
// Conservative = Minimize memory. Expire items quickly.
|
||||
// Balanced = Expire items with few hits quickly.
|
||||
// Aggressive = Keep cache full. Expire only when over 90% and adding
|
||||
//
|
||||
public enum CacheStrategy
|
||||
{
|
||||
Conservative = 0,
|
||||
Balanced = 1,
|
||||
Aggressive = 2
|
||||
}
|
||||
|
||||
// Select classes to store data on different media
|
||||
//
|
||||
public enum CacheMedium
|
||||
{
|
||||
Memory = 0,
|
||||
File = 1
|
||||
}
|
||||
|
||||
public enum CacheFlags
|
||||
{
|
||||
CacheMissing = 1,
|
||||
AllowUpdate = 2
|
||||
}
|
||||
|
||||
// The base class of all cache objects. Implements comparison and sorting
|
||||
// by the LLUUID member.
|
||||
//
|
||||
// This is not abstract because we need to instantiate it briefly as a
|
||||
// method parameter
|
||||
//
|
||||
public class CacheItemBase : IEquatable<CacheItemBase>, IComparable<CacheItemBase>
|
||||
{
|
||||
public LLUUID uuid;
|
||||
public DateTime entered;
|
||||
public DateTime lastUsed;
|
||||
public DateTime expires = new DateTime(0);
|
||||
public int hits = 0;
|
||||
|
||||
public virtual Object Retrieve()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void Store(Object data)
|
||||
{
|
||||
}
|
||||
|
||||
public CacheItemBase(LLUUID index)
|
||||
{
|
||||
uuid = index;
|
||||
entered = DateTime.Now;
|
||||
lastUsed = entered;
|
||||
}
|
||||
|
||||
public CacheItemBase(LLUUID index, DateTime ttl)
|
||||
{
|
||||
uuid = index;
|
||||
entered = DateTime.Now;
|
||||
lastUsed = entered;
|
||||
expires = ttl;
|
||||
}
|
||||
|
||||
public virtual bool Equals(CacheItemBase item)
|
||||
{
|
||||
return uuid == item.uuid;
|
||||
}
|
||||
|
||||
public virtual int CompareTo(CacheItemBase item)
|
||||
{
|
||||
return uuid.CompareTo(item.uuid);
|
||||
}
|
||||
|
||||
public virtual bool IsLocked()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple in-memory storage. Boxes the object and stores it in a variable
|
||||
//
|
||||
public class MemoryCacheItem : CacheItemBase
|
||||
{
|
||||
private Object m_Data;
|
||||
|
||||
public MemoryCacheItem(LLUUID index) :
|
||||
base(index)
|
||||
{
|
||||
}
|
||||
|
||||
public MemoryCacheItem(LLUUID index, DateTime ttl) :
|
||||
base(index, ttl)
|
||||
{
|
||||
}
|
||||
|
||||
public MemoryCacheItem(LLUUID index, Object data) :
|
||||
base(index)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) :
|
||||
base(index, ttl)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public override Object Retrieve()
|
||||
{
|
||||
return m_Data;
|
||||
}
|
||||
|
||||
public override void Store(Object data)
|
||||
{
|
||||
m_Data = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple persistent file storage
|
||||
//
|
||||
public class FileCacheItem : CacheItemBase
|
||||
{
|
||||
public FileCacheItem(LLUUID index) :
|
||||
base(index)
|
||||
{
|
||||
}
|
||||
|
||||
public FileCacheItem(LLUUID index, DateTime ttl) :
|
||||
base(index, ttl)
|
||||
{
|
||||
}
|
||||
|
||||
public FileCacheItem(LLUUID index, Object data) :
|
||||
base(index)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public FileCacheItem(LLUUID index, DateTime ttl, Object data) :
|
||||
base(index, ttl)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public override Object Retrieve()
|
||||
{
|
||||
//TODO: Add file access code
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Store(Object data)
|
||||
{
|
||||
//TODO: Add file access code
|
||||
}
|
||||
}
|
||||
|
||||
// The main cache class. This is the class you instantiate to create
|
||||
// a cache
|
||||
//
|
||||
public class Cache
|
||||
{
|
||||
private List<CacheItemBase> m_Index = new List<CacheItemBase>();
|
||||
|
||||
private CacheStrategy m_Strategy;
|
||||
private CacheMedium m_Medium;
|
||||
private CacheFlags m_Flags = 0;
|
||||
private int m_Size = 1024;
|
||||
private TimeSpan m_DefaultTTL = new TimeSpan(0);
|
||||
public ExpireDelegate OnExpire;
|
||||
|
||||
// Comparison interfaces
|
||||
//
|
||||
private class SortLRU : IComparer<CacheItemBase>
|
||||
{
|
||||
public int Compare(CacheItemBase a, CacheItemBase b)
|
||||
{
|
||||
if(a == null && b == null)
|
||||
return 0;
|
||||
if(a == null)
|
||||
return -1;
|
||||
if(b == null)
|
||||
return 1;
|
||||
|
||||
return(a.lastUsed.CompareTo(b.lastUsed));
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience constructors
|
||||
//
|
||||
public Cache()
|
||||
{
|
||||
m_Strategy = CacheStrategy.Balanced;
|
||||
m_Medium = CacheMedium.Memory;
|
||||
m_Flags = 0;
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium) :
|
||||
this(medium, CacheStrategy.Balanced)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium, CacheFlags flags) :
|
||||
this(medium, CacheStrategy.Balanced, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium, CacheStrategy strategy) :
|
||||
this(medium, strategy, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheStrategy strategy, CacheFlags flags) :
|
||||
this(CacheMedium.Memory, strategy, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheFlags flags) :
|
||||
this(CacheMedium.Memory, CacheStrategy.Balanced, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium, CacheStrategy strategy,
|
||||
CacheFlags flags)
|
||||
{
|
||||
m_Strategy = strategy;
|
||||
m_Medium = medium;
|
||||
m_Flags = flags;
|
||||
}
|
||||
|
||||
// Count of the items currently in cache
|
||||
//
|
||||
public int Count
|
||||
{
|
||||
get { lock(m_Index) { return m_Index.Count; } }
|
||||
}
|
||||
|
||||
// Maximum number of items this cache will hold
|
||||
//
|
||||
public int Size
|
||||
{
|
||||
get { return m_Size; }
|
||||
set { SetSize(value); }
|
||||
}
|
||||
|
||||
private void SetSize(int newSize)
|
||||
{
|
||||
lock(m_Index)
|
||||
{
|
||||
if(Count <= Size)
|
||||
return;
|
||||
|
||||
m_Index.Sort(new SortLRU());
|
||||
m_Index.Reverse();
|
||||
|
||||
m_Index.RemoveRange(newSize, Count - newSize);
|
||||
m_Size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan DefaultTTL
|
||||
{
|
||||
get { return m_DefaultTTL; }
|
||||
set { m_DefaultTTL = value; }
|
||||
}
|
||||
|
||||
// Get an item from cache. Return the raw item, not it's data
|
||||
//
|
||||
protected virtual CacheItemBase GetItem(LLUUID index)
|
||||
{
|
||||
CacheItemBase item = null;
|
||||
|
||||
lock(m_Index)
|
||||
{
|
||||
item = m_Index.Find(delegate(CacheItemBase i)
|
||||
{
|
||||
if(i.uuid == index)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if(item == null)
|
||||
{
|
||||
Expire(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
item.hits++;
|
||||
item.lastUsed = DateTime.Now;
|
||||
|
||||
Expire(true);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
// Get an item from cache. Do not try to fetch from source if not
|
||||
// present. Just return null
|
||||
//
|
||||
public virtual Object Get(LLUUID index)
|
||||
{
|
||||
CacheItemBase item = GetItem(index);
|
||||
|
||||
if(item == null)
|
||||
return null;
|
||||
|
||||
return item.Retrieve();
|
||||
}
|
||||
|
||||
// Fetch an object from backing store if not cached, serve from
|
||||
// cache if it is.
|
||||
//
|
||||
public virtual Object Get(LLUUID index, FetchDelegate fetch)
|
||||
{
|
||||
Object item = Get(index);
|
||||
if(item != null)
|
||||
return item;
|
||||
|
||||
Object data = fetch(index);
|
||||
if(data == null)
|
||||
{
|
||||
if((m_Flags & CacheFlags.CacheMissing) != 0)
|
||||
{
|
||||
lock(m_Index)
|
||||
{
|
||||
CacheItemBase missing = new CacheItemBase(index);
|
||||
if(!m_Index.Contains(missing))
|
||||
m_Index.Add(missing);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Store(index, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
public virtual void Store(LLUUID index, Object data)
|
||||
{
|
||||
Type container;
|
||||
|
||||
switch(m_Medium)
|
||||
{
|
||||
case CacheMedium.Memory:
|
||||
container = typeof(MemoryCacheItem);
|
||||
break;
|
||||
case CacheMedium.File:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Store(index, data, container);
|
||||
}
|
||||
|
||||
public virtual void Store(LLUUID index, Object data, Type container)
|
||||
{
|
||||
Store(index, data, container, new Object[] { index });
|
||||
}
|
||||
|
||||
public virtual void Store(LLUUID index, Object data, Type container,
|
||||
Object[] parameters)
|
||||
{
|
||||
Expire(false);
|
||||
|
||||
CacheItemBase item;
|
||||
|
||||
lock(m_Index)
|
||||
{
|
||||
if(m_Index.Contains(new CacheItemBase(index)))
|
||||
{
|
||||
if((m_Flags & CacheFlags.AllowUpdate) != 0)
|
||||
{
|
||||
item = GetItem(index);
|
||||
|
||||
item.hits++;
|
||||
item.lastUsed = DateTime.Now;
|
||||
if(m_DefaultTTL.Ticks != 0)
|
||||
item.expires = DateTime.Now + m_DefaultTTL;
|
||||
|
||||
item.Store(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
item = (CacheItemBase)Activator.CreateInstance(container,
|
||||
parameters);
|
||||
|
||||
if(m_DefaultTTL.Ticks != 0)
|
||||
item.expires = DateTime.Now + m_DefaultTTL;
|
||||
|
||||
m_Index.Add(item);
|
||||
}
|
||||
item.Store(data);
|
||||
}
|
||||
|
||||
protected virtual void Expire(bool getting)
|
||||
{
|
||||
if(getting && (m_Strategy == CacheStrategy.Aggressive))
|
||||
return;
|
||||
|
||||
if(m_DefaultTTL.Ticks != 0)
|
||||
{
|
||||
DateTime now= System.DateTime.Now;
|
||||
|
||||
foreach (CacheItemBase item in new List<CacheItemBase>(m_Index))
|
||||
{
|
||||
if(item.expires.Ticks == 0 ||
|
||||
item.expires <= now)
|
||||
m_Index.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_Strategy)
|
||||
{
|
||||
case CacheStrategy.Aggressive:
|
||||
if(Count < Size)
|
||||
return;
|
||||
|
||||
lock(m_Index)
|
||||
{
|
||||
m_Index.Sort(new SortLRU());
|
||||
m_Index.Reverse();
|
||||
|
||||
int target = (int)((float)Size * 0.9);
|
||||
if(target == Count) // Cover ridiculous cache sizes
|
||||
return;
|
||||
|
||||
ExpireDelegate doExpire = OnExpire;
|
||||
|
||||
if(doExpire != null)
|
||||
{
|
||||
List<CacheItemBase> candidates =
|
||||
m_Index.GetRange(target, Count - target);
|
||||
|
||||
foreach (CacheItemBase i in candidates)
|
||||
{
|
||||
if(doExpire(i.uuid))
|
||||
m_Index.Remove(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Index.RemoveRange(target, Count - target);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// The delegate we will use for performing fetch from backing store
|
||||
//
|
||||
public delegate Object FetchDelegate(LLUUID index);
|
||||
public delegate bool ExpireDelegate(LLUUID index);
|
||||
|
||||
// Strategy
|
||||
//
|
||||
// Conservative = Minimize memory. Expire items quickly.
|
||||
// Balanced = Expire items with few hits quickly.
|
||||
// Aggressive = Keep cache full. Expire only when over 90% and adding
|
||||
//
|
||||
public enum CacheStrategy
|
||||
{
|
||||
Conservative = 0,
|
||||
Balanced = 1,
|
||||
Aggressive = 2
|
||||
}
|
||||
|
||||
// Select classes to store data on different media
|
||||
//
|
||||
public enum CacheMedium
|
||||
{
|
||||
Memory = 0,
|
||||
File = 1
|
||||
}
|
||||
|
||||
public enum CacheFlags
|
||||
{
|
||||
CacheMissing = 1,
|
||||
AllowUpdate = 2
|
||||
}
|
||||
|
||||
// The base class of all cache objects. Implements comparison and sorting
|
||||
// by the LLUUID member.
|
||||
//
|
||||
// This is not abstract because we need to instantiate it briefly as a
|
||||
// method parameter
|
||||
//
|
||||
public class CacheItemBase : IEquatable<CacheItemBase>, IComparable<CacheItemBase>
|
||||
{
|
||||
public LLUUID uuid;
|
||||
public DateTime entered;
|
||||
public DateTime lastUsed;
|
||||
public DateTime expires = new DateTime(0);
|
||||
public int hits = 0;
|
||||
|
||||
public virtual Object Retrieve()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void Store(Object data)
|
||||
{
|
||||
}
|
||||
|
||||
public CacheItemBase(LLUUID index)
|
||||
{
|
||||
uuid = index;
|
||||
entered = DateTime.Now;
|
||||
lastUsed = entered;
|
||||
}
|
||||
|
||||
public CacheItemBase(LLUUID index, DateTime ttl)
|
||||
{
|
||||
uuid = index;
|
||||
entered = DateTime.Now;
|
||||
lastUsed = entered;
|
||||
expires = ttl;
|
||||
}
|
||||
|
||||
public virtual bool Equals(CacheItemBase item)
|
||||
{
|
||||
return uuid == item.uuid;
|
||||
}
|
||||
|
||||
public virtual int CompareTo(CacheItemBase item)
|
||||
{
|
||||
return uuid.CompareTo(item.uuid);
|
||||
}
|
||||
|
||||
public virtual bool IsLocked()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple in-memory storage. Boxes the object and stores it in a variable
|
||||
//
|
||||
public class MemoryCacheItem : CacheItemBase
|
||||
{
|
||||
private Object m_Data;
|
||||
|
||||
public MemoryCacheItem(LLUUID index) :
|
||||
base(index)
|
||||
{
|
||||
}
|
||||
|
||||
public MemoryCacheItem(LLUUID index, DateTime ttl) :
|
||||
base(index, ttl)
|
||||
{
|
||||
}
|
||||
|
||||
public MemoryCacheItem(LLUUID index, Object data) :
|
||||
base(index)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public MemoryCacheItem(LLUUID index, DateTime ttl, Object data) :
|
||||
base(index, ttl)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public override Object Retrieve()
|
||||
{
|
||||
return m_Data;
|
||||
}
|
||||
|
||||
public override void Store(Object data)
|
||||
{
|
||||
m_Data = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple persistent file storage
|
||||
//
|
||||
public class FileCacheItem : CacheItemBase
|
||||
{
|
||||
public FileCacheItem(LLUUID index) :
|
||||
base(index)
|
||||
{
|
||||
}
|
||||
|
||||
public FileCacheItem(LLUUID index, DateTime ttl) :
|
||||
base(index, ttl)
|
||||
{
|
||||
}
|
||||
|
||||
public FileCacheItem(LLUUID index, Object data) :
|
||||
base(index)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public FileCacheItem(LLUUID index, DateTime ttl, Object data) :
|
||||
base(index, ttl)
|
||||
{
|
||||
Store(data);
|
||||
}
|
||||
|
||||
public override Object Retrieve()
|
||||
{
|
||||
//TODO: Add file access code
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void Store(Object data)
|
||||
{
|
||||
//TODO: Add file access code
|
||||
}
|
||||
}
|
||||
|
||||
// The main cache class. This is the class you instantiate to create
|
||||
// a cache
|
||||
//
|
||||
public class Cache
|
||||
{
|
||||
private List<CacheItemBase> m_Index = new List<CacheItemBase>();
|
||||
|
||||
private CacheStrategy m_Strategy;
|
||||
private CacheMedium m_Medium;
|
||||
private CacheFlags m_Flags = 0;
|
||||
private int m_Size = 1024;
|
||||
private TimeSpan m_DefaultTTL = new TimeSpan(0);
|
||||
public ExpireDelegate OnExpire;
|
||||
|
||||
// Comparison interfaces
|
||||
//
|
||||
private class SortLRU : IComparer<CacheItemBase>
|
||||
{
|
||||
public int Compare(CacheItemBase a, CacheItemBase b)
|
||||
{
|
||||
if (a == null && b == null)
|
||||
return 0;
|
||||
if (a == null)
|
||||
return -1;
|
||||
if (b == null)
|
||||
return 1;
|
||||
|
||||
return(a.lastUsed.CompareTo(b.lastUsed));
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience constructors
|
||||
//
|
||||
public Cache()
|
||||
{
|
||||
m_Strategy = CacheStrategy.Balanced;
|
||||
m_Medium = CacheMedium.Memory;
|
||||
m_Flags = 0;
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium) :
|
||||
this(medium, CacheStrategy.Balanced)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium, CacheFlags flags) :
|
||||
this(medium, CacheStrategy.Balanced, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium, CacheStrategy strategy) :
|
||||
this(medium, strategy, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheStrategy strategy, CacheFlags flags) :
|
||||
this(CacheMedium.Memory, strategy, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheFlags flags) :
|
||||
this(CacheMedium.Memory, CacheStrategy.Balanced, flags)
|
||||
{
|
||||
}
|
||||
|
||||
public Cache(CacheMedium medium, CacheStrategy strategy,
|
||||
CacheFlags flags)
|
||||
{
|
||||
m_Strategy = strategy;
|
||||
m_Medium = medium;
|
||||
m_Flags = flags;
|
||||
}
|
||||
|
||||
// Count of the items currently in cache
|
||||
//
|
||||
public int Count
|
||||
{
|
||||
get { lock (m_Index) { return m_Index.Count; } }
|
||||
}
|
||||
|
||||
// Maximum number of items this cache will hold
|
||||
//
|
||||
public int Size
|
||||
{
|
||||
get { return m_Size; }
|
||||
set { SetSize(value); }
|
||||
}
|
||||
|
||||
private void SetSize(int newSize)
|
||||
{
|
||||
lock (m_Index)
|
||||
{
|
||||
if (Count <= Size)
|
||||
return;
|
||||
|
||||
m_Index.Sort(new SortLRU());
|
||||
m_Index.Reverse();
|
||||
|
||||
m_Index.RemoveRange(newSize, Count - newSize);
|
||||
m_Size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan DefaultTTL
|
||||
{
|
||||
get { return m_DefaultTTL; }
|
||||
set { m_DefaultTTL = value; }
|
||||
}
|
||||
|
||||
// Get an item from cache. Return the raw item, not it's data
|
||||
//
|
||||
protected virtual CacheItemBase GetItem(LLUUID index)
|
||||
{
|
||||
CacheItemBase item = null;
|
||||
|
||||
lock (m_Index)
|
||||
{
|
||||
item = m_Index.Find(delegate(CacheItemBase i)
|
||||
{
|
||||
if (i.uuid == index)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
Expire(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
item.hits++;
|
||||
item.lastUsed = DateTime.Now;
|
||||
|
||||
Expire(true);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
// Get an item from cache. Do not try to fetch from source if not
|
||||
// present. Just return null
|
||||
//
|
||||
public virtual Object Get(LLUUID index)
|
||||
{
|
||||
CacheItemBase item = GetItem(index);
|
||||
|
||||
if (item == null)
|
||||
return null;
|
||||
|
||||
return item.Retrieve();
|
||||
}
|
||||
|
||||
// Fetch an object from backing store if not cached, serve from
|
||||
// cache if it is.
|
||||
//
|
||||
public virtual Object Get(LLUUID index, FetchDelegate fetch)
|
||||
{
|
||||
Object item = Get(index);
|
||||
if (item != null)
|
||||
return item;
|
||||
|
||||
Object data = fetch(index);
|
||||
if (data == null)
|
||||
{
|
||||
if ((m_Flags & CacheFlags.CacheMissing) != 0)
|
||||
{
|
||||
lock (m_Index)
|
||||
{
|
||||
CacheItemBase missing = new CacheItemBase(index);
|
||||
if (!m_Index.Contains(missing))
|
||||
m_Index.Add(missing);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Store(index, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
public virtual void Store(LLUUID index, Object data)
|
||||
{
|
||||
Type container;
|
||||
|
||||
switch (m_Medium)
|
||||
{
|
||||
case CacheMedium.Memory:
|
||||
container = typeof(MemoryCacheItem);
|
||||
break;
|
||||
case CacheMedium.File:
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Store(index, data, container);
|
||||
}
|
||||
|
||||
public virtual void Store(LLUUID index, Object data, Type container)
|
||||
{
|
||||
Store(index, data, container, new Object[] { index });
|
||||
}
|
||||
|
||||
public virtual void Store(LLUUID index, Object data, Type container,
|
||||
Object[] parameters)
|
||||
{
|
||||
Expire(false);
|
||||
|
||||
CacheItemBase item;
|
||||
|
||||
lock (m_Index)
|
||||
{
|
||||
if (m_Index.Contains(new CacheItemBase(index)))
|
||||
{
|
||||
if ((m_Flags & CacheFlags.AllowUpdate) != 0)
|
||||
{
|
||||
item = GetItem(index);
|
||||
|
||||
item.hits++;
|
||||
item.lastUsed = DateTime.Now;
|
||||
if (m_DefaultTTL.Ticks != 0)
|
||||
item.expires = DateTime.Now + m_DefaultTTL;
|
||||
|
||||
item.Store(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
item = (CacheItemBase)Activator.CreateInstance(container,
|
||||
parameters);
|
||||
|
||||
if (m_DefaultTTL.Ticks != 0)
|
||||
item.expires = DateTime.Now + m_DefaultTTL;
|
||||
|
||||
m_Index.Add(item);
|
||||
}
|
||||
item.Store(data);
|
||||
}
|
||||
|
||||
protected virtual void Expire(bool getting)
|
||||
{
|
||||
if (getting && (m_Strategy == CacheStrategy.Aggressive))
|
||||
return;
|
||||
|
||||
if (m_DefaultTTL.Ticks != 0)
|
||||
{
|
||||
DateTime now= System.DateTime.Now;
|
||||
|
||||
foreach (CacheItemBase item in new List<CacheItemBase>(m_Index))
|
||||
{
|
||||
if (item.expires.Ticks == 0 ||
|
||||
item.expires <= now)
|
||||
m_Index.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_Strategy)
|
||||
{
|
||||
case CacheStrategy.Aggressive:
|
||||
if (Count < Size)
|
||||
return;
|
||||
|
||||
lock (m_Index)
|
||||
{
|
||||
m_Index.Sort(new SortLRU());
|
||||
m_Index.Reverse();
|
||||
|
||||
int target = (int)((float)Size * 0.9);
|
||||
if (target == Count) // Cover ridiculous cache sizes
|
||||
return;
|
||||
|
||||
ExpireDelegate doExpire = OnExpire;
|
||||
|
||||
if (doExpire != null)
|
||||
{
|
||||
List<CacheItemBase> candidates =
|
||||
m_Index.GetRange(target, Count - target);
|
||||
|
||||
foreach (CacheItemBase i in candidates)
|
||||
{
|
||||
if (doExpire(i.uuid))
|
||||
m_Index.Remove(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Index.RemoveRange(target, Count - target);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,10 +464,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
lock (m_DupeTracker)
|
||||
{
|
||||
if(m_DupeTracker.Count < 1024)
|
||||
if (m_DupeTracker.Count < 1024)
|
||||
return;
|
||||
|
||||
if(System.Environment.TickCount - m_DupeTrackerLastCheck < 2000)
|
||||
if (System.Environment.TickCount - m_DupeTrackerLastCheck < 2000)
|
||||
return;
|
||||
|
||||
m_DupeTrackerLastCheck = System.Environment.TickCount;
|
||||
|
@ -726,7 +726,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
// Assign sequence number here to prevent out of order packets
|
||||
packet.Header.Sequence = NextPacketSequenceNumber();
|
||||
|
||||
lock(m_NeedAck)
|
||||
lock (m_NeedAck)
|
||||
{
|
||||
// We want to see that packet arrive if it's reliable
|
||||
if (packet.Header.Reliable)
|
||||
|
|
Loading…
Reference in New Issue