public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null) { string path = GetCachePath(key, regionName); object oldData = null; //pull old value if it exists if (File.Exists(path)) { try { oldData = Get(key, regionName); } catch (Exception) { oldData = null; } } SerializableCacheItemPolicy cachePolicy = new SerializableCacheItemPolicy(policy); FileCachePayload newPayload = new FileCachePayload(value, cachePolicy); WriteFile(key, newPayload, regionName); //As documented in the spec (http://msdn.microsoft.com/en-us/library/dd780602.aspx), return the old //cached value or null return(oldData); }
public override object Remove(string key, string regionName = null) { object valueToDelete = null; if (Contains(key, regionName)) { // Because of the possibility of multiple threads accessing this, it's possible that // while we're trying to remove something, another thread has already removed it. try { //remove cache entry // CT note: calling Get from remove leads to an infinite loop and stack overflow, // so I replaced it with a simple ReadFile call. None of the code here actually // uses this object returned, but just in case someone else's outside code does. FileCachePayload fcp = ReadFile(key, regionName); valueToDelete = fcp.Payload; string path = GetCachePath(key, regionName); CurrentCacheSize -= new FileInfo(path).Length; File.Delete(path); //remove policy file string cachedPolicy = GetPolicyPath(key, regionName); CurrentCacheSize -= new FileInfo(cachedPolicy).Length; File.Delete(cachedPolicy); } catch (IOException) { } } return(valueToDelete); }
/// <summary> /// This function serves to centralize file reads within this class. /// </summary> /// <param name="mode">the payload reading mode</param> /// <param name="key"></param> /// <param name="objectBinder"></param> /// <returns></returns> // TODO: This was protected, but since Simon Thum's additions other methods require this. We need to merge with that change to move whatever is relevant behind this interface // and restore the visibility to protected public virtual FileCachePayload ReadFile(FileCache.PayloadMode mode, string key, string regionName = null, SerializationBinder objectBinder = null) { string cachePath = GetCachePath(key, regionName); string policyPath = GetPolicyPath(key, regionName); FileCachePayload payload = new FileCachePayload(null); switch (mode) { case FileCache.PayloadMode.Filename: payload.Payload = cachePath; break; case FileCache.PayloadMode.Serializable: payload.Payload = Deserialize(cachePath); break; case FileCache.PayloadMode.RawBytes: payload.Payload = LoadRawPayloadData(cachePath); break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } try { // TODO: In part of the merge it looked like the policy was force serialized with LocalCacheBinder(), is this intended? payload.Policy = Deserialize(policyPath) as SerializableCacheItemPolicy; } catch { payload.Policy = new SerializableCacheItemPolicy(); } return(payload); }
/// <summary> /// Deletes the specified key/region combo. Returns bytes freed from delete. /// </summary> /// <param name="key"></param> /// <param name="regionName"></param> /// <returns></returns> public virtual long DeleteFile(string key, string regionName = null) { long bytesFreed = 0; // Because of the possibility of multiple threads accessing this, it's possible that // while we're trying to remove something, another thread has already removed it. try { FileCachePayload fcp = ReadFile(FileCache.PayloadMode.Filename, key, regionName); string path = GetCachePath(key, regionName); bytesFreed -= new FileInfo(path).Length; File.Delete(path); //remove policy file string cachedPolicy = GetPolicyPath(key, regionName); bytesFreed -= new FileInfo(cachedPolicy).Length; File.Delete(cachedPolicy); } catch (IOException ex) { //Owning FC might be interested in this exception. throw ex; } return(Math.Abs(bytesFreed)); }
/// <summary> /// This function serves to centralize file writes within this class /// </summary> private void WriteFile(string key, FileCachePayload data, string regionName = null) { string cachedPolicy = GetPolicyPath(key, regionName); string cachedItemPath = GetCachePath(key, regionName); //remove current item / policy from cache size calculations if (File.Exists(cachedItemPath)) { CurrentCacheSize -= new FileInfo(cachedItemPath).Length; } if (File.Exists(cachedPolicy)) { CurrentCacheSize -= new FileInfo(cachedPolicy).Length; } //write the object payload (lock the file so we can write to it and force others to wait for us to finish) using (FileStream stream = GetStream(cachedItemPath, FileMode.Create, FileAccess.Write)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data.Payload); //adjust cache size (while we have the file to ourselves) CurrentCacheSize += new FileInfo(cachedItemPath).Length; stream.Close(); } //write the cache policy using (FileStream stream = GetStream(cachedPolicy, FileMode.Create, FileAccess.Write)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data.Policy); // adjust cache size CurrentCacheSize += new FileInfo(cachedPolicy).Length; stream.Close(); } // try to update the last access time try { File.SetLastAccessTime(cachedItemPath, DateTime.Now); } catch (IOException) { } //check to see if limit was reached if (CurrentCacheSize > MaxCacheSize) { MaxCacheSizeReached(this, new FileCacheEventArgs(CurrentCacheSize, MaxCacheSize)); } }
public override object Get(string key, string regionName = null) { FileCachePayload payload = ReadFile(key, regionName) as FileCachePayload; string cachedItemPath = GetCachePath(key, regionName); //null payload? if (payload != null) { //did the item expire? if (payload.Policy.AbsoluteExpiration < DateTime.Now) { //set the payload to null payload.Payload = null; //delete the file from the cache try { // CT Note: I changed this to Remove from File.Delete so that the coresponding // policy file will be deleted as well, and CurrentCacheSize will be updated. Remove(key, regionName); } catch (Exception) { } } else { //does the item have a sliding expiration? if (payload.Policy.SlidingExpiration > new TimeSpan()) { payload.Policy.AbsoluteExpiration = DateTime.Now.Add(payload.Policy.SlidingExpiration); WriteFile(cachedItemPath, payload, regionName); } //update the file's access time File.SetLastAccessTime(cachedItemPath, DateTime.Now); } } else { //remove null payload Remove(key, regionName); //create dummy one for return payload = new FileCachePayload(null); } return(payload.Payload); }
/// <summary> /// Returns the policy attached to a given cache item. /// </summary> /// <param name="key">The key of the item</param> /// <param name="regionName">The region in which the key exists</param> /// <returns></returns> public CacheItemPolicy GetPolicy(string key, string regionName = null) { CacheItemPolicy policy = new CacheItemPolicy(); FileCachePayload payload = ReadFile(key, regionName) as FileCachePayload; if (payload != null) { try { policy.SlidingExpiration = payload.Policy.SlidingExpiration; policy.AbsoluteExpiration = payload.Policy.AbsoluteExpiration; } catch (Exception) { } } return policy; }
/// <summary> /// This function serves to centralize file reads within this class. /// </summary> /// <param name="path"></param> /// <param name="objectBinder"></param> /// <returns></returns> private FileCachePayload ReadFile(string key, string regionName = null, SerializationBinder objectBinder = null) { object data = null; SerializableCacheItemPolicy policy = new SerializableCacheItemPolicy(); string cachePath = GetCachePath(key, regionName); string policyPath = GetPolicyPath(key, regionName); FileCachePayload payload = new FileCachePayload(null); if (File.Exists(cachePath)) { using (FileStream stream = GetStream(cachePath, FileMode.Open, FileAccess.Read)) { BinaryFormatter formatter = new BinaryFormatter(); //AC: From http://spazzarama.com//2009/06/25/binary-deserialize-unable-to-find-assembly/ // Needed to deserialize custom objects if (objectBinder != null) { //take supplied binder over default binder formatter.Binder = objectBinder; } else if (_binder != null) { formatter.Binder = _binder; } try { data = formatter.Deserialize(stream); } catch (SerializationException) { data = null; } finally { stream.Close(); } } } if (File.Exists(policyPath)) { using (FileStream stream = GetStream(policyPath, FileMode.Open, FileAccess.Read)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Binder = new LocalCacheBinder(); try { policy = formatter.Deserialize(stream) as SerializableCacheItemPolicy; } catch (SerializationException) { policy = new SerializableCacheItemPolicy(); } finally { stream.Close(); } } } payload.Payload = data; payload.Policy = policy; return(payload); }
/// <summary> /// This function serves to centralize file writes within this class /// </summary> public virtual long WriteFile(FileCache.PayloadMode mode, string key, FileCachePayload data, string regionName = null, bool policyUpdateOnly = false) { string cachedPolicy = GetPolicyPath(key, regionName); string cachedItemPath = GetCachePath(key, regionName); long cacheSizeDelta = 0; //ensure that the cache policy contains the correct key data.Policy.Key = key; if (!policyUpdateOnly) { long oldBlobSize = 0; if (File.Exists(cachedItemPath)) { oldBlobSize = new FileInfo(cachedItemPath).Length; } switch (mode) { case FileCache.PayloadMode.Serializable: using (FileStream stream = GetStream(cachedItemPath, FileMode.Create, FileAccess.Write, FileShare.None)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data.Payload); } break; case FileCache.PayloadMode.RawBytes: using (FileStream stream = GetStream(cachedItemPath, FileMode.Create, FileAccess.Write, FileShare.None)) { if (data.Payload is byte[]) { byte[] dataPayload = (byte[])data.Payload; stream.Write(dataPayload, 0, dataPayload.Length); } else if (data.Payload is Stream) { Stream dataPayload = (Stream)data.Payload; dataPayload.CopyTo(stream); // no close or the like, we are not the owner } } break; case FileCache.PayloadMode.Filename: File.Copy((string)data.Payload, cachedItemPath, true); break; } //adjust cache size (while we have the file to ourselves) cacheSizeDelta += new FileInfo(cachedItemPath).Length - oldBlobSize; } //remove current policy file from cache size calculations if (File.Exists(cachedPolicy)) { cacheSizeDelta -= new FileInfo(cachedPolicy).Length; } //write the cache policy using (FileStream stream = GetStream(cachedPolicy, FileMode.Create, FileAccess.Write, FileShare.None)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data.Policy); // adjust cache size cacheSizeDelta += new FileInfo(cachedPolicy).Length; stream.Close(); } return(cacheSizeDelta); }