Browse Source

Enhancing DiskCache to handle 24,000 files

Former-commit-id: bb3d1ded41e10fff13d46fa9009a838c2bd958f0
pull/17/head
JimBobSquarePants 14 years ago
parent
commit
bc6e298074
  1. 49
      src/ImageProcessor.Web/Caching/DiskCache.cs
  2. 2
      src/ImageProcessor.Web/Config/ImageProcessorConfig.cs
  3. 6
      src/ImageProcessor.Web/Helpers/FileCompareLastwritetime.cs
  4. 18
      src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
  5. 5
      src/ImageProcessor.Web/ImageFactoryExtensions.cs
  6. 2
      src/Test/Test/Web.config

49
src/ImageProcessor.Web/Caching/DiskCache.cs

@ -84,22 +84,28 @@ namespace ImageProcessor.Web.Caching
if (absoluteCachePath != null) if (absoluteCachePath != null)
{ {
DirectoryInfo di = new DirectoryInfo(absoluteCachePath);
if (!di.Exists)
{
// Create the directory.
Directory.CreateDirectory(absoluteCachePath);
}
string parsedExtension = ParseExtension(imagePath); string parsedExtension = ParseExtension(imagePath);
string fallbackExtension = imageName.Substring(imageName.LastIndexOf(".", StringComparison.Ordinal)); string fallbackExtension = imageName.Substring(imageName.LastIndexOf(".", StringComparison.Ordinal) + 1);
string subpath = !string.IsNullOrWhiteSpace(parsedExtension) ? parsedExtension : fallbackExtension;
string cachedFileName = string.Format( string cachedFileName = string.Format(
"{0}{1}", "{0}.{1}",
imagePath.ToMD5Fingerprint(), imagePath.ToMD5Fingerprint(),
!string.IsNullOrWhiteSpace(parsedExtension) ? parsedExtension : fallbackExtension); !string.IsNullOrWhiteSpace(parsedExtension) ? parsedExtension : fallbackExtension);
cachedPath = Path.Combine(absoluteCachePath, cachedFileName); cachedPath = Path.Combine(absoluteCachePath, subpath, cachedFileName);
string cachedDirectory = Path.GetDirectoryName(cachedPath);
if (cachedDirectory != null)
{
DirectoryInfo directoryInfo = new DirectoryInfo(cachedDirectory);
if (!directoryInfo.Exists)
{
// Create the directory.
Directory.CreateDirectory(cachedDirectory);
}
}
} }
return cachedPath; return cachedPath;
@ -189,9 +195,17 @@ namespace ImageProcessor.Web.Caching
DirectoryInfo directoryInfo = new DirectoryInfo(folder); DirectoryInfo directoryInfo = new DirectoryInfo(folder);
if (directoryInfo.Exists) if (directoryInfo.Exists)
{
List<DirectoryInfo> directoryInfos = directoryInfo
.EnumerateDirectories("*", SearchOption.AllDirectories)
.ToList();
Parallel.ForEach(
directoryInfos,
dir =>
{ {
// Get all the files in the cache ordered by LastAccessTime - oldest first. // Get all the files in the cache ordered by LastAccessTime - oldest first.
List<FileInfo> fileInfos = directoryInfo.EnumerateFiles("*", SearchOption.AllDirectories) List<FileInfo> fileInfos = dir.EnumerateFiles("*", SearchOption.AllDirectories)
.OrderBy(x => x.LastAccessTime).ToList(); .OrderBy(x => x.LastAccessTime).ToList();
int counter = fileInfos.Count; int counter = fileInfos.Count;
@ -205,19 +219,20 @@ namespace ImageProcessor.Web.Caching
try try
{ {
// Delete the file if we are nearing our limit buffer. // Delete the file if we are nearing our limit buffer.
if (counter >= MaxFilesCount || fileInfo.LastAccessTime < DateTime.Now.AddDays(-MaxFileCachedDuration)) if (counter >= MaxFilesCount && fileInfo.LastAccessTime.ToUniversalTime() < DateTime.UtcNow.AddHours(1)
|| fileInfo.LastAccessTime.ToUniversalTime() < DateTime.UtcNow.AddDays(-MaxFileCachedDuration))
{ {
fileInfo.Delete(); fileInfo.Delete();
counter -= 1; counter -= 1;
} }
} }
catch catch (IOException)
{ {
// TODO: Sort out the try/catch. // Do Nothing, skip to the next.
throw;
} }
} }
}); });
});
} }
} }
} }
@ -237,7 +252,7 @@ namespace ImageProcessor.Web.Caching
{ {
if (match.Success) if (match.Success)
{ {
return "." + match.Value.Split('=')[1]; return match.Value.Split('=')[1];
} }
} }

2
src/ImageProcessor.Web/Config/ImageProcessorConfig.cs

@ -76,7 +76,7 @@ namespace ImageProcessor.Web.Config
/// <summary> /// <summary>
/// Gets the list of available GraphicsProcessors. /// Gets the list of available GraphicsProcessors.
/// </summary> /// </summary>
public List<IGraphicsProcessor> GraphicsProcessors { get; private set; } public IList<IGraphicsProcessor> GraphicsProcessors { get; private set; }
#region Caching #region Caching
/// <summary> /// <summary>

6
src/ImageProcessor.Web/Helpers/FileCompareLastwritetime.cs

@ -28,7 +28,7 @@ namespace ImageProcessor.Web.Helpers
/// </returns> /// </returns>
public static DateTime ToMinute(DateTime value) public static DateTime ToMinute(DateTime value)
{ {
return new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, 0, value.Kind); return new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, 0, value.Kind).ToUniversalTime();
} }
/// <summary> /// <summary>
@ -43,7 +43,7 @@ namespace ImageProcessor.Web.Helpers
/// <returns>true if the specified objects are equal; otherwise, false.</returns> /// <returns>true if the specified objects are equal; otherwise, false.</returns>
public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2) public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
{ {
return ToMinute(f1.LastWriteTime) == ToMinute(f2.LastWriteTime); return ToMinute(f1.LastWriteTime.ToUniversalTime()) == ToMinute(f2.LastWriteTime.ToUniversalTime());
} }
/// <summary> /// <summary>
@ -53,7 +53,7 @@ namespace ImageProcessor.Web.Helpers
/// <returns>A hash code for the specified <see cref="T:System.IO.FileInfo"/>.</returns> /// <returns>A hash code for the specified <see cref="T:System.IO.FileInfo"/>.</returns>
public int GetHashCode(System.IO.FileInfo fi) public int GetHashCode(System.IO.FileInfo fi)
{ {
return ToMinute(fi.LastWriteTime).GetHashCode(); return ToMinute(fi.LastWriteTime.ToUniversalTime()).GetHashCode();
} }
} }
} }

18
src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs

@ -78,13 +78,17 @@ namespace ImageProcessor.Web.HttpModules
// Is this a remote file. // Is this a remote file.
bool isRemote = context.Request.Path.Equals(RemotePrefix, StringComparison.OrdinalIgnoreCase); bool isRemote = context.Request.Path.Equals(RemotePrefix, StringComparison.OrdinalIgnoreCase);
string path; string path = string.Empty;
string queryString = string.Empty; string queryString = string.Empty;
if (isRemote) if (isRemote)
{ {
// We need to split the querystring to get the actual values we want. // We need to split the querystring to get the actual values we want.
string[] paths = HttpUtility.UrlDecode(context.Request.QueryString.ToString()).Split('?'); string urlDecode = HttpUtility.UrlDecode(context.Request.QueryString.ToString());
if (urlDecode != null)
{
string[] paths = urlDecode.Split('?');
path = paths[0]; path = paths[0];
@ -93,6 +97,7 @@ namespace ImageProcessor.Web.HttpModules
queryString = paths[1]; queryString = paths[1];
} }
} }
}
else else
{ {
path = HostingEnvironment.MapPath(context.Request.Path); path = HostingEnvironment.MapPath(context.Request.Path);
@ -147,9 +152,18 @@ namespace ImageProcessor.Web.HttpModules
} }
} }
else else
{
try
{ {
imageFactory.Load(fullPath).AutoProcess().Save(cachedPath); imageFactory.Load(fullPath).AutoProcess().Save(cachedPath);
} }
catch (Exception ex)
{
throw ex;
}
}
} }
// Add 1 to the counter // Add 1 to the counter

5
src/ImageProcessor.Web/ImageFactoryExtensions.cs

@ -8,15 +8,10 @@
namespace ImageProcessor.Web namespace ImageProcessor.Web
{ {
#region Using #region Using
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using ImageProcessor.Processors; using ImageProcessor.Processors;
using ImageProcessor.Web.Config; using ImageProcessor.Web.Config;
using ImageProcessor.Web.Helpers;
#endregion #endregion
/// <summary> /// <summary>

2
src/Test/Test/Web.config

@ -72,7 +72,7 @@
<add url="http://images.mymovies.net"/> <add url="http://images.mymovies.net"/>
</whiteList> </whiteList>
</security> </security>
<cache virtualPath="~/cache" maxDays="365" /> <cache virtualPath="~/cache" maxDays="28" />
<processing> <processing>
<plugins> <plugins>
<plugin name ="Resize"> <plugin name ="Resize">

Loading…
Cancel
Save