// 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; } } } }