Browse Source

cache updates

Former-commit-id: 8f3bec7fd268acc12ceabe64541a3ffda5b25901
af/merge-core
James South 13 years ago
parent
commit
b31405b5a5
  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. /// 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. /// This buffer will help us to ensure that we rarely hit anywhere near that limit.
/// </remarks> /// </remarks>
private const int MaxFilesCount = 6000; private const int MaxFilesCount = 6500;
/// <summary> /// <summary>
/// The regular expression to search strings for extension changes. /// The regular expression to search strings for extension changes.
@ -177,8 +177,8 @@ namespace ImageProcessor.Web.Caching
{ {
lock (SyncRoot) lock (SyncRoot)
{ {
DateTime dateTime = File.GetLastWriteTime(imagePath); DateTime dateTime = File.GetLastWriteTimeUtc(imagePath);
File.SetLastWriteTime(cachedImagePath, dateTime); File.SetLastWriteTimeUtc(cachedImagePath, dateTime);
} }
} }
} }
@ -202,11 +202,11 @@ namespace ImageProcessor.Web.Caching
Parallel.ForEach( Parallel.ForEach(
directoryInfos, directoryInfos,
dir => subDirectoryInfo =>
{ {
// 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 = dir.EnumerateFiles("*", SearchOption.AllDirectories) List<FileInfo> fileInfos = subDirectoryInfo.EnumerateFiles("*", SearchOption.AllDirectories)
.OrderBy(x => x.LastAccessTime).ToList(); .OrderBy(x => x.LastAccessTimeUtc).ToList();
int counter = fileInfos.Count; int counter = fileInfos.Count;
@ -214,23 +214,24 @@ namespace ImageProcessor.Web.Caching
fileInfos, fileInfos,
fileInfo => 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. try
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 (IOException)
catch (IOException) {
{ // Do Nothing, skip to the next.
// 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> /// <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.ToUniversalTime()) == ToMinute(f2.LastWriteTime.ToUniversalTime()); return ToMinute(f1.LastWriteTimeUtc) == ToMinute(f2.LastWriteTimeUtc);
} }
/// <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.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; Type type = ctor.DeclaringType;
ParameterInfo[] paramsInfo = ctor.GetParameters(); 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"); ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length]; Expression[] argsExp = new Expression[paramsInfo.Length];
//pick each arg from the params array // Pick each arg from the params array
//and create a typed expression of them // and create a typed expression for them
for (int i = 0; i < paramsInfo.Length; i++) for (int i = 0; i < paramsInfo.Length; i++)
{ {
Expression index = Expression.Constant(i); Expression index = Expression.Constant(i);
@ -36,15 +36,15 @@ namespace ImageProcessor.Web.Helpers
argsExp[i] = paramCastExp; argsExp[i] = paramCastExp;
} }
//make a NewExpression that calls the // Make a NewExpression that calls the
//ctor with the args we just created // ctor with the args we just created
NewExpression newExp = Expression.New(ctor, argsExp); NewExpression newExp = Expression.New(ctor, argsExp);
//create a lambda with the New // Create a lambda with the New
//Expression as body and our param object[] as arg // Expression as body and our param object[] as arg
LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator<T>), newExp, param); LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator<T>), newExp, param);
//compile it // Compile it
ObjectActivator<T> compiled = (ObjectActivator<T>)lambda.Compile(); ObjectActivator<T> compiled = (ObjectActivator<T>)lambda.Compile();
return compiled; return compiled;
} }

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

@ -106,6 +106,16 @@ namespace ImageProcessor.Web.HttpModules
if (ImageUtils.IsValidImageExtension(path) && !string.IsNullOrWhiteSpace(queryString)) 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 fullPath = string.Format("{0}?{1}", path, queryString);
string imageName = Path.GetFileName(path); string imageName = Path.GetFileName(path);
string cachedPath = DiskCache.GetCachePath(fullPath, imageName); string cachedPath = DiskCache.GetCachePath(fullPath, imageName);
@ -117,16 +127,6 @@ namespace ImageProcessor.Web.HttpModules
if ((exists == false) || (!isRemote && updated)) 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. // Process the image.
using (ImageFactory imageFactory = new ImageFactory()) 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. // Ensure that the LastWriteTime property of the source and cached file match.
DiskCache.SetCachedLastWriteTime(path, cachedPath); 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(); context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(imageName).ToDescription();
// The cached file is valid so just rewrite the path. // The cached file is valid so just rewrite the path.
context.RewritePath(DiskCache.GetVirtualPath(cachedPath, context.Request), false); 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> /// </summary>
public static class ImageFactoryExtensions public static class ImageFactoryExtensions
{ {
private static readonly object SyncLock = new object(); private static readonly object SyncRoot = new object();
/// <summary> /// <summary>
/// Auto processes image files based on any querystring parameters added to the image path. /// 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) if (factory.ShouldProcess)
{ {
// TODO: This is going to be a bottleneck for speed. Find a faster way. // 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. // Get a list of all graphics processors that have parsed and matched the querystring.
List<IGraphicsProcessor> list = List<IGraphicsProcessor> list =

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

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

Loading…
Cancel
Save