Browse Source

cache updates

Former-commit-id: 568501d80eb07e3dcbfafa603c1e3bc448291e1b
af/merge-core
James South 13 years ago
parent
commit
5e8a13b2bf
  1. 31
      src/ImageProcessor.Web/Caching/DiskCache.cs
  2. 4
      src/ImageProcessor.Web/Helpers/FileCompareLastwritetime.cs
  3. 16
      src/ImageProcessor.Web/Helpers/ObjectFactory.cs
  4. 38
      src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs
  5. 4
      src/ImageProcessor.Web/ImageFactoryExtensions.cs
  6. 2
      src/ImageProcessor.Web/ImageProcessor.Web.csproj

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

@ -51,7 +51,7 @@ namespace ImageProcessor.Web.Caching
/// NTFS Folder can handle up to 8000 files in a directory.
/// This buffer will help us to ensure that we rarely hit anywhere near that limit.
/// </remarks>
private const int MaxFilesCount = 6000;
private const int MaxFilesCount = 6500;
/// <summary>
/// The regular expression to search strings for extension changes.
@ -177,8 +177,8 @@ namespace ImageProcessor.Web.Caching
{
lock (SyncRoot)
{
DateTime dateTime = File.GetLastWriteTime(imagePath);
File.SetLastWriteTime(cachedImagePath, dateTime);
DateTime dateTime = File.GetLastWriteTimeUtc(imagePath);
File.SetLastWriteTimeUtc(cachedImagePath, dateTime);
}
}
}
@ -202,11 +202,11 @@ namespace ImageProcessor.Web.Caching
Parallel.ForEach(
directoryInfos,
dir =>
subDirectoryInfo =>
{
// Get all the files in the cache ordered by LastAccessTime - oldest first.
List<FileInfo> fileInfos = dir.EnumerateFiles("*", SearchOption.AllDirectories)
.OrderBy(x => x.LastAccessTime).ToList();
List<FileInfo> fileInfos = subDirectoryInfo.EnumerateFiles("*", SearchOption.AllDirectories)
.OrderBy(x => x.LastAccessTimeUtc).ToList();
int counter = fileInfos.Count;
@ -214,23 +214,24 @@ namespace ImageProcessor.Web.Caching
fileInfos,
fileInfo =>
{
lock (SyncRoot)
// Delete the file if we are nearing our limit buffer.
if (counter >= MaxFilesCount || fileInfo.LastAccessTimeUtc < DateTime.UtcNow.AddDays(-MaxFileCachedDuration))
{
try
lock (SyncRoot)
{
// Delete the file if we are nearing our limit buffer.
if (counter >= MaxFilesCount && fileInfo.LastAccessTime.ToUniversalTime() < DateTime.UtcNow.AddHours(1)
|| fileInfo.LastAccessTime.ToUniversalTime() < DateTime.UtcNow.AddDays(-MaxFileCachedDuration))
try
{
fileInfo.Delete();
counter -= 1;
}
}
catch (IOException)
{
// Do Nothing, skip to the next.
catch (IOException)
{
// Do Nothing, skip to the next.
// TODO: Should we handle this?
}
}
}
});
});
}

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

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

16
src/ImageProcessor.Web/Helpers/Class1.cs → src/ImageProcessor.Web/Helpers/ObjectFactory.cs

@ -17,13 +17,13 @@ namespace ImageProcessor.Web.Helpers
Type type = ctor.DeclaringType;
ParameterInfo[] paramsInfo = ctor.GetParameters();
//create a single param of type object[]
// Create a single param of type object[]
ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length];
//pick each arg from the params array
//and create a typed expression of them
// Pick each arg from the params array
// and create a typed expression for them
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
@ -36,15 +36,15 @@ namespace ImageProcessor.Web.Helpers
argsExp[i] = paramCastExp;
}
//make a NewExpression that calls the
//ctor with the args we just created
// Make a NewExpression that calls the
// ctor with the args we just created
NewExpression newExp = Expression.New(ctor, argsExp);
//create a lambda with the New
//Expression as body and our param object[] as arg
// Create a lambda with the New
// Expression as body and our param object[] as arg
LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator<T>), newExp, param);
//compile it
// Compile it
ObjectActivator<T> compiled = (ObjectActivator<T>)lambda.Compile();
return compiled;
}

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

@ -106,6 +106,16 @@ namespace ImageProcessor.Web.HttpModules
if (ImageUtils.IsValidImageExtension(path) && !string.IsNullOrWhiteSpace(queryString))
{
// Check to see if this is the first run and if so run the cache controller.
if (isFirstRun)
{
// Trim the cache.
DiskCache.PurgeCachedFolders();
// Disable the controller.
isFirstRun = false;
}
string fullPath = string.Format("{0}?{1}", path, queryString);
string imageName = Path.GetFileName(path);
string cachedPath = DiskCache.GetCachePath(fullPath, imageName);
@ -117,16 +127,6 @@ namespace ImageProcessor.Web.HttpModules
if ((exists == false) || (!isRemote && updated))
{
// Check to see if this is the first run and if so run the cache controller.
if (isFirstRun)
{
// Trim the cache.
DiskCache.PurgeCachedFolders();
// Disable the controller.
isFirstRun = false;
}
// Process the image.
using (ImageFactory imageFactory = new ImageFactory())
{
@ -171,20 +171,22 @@ namespace ImageProcessor.Web.HttpModules
// Ensure that the LastWriteTime property of the source and cached file match.
DiskCache.SetCachedLastWriteTime(path, cachedPath);
// If the number of cached imaged hits the maximum allowed for this session then we clear
// the cache again and reset the counter
if (cachedImageCounter >= DiskCache.MaxRunsBeforeCacheClear)
{
DiskCache.PurgeCachedFolders();
cachedImageCounter = 0;
}
}
context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(imageName).ToDescription();
// The cached file is valid so just rewrite the path.
context.RewritePath(DiskCache.GetVirtualPath(cachedPath, context.Request), false);
// 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#
// it would be nice to nail it though.
if (cachedImageCounter >= DiskCache.MaxRunsBeforeCacheClear)
{
DiskCache.PurgeCachedFolders();
cachedImageCounter = 0;
}
}
}
}

4
src/ImageProcessor.Web/ImageFactoryExtensions.cs

@ -19,7 +19,7 @@ namespace ImageProcessor.Web
/// </summary>
public static class ImageFactoryExtensions
{
private static readonly object SyncLock = new object();
private static readonly object SyncRoot = new object();
/// <summary>
/// Auto processes image files based on any querystring parameters added to the image path.
@ -36,7 +36,7 @@ public static ImageFactory AutoProcess(this ImageFactory factory)
if (factory.ShouldProcess)
{
// TODO: This is going to be a bottleneck for speed. Find a faster way.
lock (SyncLock)
lock (SyncRoot)
{
// Get a list of all graphics processors that have parsed and matched the querystring.
List<IGraphicsProcessor> list =

2
src/ImageProcessor.Web/ImageProcessor.Web.csproj

@ -56,8 +56,6 @@
<Compile Include="Config\ImageProcessingSection.cs" />
<Compile Include="Config\ImageProcessorConfig.cs" />
<Compile Include="Config\ImageSecuritySection.cs" />
<Compile Include="Helpers\Class1.cs" />
<Compile Include="Helpers\ProcessorFactory.cs" />
<Compile Include="Helpers\FileCompareLastwritetime.cs" />
<Compile Include="Helpers\RemoteFile.cs" />
<Compile Include="HttpModules\ImageProcessingModule.cs" />

Loading…
Cancel
Save