Browse Source

Adding code comments

Former-commit-id: 2a51566a5c79a24bda73701a439d91b1492b0f59
Former-commit-id: 2d4fff12db92bc6a959fb94a5f2b3a4e551fe0f0
af/merge-core
James South 11 years ago
parent
commit
be7f51318e
  1. 115
      src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs
  2. 55
      src/ImageProcessor.Web/Caching/DiskCache.cs
  3. 58
      src/ImageProcessor.Web/Caching/IImageCache.cs
  4. 62
      src/ImageProcessor.Web/Caching/ImageCacheBase.cs
  5. 4
      src/ImageProcessor.Web/Services/IImageService.cs
  6. 1
      src/ImageProcessor.Web/Settings.StyleCop

115
src/ImageProcessor.Web.AzureBlobCache/AzureBlobCache.cs

@ -1,4 +1,15 @@
namespace ImageProcessor.Web.Caching
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AzureBlobCache.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Provides an <see cref="IImageCache" /> implementation that uses Azure blob storage.
// The cache is self healing and cleaning.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Caching
{
using System;
using System.Collections.Generic;
@ -15,54 +26,72 @@
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
/// <summary>
/// Provides an <see cref="IImageCache"/> implementation that uses Azure blob storage.
/// The cache is self healing and cleaning.
/// </summary>
public class AzureBlobCache : ImageCacheBase
{
/// <summary>
/// The max age.
/// The maximum number of days to store the image.
/// </summary>
private readonly int maxDays;
private CloudStorageAccount cloudCachedStorageAccount;
private CloudStorageAccount cloudSourceStorageAccount;
private CloudBlobClient cloudCachedBlobClient;
private CloudBlobClient cloudSourceBlobClient;
private CloudBlobContainer cloudCachedBlobContainer;
/// <summary>
/// The cloud cached blob container.
/// </summary>
private readonly CloudBlobContainer cloudCachedBlobContainer;
private CloudBlobContainer cloudSourceBlobContainer;
/// <summary>
/// The cloud source blob container.
/// </summary>
private readonly CloudBlobContainer cloudSourceBlobContainer;
private string cachedCDNRoot;
/// <summary>
/// The cached root url for a content delivery network.
/// </summary>
private readonly string cachedCdnRoot;
/// <summary>
/// The cached rewrite path.
/// </summary>
private string cachedRewritePath;
/// <summary>
/// The physical cached path.
/// Initializes a new instance of the <see cref="AzureBlobCache"/> class.
/// </summary>
private string physicalCachedPath;
/// <param name="requestPath">
/// The request path for the image.
/// </param>
/// <param name="fullPath">
/// The full path for the image.
/// </param>
/// <param name="querystring">
/// The querystring containing instructions.
/// </param>
public AzureBlobCache(string requestPath, string fullPath, string querystring)
: base(requestPath, fullPath, querystring)
{
this.maxDays = Convert.ToInt32(this.Settings["MaxDays"]);
// Retrieve storage accounts from connection string.
this.cloudCachedStorageAccount = CloudStorageAccount.Parse(this.Settings["CachedStorageAccount"]);
this.cloudSourceStorageAccount = CloudStorageAccount.Parse(this.Settings["SourceStorageAccount"]);
CloudStorageAccount cloudCachedStorageAccount = CloudStorageAccount.Parse(this.Settings["CachedStorageAccount"]);
CloudStorageAccount cloudSourceStorageAccount = CloudStorageAccount.Parse(this.Settings["SourceStorageAccount"]);
// Create the blob clients.
this.cloudCachedBlobClient = this.cloudCachedStorageAccount.CreateCloudBlobClient();
this.cloudSourceBlobClient = this.cloudSourceStorageAccount.CreateCloudBlobClient();
CloudBlobClient cloudCachedBlobClient = cloudCachedStorageAccount.CreateCloudBlobClient();
CloudBlobClient cloudSourceBlobClient = cloudSourceStorageAccount.CreateCloudBlobClient();
// Retrieve references to a previously created containers.
this.cloudCachedBlobContainer = this.cloudCachedBlobClient.GetContainerReference(this.Settings["CachedBlobContainer"]);
this.cloudSourceBlobContainer = this.cloudSourceBlobClient.GetContainerReference(this.Settings["SourceBlobContainer"]);
this.cloudCachedBlobContainer = cloudCachedBlobClient.GetContainerReference(this.Settings["CachedBlobContainer"]);
this.cloudSourceBlobContainer = cloudSourceBlobClient.GetContainerReference(this.Settings["SourceBlobContainer"]);
this.cachedCDNRoot = this.Settings["CachedCDNRoot"];
this.cachedCdnRoot = this.Settings["CachedCDNRoot"];
}
/// <summary>
/// Gets the maximum number of days to store the image.
/// </summary>
public override int MaxDays
{
get
@ -71,6 +100,12 @@
}
}
/// <summary>
/// Gets a value indicating whether the image is new or updated in an asynchronous manner.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> returning the value.
/// </returns>
public override async Task<bool> IsNewOrUpdatedAsync()
{
string cachedFileName = await this.CreateCachedFileName();
@ -79,7 +114,7 @@
// That gives us massive scope to store millions of files.
string pathFromKey = string.Join("\\", cachedFileName.ToCharArray().Take(6));
this.CachedPath = Path.Combine(this.cloudCachedBlobContainer.Uri.ToString(), pathFromKey, cachedFileName).Replace(@"\", "/");
this.cachedRewritePath = Path.Combine(this.cachedCDNRoot, this.cloudCachedBlobContainer.Name, pathFromKey, cachedFileName).Replace(@"\", "/");
this.cachedRewritePath = Path.Combine(this.cachedCdnRoot, this.cloudCachedBlobContainer.Name, pathFromKey, cachedFileName).Replace(@"\", "/");
bool isUpdated = false;
CachedImage cachedImage = CacheIndexer.GetValue(this.CachedPath);
@ -147,18 +182,36 @@
return isUpdated;
}
/// <summary>
/// Adds the image to the cache in an asynchronous manner.
/// </summary>
/// <param name="stream">
/// The stream containing the image data.
/// </param>
/// <param name="contentType">
/// The content type of the image.
/// </param>
/// <returns>
/// The <see cref="Task"/> representing an asynchronous operation.
/// </returns>
public override async Task AddImageToCacheAsync(Stream stream, string contentType)
{
string blobPath = this.CachedPath.Substring(this.cloudCachedBlobContainer.Uri.ToString().Length + 1);
CloudBlockBlob blockBlob = this.cloudCachedBlobContainer.GetBlockBlobReference(blobPath);
await blockBlob.UploadFromStreamAsync(stream);
blockBlob.Properties.ContentType = contentType;
blockBlob.Properties.CacheControl = string.Format("public, max-age={0}", this.MaxDays * 86400);
await blockBlob.SetPropertiesAsync();
}
/// <summary>
/// Trims the cache of any expired items in an asynchronous manner.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> representing an asynchronous operation.
/// </returns>
public override async Task TrimCacheAsync()
{
Uri uri = new Uri(this.CachedPath);
@ -197,6 +250,12 @@
}
}
/// <summary>
/// Gets a string identifying the cached file name.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> returning the value.
/// </returns>
public override async Task<string> CreateCachedFileName()
{
string streamHash = string.Empty;
@ -260,6 +319,12 @@
return cachedFileName;
}
/// <summary>
/// Rewrites the path to point to the cached image.
/// </summary>
/// <param name="context">
/// The <see cref="HttpContext"/> encapsulating all information about the request.
/// </param>
public override void RewritePath(HttpContext context)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.cachedRewritePath);

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

@ -1,4 +1,15 @@
namespace ImageProcessor.Web.Caching
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DiskCache.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Provides an <see cref="IImageCache" /> implementation that is file system based.
// The cache is self healing and cleaning.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Caching
{
using System;
using System.Collections.Generic;
@ -9,9 +20,12 @@
using System.Web;
using System.Web.Hosting;
using ImageProcessor.Web.Configuration;
using ImageProcessor.Web.Extensions;
/// <summary>
/// Provides an <see cref="IImageCache"/> implementation that is file system based.
/// The cache is self healing and cleaning.
/// </summary>
public class DiskCache : ImageCacheBase
{
/// <summary>
@ -27,7 +41,7 @@
private const int MaxFilesCount = 100;
/// <summary>
/// The max age.
/// The maximum number of days to store the image.
/// </summary>
private readonly int maxDays;
@ -42,7 +56,7 @@
private readonly string absoluteCachePath;
/// <summary>
/// The virtual cached path to the cached file.
/// The virtual path to the cached file.
/// </summary>
private string virtualCachedFilePath;
@ -75,8 +89,7 @@
}
/// <summary>
/// The maximum number of days to cache files on the system for.
/// TODO: Shift the getter source to proper config.
/// Gets the maximum number of days to store the image.
/// </summary>
public override int MaxDays
{
@ -86,6 +99,12 @@
}
}
/// <summary>
/// Gets a value indicating whether the image is new or updated in an asynchronous manner.
/// </summary>
/// <returns>
/// The <see cref="Task"/>.
/// </returns>
public override async Task<bool> IsNewOrUpdatedAsync()
{
string cachedFileName = await this.CreateCachedFileName();
@ -138,6 +157,18 @@
return isUpdated;
}
/// <summary>
/// Adds the image to the cache in an asynchronous manner.
/// </summary>
/// <param name="stream">
/// The stream containing the image data.
/// </param>
/// <param name="contentType">
/// The content type of the image.
/// </param>
/// <returns>
/// The <see cref="Task"/> representing an asynchronous operation.
/// </returns>
public override async Task AddImageToCacheAsync(Stream stream, string contentType)
{
// ReSharper disable once AssignNullToNotNullAttribute
@ -153,6 +184,12 @@
}
}
/// <summary>
/// Trims the cache of any expired items in an asynchronous manner.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> representing an asynchronous operation.
/// </returns>
public override async Task TrimCacheAsync()
{
string directory = Path.GetDirectoryName(this.CachedPath);
@ -198,6 +235,12 @@
}
}
/// <summary>
/// Rewrites the path to point to the cached image.
/// </summary>
/// <param name="context">
/// The <see cref="HttpContext"/> encapsulating all information about the request.
/// </param>
public override void RewritePath(HttpContext context)
{
// The cached file is valid so just rewrite the path.

58
src/ImageProcessor.Web/Caching/IImageCache.cs

@ -1,4 +1,13 @@

// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IImageCache.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Defines properties and methods for allowing caching of images to different sources.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Caching
{
using System.Collections.Generic;
@ -6,6 +15,9 @@ namespace ImageProcessor.Web.Caching
using System.Threading.Tasks;
using System.Web;
/// <summary>
/// Defines properties and methods for allowing caching of images to different sources.
/// </summary>
public interface IImageCache
{
/// <summary>
@ -13,20 +25,60 @@ namespace ImageProcessor.Web.Caching
/// </summary>
Dictionary<string, string> Settings { get; set; }
/// <summary>
/// Gets the path to the cached image.
/// </summary>
string CachedPath { get; }
/// <summary>
/// Gets the maximum number of days to store the image.
/// </summary>
int MaxDays { get; }
/// <summary>
/// Gets a value indicating whether the image is new or updated in an asynchronous manner.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> returning the value.
/// </returns>
Task<bool> IsNewOrUpdatedAsync();
/// <summary>
/// Adds the image to the cache in an asynchronous manner.
/// </summary>
/// <param name="stream">
/// The stream containing the image data.
/// </param>
/// <param name="contentType">
/// The content type of the image.
/// </param>
/// <returns>
/// The <see cref="Task"/> representing an asynchronous operation.
/// </returns>
Task AddImageToCacheAsync(Stream stream, string contentType);
/// <summary>
/// Trims the cache of any expired items in an asynchronous manner.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> representing an asynchronous operation.
/// </returns>
Task TrimCacheAsync();
/// <summary>
/// Gets a string identifying the cached file name.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> returning the value.
/// </returns>
Task<string> CreateCachedFileName();
/// <summary>
/// Rewrites the path to point to the cached image.
/// </summary>
/// <param name="context">
/// The <see cref="HttpContext"/> encapsulating all information about the request.
/// </param>
void RewritePath(HttpContext context);
//void SetHeaders(HttpContext context);
}
}

62
src/ImageProcessor.Web/Caching/ImageCacheBase.cs

@ -1,10 +1,20 @@
namespace ImageProcessor.Web.Caching
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageCacheBase.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// The image cache base provides methods for implementing the <see cref="IImageCache" /> interface.
// It is recommended that any implementations inherit from this class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Web.Caching
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;
@ -12,6 +22,10 @@
using ImageProcessor.Web.Extensions;
using ImageProcessor.Web.Helpers;
/// <summary>
/// The image cache base provides methods for implementing the <see cref="IImageCache"/> interface.
/// It is recommended that any implementations inherit from this class.
/// </summary>
public abstract class ImageCacheBase : IImageCache
{
/// <summary>
@ -54,16 +68,52 @@
/// </summary>
public Dictionary<string, string> Settings { get; set; }
public string CachedPath { get; protected set; }
/// <summary>
/// Gets or sets the path to the cached image.
/// </summary>
public string CachedPath { get; set; }
/// <summary>
/// Gets the maximum number of days to store the image.
/// </summary>
public abstract int MaxDays { get; }
/// <summary>
/// Gets a value indicating whether the image is new or updated in an asynchronous manner.
/// </summary>
/// <returns>
/// The <see cref="Task"/>.
/// </returns>
public abstract Task<bool> IsNewOrUpdatedAsync();
/// <summary>
/// Adds the image to the cache in an asynchronous manner.
/// </summary>
/// <param name="stream">
/// The stream containing the image data.
/// </param>
/// <param name="contentType">
/// The content type of the image.
/// </param>
/// <returns>
/// The <see cref="Task"/> representing an asynchronous operation.
/// </returns>
public abstract Task AddImageToCacheAsync(Stream stream, string contentType);
/// <summary>
/// Trims the cache of any expired items in an asynchronous manner.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> representing an asynchronous operation.
/// </returns>
public abstract Task TrimCacheAsync();
/// <summary>
/// Gets a string identifying the cached file name.
/// </summary>
/// <returns>
/// The asynchronous <see cref="Task"/> returning the value.
/// </returns>
public virtual Task<string> CreateCachedFileName()
{
string streamHash = string.Empty;
@ -106,6 +156,12 @@
return Task.FromResult(cachedFileName);
}
/// <summary>
/// Rewrites the path to point to the cached image.
/// </summary>
/// <param name="context">
/// The <see cref="HttpContext"/> encapsulating all information about the request.
/// </param>
public abstract void RewritePath(HttpContext context);
/// <summary>

4
src/ImageProcessor.Web/Services/IImageService.cs

@ -4,7 +4,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Defines properties and methods for allowing retrieval of image from different sources.
// Defines properties and methods for allowing retrieval of images from different sources.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
@ -15,7 +15,7 @@ namespace ImageProcessor.Web.Services
using System.Threading.Tasks;
/// <summary>
/// Defines properties and methods for allowing retrieval of image from different sources.
/// Defines properties and methods for allowing retrieval of images from different sources.
/// </summary>
public interface IImageService
{

1
src/ImageProcessor.Web/Settings.StyleCop

@ -1,6 +1,7 @@
<StyleCopSettings Version="105">
<GlobalSettings>
<CollectionProperty Name="RecognizedWords">
<Value>cdn</Value>
<Value>dllimport</Value>
</CollectionProperty>
</GlobalSettings>

Loading…
Cancel
Save