// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
//
//
// Encapsulates methods that allow the caching and retrieval of objects from the in memory cache.
//
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Caching
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.Caching;
///
/// Encapsulates methods that allow the caching and retrieval of objects from the in memory cache.
///
internal static class MemCache
{
///
/// The cache
///
private static readonly ObjectCache Cache = MemoryCache.Default;
///
/// An internal list of cache keys to allow bulk removal.
///
private static readonly ConcurrentDictionary CacheItems = new ConcurrentDictionary();
///
/// Adds an item to the cache.
///
///
/// A unique identifier for the cache entry.
///
///
/// The object to insert.
///
///
/// Optional. An object that contains eviction details for the cache entry. This object
/// provides more options for eviction than a simple absolute expiration. The default value for the optional parameter
/// is null.
///
///
/// Optional. A named region in the cache to which the cache entry can be added,
/// if regions are implemented. The default value for the optional parameter
/// is null.
///
///
/// True if the insertion try succeeds, or false if there is an already an entry
/// in the cache with the same key as key.
///
public static bool AddItem(string key, object value, CacheItemPolicy policy = null, string regionName = null)
{
bool isAdded;
lock (Cache)
{
if (policy == null)
{
// Create a new cache policy with the default values
policy = new CacheItemPolicy();
}
try
{
Cache.Set(key, value, policy, regionName);
isAdded = true;
}
catch
{
isAdded = false;
}
if (isAdded)
{
CacheItems[key] = regionName;
}
}
return isAdded;
}
///
/// Fetches an item matching the given key from the cache.
///
///
/// A unique identifier for the cache entry.
///
///
/// Optional. A named region in the cache to which the cache entry can be added,
/// if regions are implemented. The default value for the optional parameter
/// is null.
///
///
/// The cache entry that is identified by key.
///
public static object GetItem(string key, string regionName = null)
{
lock (Cache)
{
return Cache.Get(key, regionName);
}
}
///
/// Updates an item to the cache.
///
///
/// A unique identifier for the cache entry.
///
///
/// The object to insert.
///
///
/// Optional. An object that contains eviction details for the cache entry. This object
/// provides more options for eviction than a simple absolute expiration. The default value for the optional parameter
/// is null.
///
///
/// Optional. A named region in the cache to which the cache entry can be added,
/// if regions are implemented. The default value for the optional parameter
/// is null.
///
///
/// True if the update try succeeds, or false if there is an already an entry
/// in the cache with the same key as key.
///
public static bool UpdateItem(string key, object value, CacheItemPolicy policy = null, string regionName = null)
{
bool isUpDated = true;
// Remove the item from the cache if it already exists. MemoryCache will
// not add an item with an existing name.
if (GetItem(key, regionName) != null)
{
isUpDated = RemoveItem(key, regionName);
}
if (policy == null)
{
// Create a new cache policy with the default values
policy = new CacheItemPolicy();
}
if (isUpDated)
{
isUpDated = AddItem(key, value, policy, regionName);
}
return isUpDated;
}
///
/// Removes an item matching the given key from the cache.
///
///
/// A unique identifier for the cache entry.
///
///
/// Optional. A named region in the cache to which the cache entry can be added,
/// if regions are implemented. The default value for the optional parameter
/// is null.
///
///
/// True if the removal try succeeds, or false if there is an already an entry
/// in the cache with the same key as key.
///
public static bool RemoveItem(string key, string regionName = null)
{
bool isRemoved;
lock (Cache)
{
isRemoved = Cache.Remove(key, regionName) != null;
if (isRemoved)
{
string removedValue;
CacheItems.TryRemove(key, out removedValue);
}
}
return isRemoved;
}
///
/// Clears the cache.
///
///
/// The region name.
///
///
/// The .
///
public static bool Clear(string regionName = null)
{
bool isCleared = false;
lock (CacheItems)
{
// You can't remove items from a collection whilst you are iterating over it so you need to
// create a collection to store the items to remove.
ConcurrentDictionary tempDictionary = new ConcurrentDictionary();
foreach (KeyValuePair cacheItem in CacheItems)
{
// Does the cached key come with a region.
if ((cacheItem.Value == null) || (cacheItem.Value != null && cacheItem.Value.Equals(regionName, StringComparison.OrdinalIgnoreCase)))
{
isCleared = RemoveItem(cacheItem.Key, cacheItem.Value);
if (isCleared)
{
string key = cacheItem.Key;
string value = cacheItem.Value;
tempDictionary.AddOrUpdate(key, value, (oldkey, oldValue) => value);
}
}
}
if (isCleared)
{
// Loop through and clear out the dictionary of cache keys.
foreach (KeyValuePair cacheItem in tempDictionary)
{
string removedValue;
CacheItems.TryRemove(cacheItem.Key, out removedValue);
}
}
}
return isCleared;
}
}
}