From 9ace78ed58fa051c2b2a6b010027d3de3382fac5 Mon Sep 17 00:00:00 2001 From: JimBobSquarePants Date: Wed, 13 Mar 2013 01:35:57 +0000 Subject: [PATCH] new caching system using SQLite Former-commit-id: c9a426196af89eb6f303b13c1f025b04333dcbf3 --- .../ImageProcessor.Tests.csproj | 101 ++++++++ .../Properties/AssemblyInfo.cs | 36 +++ src/ImageProcessor.Tests/UnitTest1.cs | 18 ++ src/ImageProcessor.Web/Caching/CachedImage.cs | 39 ++-- src/ImageProcessor.Web/Caching/DiskCache.cs | 82 +++++-- .../Caching/LockedDictionary.cs | 2 +- .../Caching/PersistantDictionary.cs | 107 ++++----- src/ImageProcessor.Web/Caching/SQLContext.cs | 216 ++++++++++++++++++ .../HttpModules/ImageProcessingModule.cs | 28 +-- .../ImageProcessor.Web.csproj | 40 +++- src/ImageProcessor.Web/packages.config | 4 + src/ImageProcessor.sln | 37 ++- src/ImageProcessor/ImageProcessor.csproj | 31 +++ src/Test/Test/Controllers/HomeController.cs | 32 +++ src/Test/Test/Test.csproj | 30 +++ src/Test/Test/Views/Home/Speed.cshtml | 20 ++ src/Test/Test/Web.config | 2 +- ...a.SQLite.x86.1.0.84.0.nupkg.REMOVED.git-id | 1 + .../System.Data.SQLite.x86.1.0.84.0.nuspec | 23 ++ ...System.Data.SQLite.Linq.dll.REMOVED.git-id | 1 + .../System.Data.SQLite.dll.REMOVED.git-id | 1 + ...System.Data.SQLite.Linq.dll.REMOVED.git-id | 1 + .../System.Data.SQLite.dll.REMOVED.git-id | 1 + ...System.Data.SQLite.Linq.dll.REMOVED.git-id | 1 + .../System.Data.SQLite.dll.REMOVED.git-id | 1 + src/packages/repositories.config | 4 + 26 files changed, 733 insertions(+), 126 deletions(-) create mode 100644 src/ImageProcessor.Tests/ImageProcessor.Tests.csproj create mode 100644 src/ImageProcessor.Tests/Properties/AssemblyInfo.cs create mode 100644 src/ImageProcessor.Tests/UnitTest1.cs create mode 100644 src/ImageProcessor.Web/Caching/SQLContext.cs create mode 100644 src/ImageProcessor.Web/packages.config create mode 100644 src/Test/Test/Views/Home/Speed.cshtml create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/System.Data.SQLite.x86.1.0.84.0.nupkg.REMOVED.git-id create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/System.Data.SQLite.x86.1.0.84.0.nuspec create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/lib/net20/System.Data.SQLite.Linq.dll.REMOVED.git-id create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/lib/net20/System.Data.SQLite.dll.REMOVED.git-id create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/lib/net40/System.Data.SQLite.Linq.dll.REMOVED.git-id create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/lib/net40/System.Data.SQLite.dll.REMOVED.git-id create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/lib/net45/System.Data.SQLite.Linq.dll.REMOVED.git-id create mode 100644 src/packages/System.Data.SQLite.x86.1.0.84.0/lib/net45/System.Data.SQLite.dll.REMOVED.git-id create mode 100644 src/packages/repositories.config diff --git a/src/ImageProcessor.Tests/ImageProcessor.Tests.csproj b/src/ImageProcessor.Tests/ImageProcessor.Tests.csproj new file mode 100644 index 000000000..00cf73739 --- /dev/null +++ b/src/ImageProcessor.Tests/ImageProcessor.Tests.csproj @@ -0,0 +1,101 @@ + + + + Debug + AnyCPU + {39911A38-CA06-413C-80AA-39EF60CE984F} + Library + Properties + ImageProcessor.Tests + ImageProcessor.Tests + v4.5 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file diff --git a/src/ImageProcessor.Tests/Properties/AssemblyInfo.cs b/src/ImageProcessor.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..e2341f344 --- /dev/null +++ b/src/ImageProcessor.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ImageProcessor.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ImageProcessor.Tests")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ab617b65-7259-4dc5-9dad-81a7c6537a4f")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/ImageProcessor.Tests/UnitTest1.cs b/src/ImageProcessor.Tests/UnitTest1.cs new file mode 100644 index 000000000..f8dfa7ad7 --- /dev/null +++ b/src/ImageProcessor.Tests/UnitTest1.cs @@ -0,0 +1,18 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ImageProcessor.Tests +{ + using System.IO; + + [TestClass] + public class UnitTest1 + { + [TestMethod] + public void TestMethod1() + { + + + } + } +} diff --git a/src/ImageProcessor.Web/Caching/CachedImage.cs b/src/ImageProcessor.Web/Caching/CachedImage.cs index 500331d55..2757e830e 100644 --- a/src/ImageProcessor.Web/Caching/CachedImage.cs +++ b/src/ImageProcessor.Web/Caching/CachedImage.cs @@ -14,53 +14,40 @@ namespace ImageProcessor.Web.Caching /// /// Describes a cached image /// - public class CachedImage + internal sealed class CachedImage { /// /// Initializes a new instance of the class. /// - /// + /// /// The value of the cached item. /// /// /// The last write time of the cached item. /// - public CachedImage(string value, DateTime lastWriteTimeUtc) + /// + /// The expires time. + /// + public CachedImage(string path, DateTime lastWriteTimeUtc, DateTime expiresTimeUtc) { - this.Value = value; + this.Path = path; this.LastWriteTimeUtc = lastWriteTimeUtc; + this.ExpiresUtc = expiresTimeUtc; } /// - /// Gets the value date time delimiter. - /// - public static string ValueLastWriteTimeDelimiter - { - get - { - return "|*|"; - } - } - - /// - /// Gets or sets the value of the cached item + /// Gets or sets the value of the cached image /// - public string Value { get; set; } + public string Path { get; set; } /// - /// Gets or sets the last write time of the cached item + /// Gets or sets the last write time of the cached image /// public DateTime LastWriteTimeUtc { get; set; } /// - /// The value and last write time as a string. + /// Gets or sets when the cached image should expire from the cache. /// - /// - /// The . - /// - public string ValueAndLastWriteTimeUtcToString() - { - return string.Format("{0}{1}{2}", this.Value, ValueLastWriteTimeDelimiter, this.LastWriteTimeUtc); - } + public DateTime ExpiresUtc { get; set; } } } diff --git a/src/ImageProcessor.Web/Caching/DiskCache.cs b/src/ImageProcessor.Web/Caching/DiskCache.cs index b5f828825..0d2ca67ea 100644 --- a/src/ImageProcessor.Web/Caching/DiskCache.cs +++ b/src/ImageProcessor.Web/Caching/DiskCache.cs @@ -19,7 +19,6 @@ namespace ImageProcessor.Web.Caching using System.Web.Hosting; using ImageProcessor.Helpers.Extensions; using ImageProcessor.Web.Config; - using ImageProcessor.Web.Helpers; #endregion /// @@ -111,6 +110,23 @@ namespace ImageProcessor.Web.Caching return cachedPath; } + /// + /// Adds an image to the cache. + /// + /// + /// The cached path. + /// + /// + /// The last write time. + /// + internal static void AddImageToCache(string cachedPath, DateTime lastWriteTimeUtc) + { + string key = Path.GetFileNameWithoutExtension(cachedPath); + DateTime expires = lastWriteTimeUtc.AddDays(MaxFileCachedDuration).ToUniversalTime(); + CachedImage cachedImage = new CachedImage(key, lastWriteTimeUtc, expires); + PersistantDictionary.Instance.Add(key, cachedImage); + } + /// /// Converts an absolute file path /// @@ -155,12 +171,14 @@ namespace ImageProcessor.Web.Caching /// internal static bool IsUpdatedFile(string imagePath, string cachedImagePath) { - if (File.Exists(imagePath) && File.Exists(cachedImagePath)) + if (File.Exists(imagePath)) { + CachedImage image; + string key = Path.GetFileNameWithoutExtension(cachedImagePath); + PersistantDictionary.Instance.TryGetValue(key, out image); FileInfo imageFileInfo = new FileInfo(imagePath); - FileInfo cachedImageFileInfo = new FileInfo(cachedImagePath); - return !new FileCompareLastwritetime().Equals(imageFileInfo, cachedImageFileInfo); + return image != null && imageFileInfo.LastWriteTimeUtc.Equals(image.LastWriteTimeUtc); } return true; @@ -169,18 +187,28 @@ namespace ImageProcessor.Web.Caching /// /// Sets the LastWriteTime of the cached file to match the original file. /// - /// The original image path. - /// The cached image path. - internal static void SetCachedLastWriteTime(string imagePath, string cachedImagePath) + /// + /// The original image path. + /// + /// + /// The cached image path. + /// + /// + /// The set to the last write time of the file. + /// + internal static DateTime SetCachedLastWriteTime(string imagePath, string cachedImagePath) { - if (File.Exists(imagePath) && File.Exists(cachedImagePath)) + lock (SyncRoot) { - lock (SyncRoot) + if (File.Exists(imagePath) && File.Exists(cachedImagePath)) { DateTime dateTime = File.GetLastWriteTimeUtc(imagePath); File.SetLastWriteTimeUtc(cachedImagePath, dateTime); + return dateTime; } } + + return DateTime.MinValue; } /// @@ -188,6 +216,24 @@ namespace ImageProcessor.Web.Caching /// private static void PurgeFolders() { + Regex searchTerm = new Regex(@"(jpeg|png|bmp|gif)"); + var list = PersistantDictionary.Instance.ToList() + .GroupBy(x => searchTerm.Match(x.Value.Path)) + .Select(y => new + { + Path = y.Key, + Expires = y.Select(z => z.Value.ExpiresUtc), + Count = y.Sum(z => z.Key.Count()) + }) + .AsEnumerable(); + + foreach (var path in list) + { + + } + + + string folder = HostingEnvironment.MapPath(CachePath); if (folder != null) @@ -197,7 +243,7 @@ namespace ImageProcessor.Web.Caching if (directoryInfo.Exists) { List directoryInfos = directoryInfo - .EnumerateDirectories("*", SearchOption.AllDirectories) + .EnumerateDirectories("*", SearchOption.TopDirectoryOnly) .ToList(); Parallel.ForEach( @@ -205,7 +251,7 @@ namespace ImageProcessor.Web.Caching subDirectoryInfo => { // Get all the files in the cache ordered by LastAccessTime - oldest first. - List fileInfos = subDirectoryInfo.EnumerateFiles("*", SearchOption.AllDirectories) + List fileInfos = subDirectoryInfo.EnumerateFiles("*", SearchOption.TopDirectoryOnly) .OrderBy(x => x.LastAccessTimeUtc).ToList(); int counter = fileInfos.Count; @@ -221,8 +267,18 @@ namespace ImageProcessor.Web.Caching { try { - fileInfo.Delete(); - counter -= 1; + // Remove from the cache. + string key = Path.GetFileNameWithoutExtension(fileInfo.Name); + CachedImage cachedImage; + + if (PersistantDictionary.Instance.TryGetValue(key, out cachedImage)) + { + if (PersistantDictionary.Instance.TryRemove(key, out cachedImage)) + { + fileInfo.Delete(); + counter -= 1; + } + } } catch (IOException) { diff --git a/src/ImageProcessor.Web/Caching/LockedDictionary.cs b/src/ImageProcessor.Web/Caching/LockedDictionary.cs index de8e214a3..d09f62548 100644 --- a/src/ImageProcessor.Web/Caching/LockedDictionary.cs +++ b/src/ImageProcessor.Web/Caching/LockedDictionary.cs @@ -21,7 +21,7 @@ namespace ImageProcessor.Web.Caching /// /// The type of the values in the dictionary. /// - public class LockedDictionary : IDictionary + internal class LockedDictionary : IDictionary { /// /// The _inner. diff --git a/src/ImageProcessor.Web/Caching/PersistantDictionary.cs b/src/ImageProcessor.Web/Caching/PersistantDictionary.cs index 4f0f1f134..1bf33387b 100644 --- a/src/ImageProcessor.Web/Caching/PersistantDictionary.cs +++ b/src/ImageProcessor.Web/Caching/PersistantDictionary.cs @@ -9,16 +9,15 @@ namespace ImageProcessor.Web.Caching { #region Using using System; - using System.IO; - using System.Web.Hosting; - using ImageProcessor.Web.Config; + using System.Collections.Generic; #endregion /// /// Represents a collection of keys and values whose operations are concurrent. /// - public class PersistantDictionary : LockedDictionary + internal sealed class PersistantDictionary : LockedDictionary { + #region Fields /// /// A new instance Initializes a new instance of the class. /// initialized lazily. @@ -26,20 +25,11 @@ namespace ImageProcessor.Web.Caching private static readonly Lazy Lazy = new Lazy(() => new PersistantDictionary()); - /// - /// The default path for cached folders on the server. - /// - private static readonly string CachePath = ImageProcessorConfig.Instance.VirtualCachePath; - /// /// The object to lock against. /// private static readonly object SyncRoot = new object(); - - /// - /// The cached index location. - /// - private readonly string cachedIndexFile = Path.Combine(HostingEnvironment.MapPath(CachePath), "imagecache.bin"); + #endregion #region Constructors /// @@ -92,7 +82,7 @@ namespace ImageProcessor.Web.Caching value = this[key]; this.Remove(key); - this.SaveCache(); + this.SaveCache(key, value, true); return true; } @@ -104,29 +94,23 @@ namespace ImageProcessor.Web.Caching /// /// The key. /// - /// - /// The delegate method that returns the value. + /// + /// The cached image to add. /// /// /// The value of the item to add or get. /// - public CachedImage GetOrAdd(string key, Func factory) + public new CachedImage Add(string key, CachedImage cachedImage) { - // Get the CachedImage. - if (this.ContainsKey(key)) - { - return this[key]; - } - lock (SyncRoot) { // Add the CachedImage. - CachedImage ret = factory(key); - this[key] = ret; - - this.SaveCache(); + if (this.SaveCache(key, cachedImage, false)) + { + this[key] = cachedImage; + } - return ret; + return cachedImage; } } #endregion @@ -134,22 +118,32 @@ namespace ImageProcessor.Web.Caching /// /// Saves the in memory cache to the file-system. /// - private void SaveCache() + /// + /// The key. + /// + /// + /// The cached Image. + /// + /// + /// The remove. + /// + /// + /// true, if the dictionary is saved to the file-system; otherwise, false. + /// + private bool SaveCache(string key, CachedImage cachedImage, bool remove) { - using (FileStream fileStream = File.Create(this.cachedIndexFile)) + try { - using (BinaryWriter binaryWriter = new BinaryWriter(fileStream)) + if (remove) { - // Put the count. - binaryWriter.Write(this.Count); - - // Put the values. - foreach (var pair in this) - { - binaryWriter.Write(pair.Key); - binaryWriter.Write(pair.Value.ValueAndLastWriteTimeUtcToString()); - } + return SQLContext.RemoveImage(key); } + + return SQLContext.AddImage(key, cachedImage); + } + catch (Exception) + { + return false; } } @@ -160,32 +154,13 @@ namespace ImageProcessor.Web.Caching { lock (SyncRoot) { - if (File.Exists(this.cachedIndexFile)) + SQLContext.CreateDatabase(); + + Dictionary dictionary = SQLContext.GetImages(); + + foreach (KeyValuePair pair in dictionary) { - using (FileStream fileStream = File.OpenRead(this.cachedIndexFile)) - { - using (BinaryReader binaryReader = new BinaryReader(fileStream)) - { - // Get the count. - int count = binaryReader.ReadInt32(); - - // Read in all pairs. - for (int i = 0; i < count; i++) - { - // Read the key/value strings - string key = binaryReader.ReadString(); - string value = binaryReader.ReadString(); - - // Create a CachedImage - string[] valueAndLastWriteTime = value.Split(new[] { CachedImage.ValueLastWriteTimeDelimiter }, StringSplitOptions.None); - DateTime lastWriteTime = DateTime.Parse(valueAndLastWriteTime[1]); - CachedImage cachedImage = new CachedImage(valueAndLastWriteTime[0], lastWriteTime); - - // Assign the value - this[key] = cachedImage; - } - } - } + this.Add(pair); } } } diff --git a/src/ImageProcessor.Web/Caching/SQLContext.cs b/src/ImageProcessor.Web/Caching/SQLContext.cs new file mode 100644 index 000000000..af8e4c5aa --- /dev/null +++ b/src/ImageProcessor.Web/Caching/SQLContext.cs @@ -0,0 +1,216 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) James South. +// Dual licensed under the MIT or GPL Version 2 licenses. +// +// ----------------------------------------------------------------------- + +namespace ImageProcessor.Web.Caching +{ + #region Using + using System; + using System.Collections.Generic; + using System.Data.SQLite; + using System.IO; + using System.Web.Hosting; + using ImageProcessor.Web.Config; + #endregion + + /// + /// Provides a wrapper for the SQLite functionality. + /// + internal sealed class SQLContext + { + /// + /// The default path for cached folders on the server. + /// + private static readonly string VirtualCachePath = ImageProcessorConfig.Instance.VirtualCachePath; + + /// + /// The cached index location. + /// + private static readonly string IndexLocation = Path.Combine(HostingEnvironment.MapPath(VirtualCachePath), "imagecache.sqlite"); + + /// + /// The connection string. + /// + private static readonly string ConnectionString = string.Format("Data Source={0};Version=3;", IndexLocation); + + /// + /// Creates the database if it doesn't already exist. + /// + public static void CreateDatabase() + { + if (!File.Exists(IndexLocation)) + { + string absolutePath = HostingEnvironment.MapPath(VirtualCachePath); + + if (absolutePath != null) + { + DirectoryInfo directoryInfo = new DirectoryInfo(absolutePath); + + if (!directoryInfo.Exists) + { + // Create the directory. + Directory.CreateDirectory(absolutePath); + } + } + + SQLiteConnection.CreateFile(IndexLocation); + + using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) + { + connection.Open(); + + using (SQLiteTransaction transaction = connection.BeginTransaction()) + { + using (SQLiteCommand command = new SQLiteCommand(connection)) + { + command.CommandText = @"CREATE TABLE names + (Key TEXT, + Path TEXT, + LastWriteTimeUtc TEXT, + ExpiresUtc TEXT, + PRIMARY KEY (Key), + UNIQUE (Value));"; + + command.ExecuteNonQuery(); + } + + transaction.Commit(); + } + } + } + } + + /// + /// Adds a cached image to the database. + /// + /// + /// The key for the cached image. + /// + /// + /// The cached image to add. + /// + /// + /// The true if the addition of the cached image is added; otherwise, false. + /// + public static bool AddImage(string key, CachedImage image) + { + try + { + using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) + { + connection.Open(); + + using (SQLiteTransaction transaction = connection.BeginTransaction()) + { + using (SQLiteCommand command = new SQLiteCommand(connection)) + { + command.CommandText = "INSERT INTO names VALUES(?, ?, ?, ?)"; + + SQLiteParameter[] parameters = new[] + { + new SQLiteParameter("Key", key), + new SQLiteParameter("Path", image.Path), + new SQLiteParameter("LastWriteTimeUtc", image.LastWriteTimeUtc), + new SQLiteParameter("ExpiresUtc", image.ExpiresUtc) + }; + + command.Parameters.AddRange(parameters); + command.ExecuteNonQuery(); + } + + transaction.Commit(); + } + } + + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Removes a cached image from the database. + /// + /// + /// The key for the cached image. + /// + /// + /// The true if the addition of the cached image is removed; otherwise, false. + /// + public static bool RemoveImage(string key) + { + try + { + using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) + { + connection.Open(); + + using (SQLiteTransaction transaction = connection.BeginTransaction()) + { + using (SQLiteCommand command = new SQLiteCommand(connection)) + { + command.CommandText = string.Format("DELETE FROM names WHERE key = '{0}';", key); + command.ExecuteNonQuery(); + } + + transaction.Commit(); + } + } + + return true; + } + catch (Exception) + { + return false; + } + } + + /// + /// Gets all the images from the database. + /// + /// + /// The . + /// + public static Dictionary GetImages() + { + Dictionary dictionary = new Dictionary(); + + try + { + using (SQLiteConnection connection = new SQLiteConnection(ConnectionString)) + { + connection.Open(); + + using (SQLiteCommand command = new SQLiteCommand(connection)) + { + command.CommandText = "SELECT * FROM names;"; + + SQLiteDataReader reader = command.ExecuteReader(); + + while (reader.Read()) + { + string key = reader["Key"].ToString(); + CachedImage image = new CachedImage( + reader["Path"].ToString(), + DateTime.Parse(reader["LastWriteTimeUtc"].ToString()).ToUniversalTime(), + DateTime.Parse(reader["LastWriteTimeUtc"].ToString()).ToUniversalTime()); + + dictionary.Add(key, image); + } + } + } + + return dictionary; + } + catch (Exception) + { + return new Dictionary(); + } + } + } +} diff --git a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs index 0cac04a94..1bc4a98d6 100644 --- a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs @@ -27,14 +27,14 @@ namespace ImageProcessor.Web.HttpModules { #region Fields /// - /// The value to prefix any remote image requests with to ensure they get captured. + /// The key for storing the response type of the current image. /// - private static readonly string RemotePrefix = ImageProcessorConfig.Instance.RemotePrefix; + private const string CachedResponseTypeKey = "CACHED_IMAGE_RESPONSE_TYPE"; /// - /// The key for storing the response type of the current image. + /// The value to prefix any remote image requests with to ensure they get captured. /// - private const string CachedResponseTypeKey = "CACHED_IMAGE_RESPONSE_TYPE"; + private static readonly string RemotePrefix = ImageProcessorConfig.Instance.RemotePrefix; /// /// Whether this is the first run of the handler. @@ -153,16 +153,7 @@ namespace ImageProcessor.Web.HttpModules } else { - try - { - imageFactory.Load(fullPath).AutoProcess().Save(cachedPath); - } - catch (Exception ex) - { - - throw ex; - } - + imageFactory.Load(fullPath).AutoProcess().Save(cachedPath); } } @@ -170,7 +161,10 @@ namespace ImageProcessor.Web.HttpModules cachedImageCounter += 1; // Ensure that the LastWriteTime property of the source and cached file match. - DiskCache.SetCachedLastWriteTime(path, cachedPath); + DateTime dateTime = DiskCache.SetCachedLastWriteTime(path, cachedPath); + + // Add to the cache. + DiskCache.AddImageToCache(cachedPath, dateTime); } context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(imageName).ToDescription(); @@ -180,7 +174,7 @@ namespace ImageProcessor.Web.HttpModules // If the number of cached imaged hits the maximum allowed for this session then we clear // the cache again and reset the counter. - // TODO: There is a potential concurrency issue here but collision probability is very low# + // TODO: There is a potential concurrency issue here but collision probability is very low // it would be nice to nail it though. if (cachedImageCounter >= DiskCache.MaxRunsBeforeCacheClear) { @@ -192,7 +186,7 @@ namespace ImageProcessor.Web.HttpModules } /// - /// Occurs just before ASP.NET send Httpheaders to the client. + /// Occurs just before ASP.NET send HttpHeaders to the client. /// /// The source of the event. /// An EventArgs that contains the event data. diff --git a/src/ImageProcessor.Web/ImageProcessor.Web.csproj b/src/ImageProcessor.Web/ImageProcessor.Web.csproj index 0ef489007..808943ab4 100644 --- a/src/ImageProcessor.Web/ImageProcessor.Web.csproj +++ b/src/ImageProcessor.Web/ImageProcessor.Web.csproj @@ -38,10 +38,45 @@ AnyCPU prompt + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + true + bin\x86\All\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + False + ..\packages\System.Data.SQLite.x86.1.0.84.0\lib\net40\System.Data.SQLite.dll + + + False + ..\packages\System.Data.SQLite.x86.1.0.84.0\lib\net40\System.Data.SQLite.Linq.dll + @@ -55,6 +90,7 @@ + @@ -71,7 +107,9 @@ ImageProcessor - + + +