Unified ImageFileCache implementations

This commit is contained in:
Clemens 2021-06-30 20:59:38 +02:00
parent f9347edf19
commit 642c3066fb
2 changed files with 112 additions and 112 deletions

View file

@ -5,7 +5,9 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MapControl.Caching
{
@ -30,6 +32,11 @@ namespace MapControl.Caching
Debug.WriteLine("Created ImageFileCache in " + rootDirectory);
}
public Task Clean()
{
return Task.Factory.StartNew(CleanRootDirectory, TaskCreationOptions.LongRunning);
}
private string GetPath(string key)
{
try
@ -44,6 +51,81 @@ namespace MapControl.Caching
return null;
}
private void CleanRootDirectory()
{
foreach (var dir in new DirectoryInfo(rootDirectory).EnumerateDirectories())
{
var deletedFileCount = CleanDirectory(dir);
if (deletedFileCount > 0)
{
Debug.WriteLine("ImageFileCache: Cleaned {0} files in {1}", deletedFileCount, dir);
}
}
}
private static int CleanDirectory(DirectoryInfo directory)
{
var deletedFileCount = 0;
foreach (var dir in directory.EnumerateDirectories())
{
deletedFileCount += CleanDirectory(dir);
}
foreach (var file in directory.EnumerateFiles())
{
try
{
if (ReadExpiration(file) < DateTime.UtcNow)
{
file.Delete();
deletedFileCount++;
}
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed cleaning {0}: {1}", file.FullName, ex.Message);
}
}
if (!directory.EnumerateFileSystemInfos().Any())
{
try
{
directory.Delete();
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed cleaning {0}: {1}", directory.FullName, ex.Message);
}
}
return deletedFileCount;
}
private static DateTime ReadExpiration(FileInfo file)
{
DateTime? expiration = null;
if (file.Length > 16)
{
var buffer = new byte[16];
using (var stream = file.OpenRead())
{
stream.Seek(-16, SeekOrigin.End);
if (stream.Read(buffer, 0, 16) == 16)
{
expiration = ReadExpiration(buffer);
}
}
}
return expiration ?? DateTime.Today;
}
private static DateTime ReadExpiration(ref byte[] buffer)
{
DateTime? expiration = ReadExpiration(buffer);
@ -59,13 +141,15 @@ namespace MapControl.Caching
private static DateTime? ReadExpiration(byte[] buffer)
{
DateTime? expiration = null;
if (buffer.Length >= 16 &&
Encoding.ASCII.GetString(buffer, buffer.Length - 16, 8) == expiresTag)
{
return new DateTime(BitConverter.ToInt64(buffer, buffer.Length - 8), DateTimeKind.Utc);
expiration = new DateTime(BitConverter.ToInt64(buffer, buffer.Length - 8), DateTimeKind.Utc);
}
return null;
return expiration;
}
}
}

View file

@ -11,7 +11,6 @@ using System.Runtime.Caching;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace MapControl.Caching
{
@ -27,11 +26,6 @@ namespace MapControl.Caching
private readonly MemoryCache memoryCache = MemoryCache.Default;
public Task Clean()
{
return Task.Factory.StartNew(CleanRootDirectory, TaskCreationOptions.LongRunning);
}
public override string Name
{
get { return string.Empty; }
@ -75,7 +69,23 @@ namespace MapControl.Caching
throw new ArgumentNullException(nameof(key));
}
return memoryCache.Contains(key) || FindFile(key) != null;
if (memoryCache.Contains(key))
{
return true;
}
var path = GetPath(key);
try
{
return path != null && File.Exists(path);
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed finding {0}: {1}", path, ex.Message);
}
return false;
}
public override object Get(string key, string regionName = null)
@ -94,11 +104,11 @@ namespace MapControl.Caching
if (imageCacheItem == null)
{
var path = FindFile(key);
var path = GetPath(key);
if (path != null)
try
{
try
if (path != null && File.Exists(path))
{
var buffer = File.ReadAllBytes(path);
var expiration = ReadExpiration(ref buffer);
@ -113,10 +123,10 @@ namespace MapControl.Caching
//Debug.WriteLine("ImageFileCache: Read {0}, Expires {1}", path, imageCacheItem.Expiration.ToLocalTime());
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed reading {0}: {1}", path, ex.Message);
}
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed reading {0}: {1}", path, ex.Message);
}
}
@ -232,115 +242,21 @@ namespace MapControl.Caching
memoryCache.Remove(key);
var path = FindFile(key);
if (path != null)
{
try
{
File.Delete(path);
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed removing {0}: {1}", path, ex.Message);
}
}
return null;
}
private string FindFile(string key)
{
var path = GetPath(key);
try
{
if (path != null && File.Exists(path))
{
return path;
File.Delete(path);
}
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed finding {0}: {1}", path, ex.Message);
Debug.WriteLine("ImageFileCache: Failed removing {0}: {1}", path, ex.Message);
}
return null;
}
private async Task CleanRootDirectory()
{
foreach (var dir in new DirectoryInfo(rootDirectory).EnumerateDirectories())
{
var deletedFileCount = await CleanDirectory(dir).ConfigureAwait(false);
if (deletedFileCount > 0)
{
Debug.WriteLine("ImageFileCache: Cleaned {0} files in {1}", deletedFileCount, dir);
}
}
}
private static async Task<int> CleanDirectory(DirectoryInfo directory)
{
var deletedFileCount = 0;
foreach (var dir in directory.EnumerateDirectories())
{
deletedFileCount += await CleanDirectory(dir).ConfigureAwait(false);
}
foreach (var file in directory.EnumerateFiles())
{
try
{
if (await ReadExpirationAsync(file).ConfigureAwait(false) < DateTime.UtcNow)
{
file.Delete();
deletedFileCount++;
}
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed cleaning {0}: {1}", file.FullName, ex.Message);
}
}
if (!directory.EnumerateFileSystemInfos().Any())
{
try
{
directory.Delete();
}
catch (Exception ex)
{
Debug.WriteLine("ImageFileCache: Failed cleaning {0}: {1}", directory.FullName, ex.Message);
}
}
return deletedFileCount;
}
private static async Task<DateTime> ReadExpirationAsync(FileInfo file)
{
DateTime? expiration = null;
if (file.Length > 16)
{
var buffer = new byte[16];
using (var stream = file.OpenRead())
{
stream.Seek(-16, SeekOrigin.End);
if (await stream.ReadAsync(buffer, 0, 16).ConfigureAwait(false) == 16)
{
expiration = ReadExpiration(buffer);
}
}
}
return expiration ?? DateTime.Today;
}
}
}