// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using Microsoft.AspNet.FileSystems;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.Runtime;
namespace Microsoft.AspNet.Mvc.Core
{
///
/// A default implementation for the interface.
///
public class ExpiringFileInfoCache : IFileInfoCache
{
private readonly ConcurrentDictionary _fileInfoCache =
new ConcurrentDictionary(StringComparer.Ordinal);
private readonly PhysicalFileSystem _fileSystem;
private readonly TimeSpan _offset;
protected virtual IFileSystem FileSystem
{
get
{
return _fileSystem;
}
}
protected virtual DateTime UtcNow
{
get
{
return DateTime.UtcNow;
}
}
public ExpiringFileInfoCache(IApplicationEnvironment env,
IOptionsAccessor optionsAccessor)
{
// TODO: Inject the IFileSystem but only when we get it from the host
_fileSystem = new PhysicalFileSystem(env.ApplicationBasePath);
_offset = optionsAccessor.Options.ViewEngineOptions.ExpirationBeforeCheckingFilesOnDisk;
}
///
public IFileInfo GetFileInfo([NotNull] string virtualPath)
{
IFileInfo fileInfo;
ExpiringFileInfo expiringFileInfo;
var utcNow = UtcNow;
if (_fileInfoCache.TryGetValue(virtualPath, out expiringFileInfo)
&& expiringFileInfo.ValidUntil > utcNow)
{
fileInfo = expiringFileInfo.FileInfo;
}
else
{
FileSystem.TryGetFileInfo(virtualPath, out fileInfo);
expiringFileInfo = new ExpiringFileInfo()
{
FileInfo = fileInfo,
ValidUntil = _offset == TimeSpan.MaxValue ? DateTime.MaxValue : utcNow.Add(_offset),
};
_fileInfoCache.AddOrUpdate(virtualPath, expiringFileInfo, (a, b) => expiringFileInfo);
}
return fileInfo;
}
private class ExpiringFileInfo
{
public IFileInfo FileInfo { get; set; }
public DateTime ValidUntil { get; set; }
}
}
}