📷 A modern, cross-platform, 2D Graphics library for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

159 lines
4.8 KiB

// -----------------------------------------------------------------------
// <copyright file="PersistantDictionary.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// -----------------------------------------------------------------------
namespace ImageProcessor.Web.Caching
{
#region Using
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ImageProcessor.Web.Helpers;
#endregion
/// <summary>
/// Represents a collection of keys and values whose operations are concurrent.
/// </summary>
internal sealed class PersistantDictionary : LockedDictionary<string, CachedImage>
{
#region Fields
/// <summary>
/// A new instance Initializes a new instance of the <see cref="T:ImageProcessor.Web.Caching.PersistantDictionary"/> class.
/// initialized lazily.
/// </summary>
private static readonly Lazy<PersistantDictionary> Lazy =
new Lazy<PersistantDictionary>(() => new PersistantDictionary());
/// <summary>
/// The object to lock against.
/// </summary>
private static readonly object SyncRoot = new object();
#endregion
#region Constructors
/// <summary>
/// Prevents a default instance of the <see cref="T:ImageProcessor.Web.Caching.PersistantDictionary"/> class
/// from being created.
/// </summary>
private PersistantDictionary()
{
this.LoadCache();
}
#endregion
/// <summary>
/// Gets the current instance of the <see cref="T:ImageProcessor.Web.Caching.PersistantDictionary"/> class.
/// </summary>
public static PersistantDictionary Instance
{
get
{
return Lazy.Value;
}
}
#region Public
/// <summary>
/// Tries to remove the value associated with the specified key.
/// </summary>
/// <param name="key">
/// The key of the item to remove.
/// </param>
/// <returns>
/// true if the <see cref="PersistantDictionary"/> removes an element with
/// the specified key; otherwise, false.
/// </returns>
public async Task<bool> TryRemoveAsync(string key)
{
// No CachedImage to remove.
if (!this.ContainsKey(key))
{
return false;
}
// Remove the CachedImage.
CachedImage value = this[key];
this.Remove(key);
await this.SaveCacheAsync(key, value, true);
return true;
}
/// <summary>
/// Adds the specified key and value to the dictionary or returns the value if it exists.
/// </summary>
/// <param name="key">
/// The key.
/// </param>
/// <param name="cachedImage">
/// The cached image to add.
/// </param>
/// <returns>
/// The value of the item to add or get.
/// </returns>
public async Task<CachedImage> AddAsync(string key, CachedImage cachedImage)
{
// Add the CachedImage.
if (await this.SaveCacheAsync(key, cachedImage, false))
{
this.Add(key, cachedImage);
}
return cachedImage;
}
#endregion
/// <summary>
/// Saves the in memory cache to the file-system.
/// </summary>
/// <param name="key">
/// The key.
/// </param>
/// <param name="cachedImage">
/// The cached Image.
/// </param>
/// <param name="remove">
/// The remove.
/// </param>
/// <returns>
/// true, if the dictionary is saved to the file-system; otherwise, false.
/// </returns>
private async Task<bool> SaveCacheAsync(string key, CachedImage cachedImage, bool remove)
{
try
{
if (remove)
{
return await SQLContext.RemoveImageAsync(key);
}
return await SQLContext.AddImageAsync(cachedImage);
}
catch
{
return false;
}
}
/// <summary>
/// Loads the cache file to populate the in memory cache.
/// </summary>
private void LoadCache()
{
lock (SyncRoot)
{
SQLContext.CreateDatabase();
Dictionary<string, CachedImage> dictionary = SQLContext.GetImages();
foreach (KeyValuePair<string, CachedImage> pair in dictionary)
{
this.Add(pair);
}
}
}
}
}