/// <summary>The restore sprited images from cache.</summary> /// <param name="mapXmlFile">The map xml file.</param> /// <param name="cacheSection">The cache section.</param> /// <param name="results">The results.</param> /// <param name="destinationDirectory">The destination Directory.</param> /// <param name="imageAssembleScanDestinationFile">The image Assemble Scan Destination File.</param> /// <returns>The <see cref="bool"/>.</returns> private static ImageLog RestoreSpritedImagesFromCache(string mapXmlFile, ICacheSection cacheSection, BlockingCollection <ContentItem> results, string destinationDirectory, string imageAssembleScanDestinationFile) { // restore log file, is required by next step in applying sprites to the css. var spriteLogFileContentItem = cacheSection.GetCachedContentItems(CacheFileCategories.SpriteLogFile).FirstOrDefault(); if (spriteLogFileContentItem == null) { return(null); } if (!string.IsNullOrWhiteSpace(imageAssembleScanDestinationFile)) { var spriteLogFileXmlContentItem = cacheSection.GetCachedContentItems(CacheFileCategories.SpriteLogFileXml).FirstOrDefault(); if (spriteLogFileXmlContentItem != null) { spriteLogFileXmlContentItem.WriteTo(mapXmlFile); } } var imageLog = spriteLogFileContentItem.Content.FromJson <ImageLog>(true); // Restore images var spritedImageContentItems = cacheSection.GetCachedContentItems(CacheFileCategories.HashedSpriteImage); spritedImageContentItems.ForEach(sici => sici.WriteToContentPath(destinationDirectory)); results.AddRange(spritedImageContentItems); return(imageLog); }
/// <summary> /// Parse out the @imports and replace with all files in directory @import. /// </summary> /// <param name="fileContent">The content</param> /// <param name="workingFolder">The workingFolder</param> /// <param name="cacheSection">The cache section</param> /// <param name="minimalOutput">Is the goal to have the most minimal output (true skips lots of comments)</param> /// <returns>The parses less content.</returns> private static string ParseImports(string fileContent, string workingFolder, ICacheSection cacheSection, bool minimalOutput) { var withImports = ImportsPattern.Replace(fileContent, match => ReplaceImports(match, workingFolder.EnsureEndSeparator(), cacheSection, minimalOutput)); SetImportSourceDependencies(withImports, workingFolder, cacheSection); return(withImports); }
/// <summary>The restore bundle from cache.</summary> /// <param name="cacheSection">The cache section.</param> /// <returns>The <see cref="bool"/>.</returns> private bool RestoreBundleFromCache(ICacheSection cacheSection) { var endResults = cacheSection.GetCachedContentItems(CacheFileCategories.AssemblerResult, true); endResults.ForEach(er => er.WriteToContentPath(this.context.Configuration.DestinationDirectory)); return(true); }
/// <summary>The method called from the regex replace to replace the matched wgInclude() statements.</summary> /// <param name="match">The regex match</param> /// <param name="workingFolder">The working folder from which to determine relative path's in the include.</param> /// <param name="cacheSection">The cache Section.</param> /// <param name="minimalOutput">Is the goal to have the most minimal output (true skips lots of comments)</param> /// <returns>The contents of the file to replace, with a /* WGINCLUDE [fullFilePath] */ header on top.</returns> private static string ReplaceInputs(Match match, string workingFolder, ICacheSection cacheSection, bool minimalOutput) { var fileOrPath = Path.Combine(workingFolder, match.Groups["fileOrPath"].Value.Trim()); var inputSpec = new InputSpec { IsOptional = true, Path = fileOrPath }; if (Directory.Exists(fileOrPath)) { inputSpec.SearchPattern = match.Groups["searchPattern"].Value.Trim(); } cacheSection.AddSourceDependency(inputSpec); var result = string.Empty; foreach (var file in inputSpec.GetFiles()) { if (!minimalOutput) { result += "/* WGINCLUDE: {0} */\r\n".InvariantFormat(file); } result += File.ReadAllText(file) + "\r\n"; } return(result); }
/// <summary>Begins a new cache section.</summary> /// <param name="webGreaseSectionKey">The web Grease Section Key.</param> /// <param name="autoLoad">The auto Load.</param> /// <returns>The <see cref="ICacheSection"/>.</returns> public ICacheSection BeginSection(WebGreaseSectionKey webGreaseSectionKey, bool autoLoad = true) { return(this.currentCacheSection = CacheSection.Begin( this.context, webGreaseSectionKey.Category, webGreaseSectionKey.Value, this.CurrentCacheSection, autoLoad)); }
public static IEnumerable <ICacheResult> GetAllEntriesUntyped([NotNull] this ICacheSection cacheSection) { cacheSection.AssertArgumentNotNull(nameof(cacheSection)); var values = cacheSection .Keys .Select(key => cacheSection.GetCacheEntryUntyped(key)) .Where(cacheResult => cacheResult != null); return(values); }
public async Task Test1() { MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions()); var cacheManager = new CacheManager(memoryCache); double d1 = await cacheManager.GetOrCreateAsync(Cache.Section1, "Value1", context => Task.FromResult(1.0)); double d2 = await cacheManager.GetOrCreateAsync(Cache.Section1, "Value2", context => Task.FromResult(2.0)); ICacheSection <double> cacheSection = cacheManager.GetOrCreateSection(Cache.Section1); }
public static IEnumerable <CacheResult <T> > GetAllEntries <T>([NotNull] this ICacheSection <T> cacheSection) { cacheSection.AssertArgumentNotNull(nameof(cacheSection)); var values = cacheSection .Keys .Select(key => cacheSection.GetCacheEntry(key)) .Where(cacheResult => !cacheResult.IsEmpty()); return(values); }
public static IEnumerable <T> GetAllValues <T>([NotNull] this ICacheSection <T> cacheSection) { cacheSection.AssertArgumentNotNull(nameof(cacheSection)); var values = cacheSection .Keys .Select(key => cacheSection.Get(key)) .Where(option => option.IsSome) .Select(option => option.GetValueOrDefault()); return(values); }
/// <summary>The handle other content type cache sections.</summary> /// <param name="context">The context.</param> /// <param name="parentCacheSection">The session cache section.</param> /// <param name="sessionCacheData">The session cache data.</param> /// <param name="contentTypeSectionId">The content type section id.</param> private void HandleOtherContentTypeCacheSections(IWebGreaseContext context, ICacheSection parentCacheSection, SessionCacheData sessionCacheData, string[] contentTypeSectionId) { if (sessionCacheData != null) { foreach (var configType in sessionCacheData.ConfigTypes.Keys.Where(ct => !ct.Equals(this.ConfigType, StringComparison.OrdinalIgnoreCase))) { // TODO: Do a better job at touching all the files used by the last build from another config type. var otherContentTypeCacheSection = CacheSection.Begin(context, WebGreaseContext.ToStringId(contentTypeSectionId), sessionCacheData.GetConfigTypeUniqueKey(configType), parentCacheSection); otherContentTypeCacheSection.Save(); } } }
/// <summary> /// Initializes a new instance of the <see cref="MemoryCacheStorage{TSessionState, TOperationState}"/> class. /// </summary> /// <param name="memoryCache">Memory cache.</param> /// <param name="cacheSectionName">Optional cache section name.</param> /// <param name="configureCacheEntry">Optional cache configure method for all sections.</param> public MemoryCacheStorage( IMemoryCache memoryCache, string?cacheSectionName = null, Action <ICacheEntryContext>?configureCacheEntry = null) { memoryCache.AssertArgumentNotNull(nameof(memoryCache)); string sectionName = cacheSectionName ?? $"OperationManager<{nameof(TSessionState)}, {nameof(TOperationState)}>"; _sessionsCache = new CacheManager(memoryCache, configureCacheEntry) .GetOrCreateSection(sectionName, CacheSettings <IOperationManager <TSessionState, TOperationState> > .Default); }
/// <summary>Ends the cache section.</summary> /// <param name="cacheSection">The cache section.</param> public void EndSection(ICacheSection cacheSection) { #if DEBUG if (this.CurrentCacheSection != cacheSection) { throw new BuildWorkflowException("Something unexpected went wrong with the caching logic."); } #endif if (this.CurrentCacheSection == cacheSection) { this.currentCacheSection = cacheSection.Parent; } }
/// <summary>The create sprited images.</summary> /// <param name="mapXmlFile">The map xml file.</param> /// <param name="imageAssemblyAnalysisLog">The image assembly analysis log.</param> /// <param name="imageReferencesToAssemble">The image references to assemble.</param> /// <param name="cacheSection">The cache section.</param> /// <param name="results">The results.</param> /// <param name="threadContext">The thread Context.</param> /// <returns>The <see cref="bool"/>.</returns> private ImageLog CreateSpritedImages( string mapXmlFile, ImageAssemblyAnalysisLog imageAssemblyAnalysisLog, IEnumerable <InputImage> imageReferencesToAssemble, ICacheSection cacheSection, BlockingCollection <ContentItem> results, IWebGreaseContext threadContext) { if (!Directory.Exists(this.ImagesOutputDirectory)) { Directory.CreateDirectory(this.ImagesOutputDirectory); } var imageMap = ImageAssembleGenerator.AssembleImages( imageReferencesToAssemble.ToSafeReadOnlyCollection(), SpritePackingType.Vertical, this.ImagesOutputDirectory, string.Empty, true, threadContext, this.ImageAssemblyPadding, imageAssemblyAnalysisLog, this.ForcedSpritingImageType); if (imageMap == null || imageMap.Document == null) { return(null); } var destinationDirectory = threadContext.Configuration.DestinationDirectory; if (!string.IsNullOrWhiteSpace(this.ImageAssembleScanDestinationFile)) { var scanXml = imageMap.Document.ToString(); FileHelper.WriteFile(mapXmlFile, scanXml); cacheSection.AddResult(ContentItem.FromFile(mapXmlFile), CacheFileCategories.SpriteLogFileXml); } var imageLog = new ImageLog(imageMap.Document); cacheSection.AddResult(ContentItem.FromContent(imageLog.ToJson(true)), CacheFileCategories.SpriteLogFile); foreach (var spritedFile in imageLog.InputImages.Select(il => il.OutputFilePath).Distinct()) { var spritedImageContentItem = ContentItem.FromFile(spritedFile, spritedFile.MakeRelativeToDirectory(destinationDirectory)); results.Add(spritedImageContentItem); cacheSection.AddResult(spritedImageContentItem, CacheFileCategories.HashedSpriteImage); } return(imageLog); }
/// <summary>Initializes a new instance of the <see cref="CacheManager"/> class.</summary> /// <param name="configuration">The configuration.</param> /// <param name="logManager">The log manager.</param> /// <param name="parentCacheSection">The parent Cache Section.</param> public CacheManager(WebGreaseConfiguration configuration, LogManager logManager, ICacheSection parentCacheSection) { this.currentCacheSection = parentCacheSection; if (configuration == null) { throw new ArgumentNullException("configuration"); } if (logManager == null) { throw new ArgumentNullException("logManager"); } var cacheRoot = configuration.CacheRootPath.AsNullIfWhiteSpace() ?? "_webgrease.cache"; if (!Path.IsPathRooted(cacheRoot)) { cacheRoot = Path.Combine(configuration.SourceDirectory, cacheRoot); } this.cacheRootPath = GetCacheUniquePath(cacheRoot, configuration.CacheUniqueKey); if (!Directory.Exists(this.cacheRootPath)) { Directory.CreateDirectory(this.cacheRootPath); } Safe.Lock( First, () => { // Only log this once when multi threading. if (First.Contains(this.cacheRootPath)) { First.Add(this.cacheRootPath); logManager.Information("Cache enabled using cache path: {0}".InvariantFormat(this.cacheRootPath)); } }); }
/// <summary>The replace imports.</summary> /// <param name="match">The match.</param> /// <param name="workingFolder">The working folder.</param> /// <param name="cacheSection">The cache Section.</param> /// <param name="minimalOutput">Is the goal to have the most minimal output (true skips lots of comments)</param> /// <returns>The replaced imports.</returns> private static string ReplaceImports(Match match, string workingFolder, ICacheSection cacheSection, bool minimalOutput) { var path = match.Groups["path"].Value; string pattern = null; var pathParts = path.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries).ToList(); var possiblePattern = pathParts.LastOrDefault(); if (!string.IsNullOrEmpty(possiblePattern) && possiblePattern.Contains("*")) { pattern = possiblePattern; pathParts.RemoveAt(pathParts.Count - 1); } var pathInfo = new DirectoryInfo(Path.Combine(workingFolder, string.Join("\\", pathParts))); cacheSection.AddSourceDependency(new InputSpec { IsOptional = true, Path = pathInfo.FullName, SearchOption = SearchOption.TopDirectoryOnly, SearchPattern = pattern }); if (!pathInfo.Exists) { return(string.Empty); } var files = !string.IsNullOrWhiteSpace(pattern) ? Directory.GetFiles(pathInfo.FullName, pattern) : Directory.GetFiles(pathInfo.FullName); return ((minimalOutput ? string.Empty : GetImportsComment(path, string.Empty)) + string.Join( " ", files .Select(file => MakeRelativePath(workingFolder, file)) .Select(relativeFile => "{0}\r\n@import \"{1}\";".InvariantFormat( minimalOutput ? string.Empty : "\r\n" + GetImportsComment(path, Path.GetFileName(relativeFile)), relativeFile.Replace("\\", "/"))))); }
public void EndSection(ICacheSection cacheSection) { throw new NotImplementedException(); }
/// <summary>Hash the images.</summary> /// <param name="cssContent">The css content.</param> /// <param name="imageHasher">The image Hasher.</param> /// <param name="cacheSection">The cache section.</param> /// <param name="threadContext">The context.</param> /// <param name="sourceImages">The source Images.</param> /// <param name="missingImage">The missing Image.</param> /// <returns>The css with hashed images.</returns> private static Tuple <string, IEnumerable <ContentItem> > HashImages(string cssContent, FileHasherActivity imageHasher, ICacheSection cacheSection, IWebGreaseContext threadContext, IDictionary <string, string> sourceImages, string missingImage) { return(threadContext.SectionedAction(SectionIdParts.MinifyCssActivity, SectionIdParts.ImageHash).Execute(() => { var contentImagesToHash = new HashSet <string>(); var hashedContentItems = new List <ContentItem>(); var hashedImages = new Dictionary <string, string>(); cssContent = UrlHashRegexPattern.Replace( cssContent, match => { var urlToHash = match.Groups["url"].Value; var extraInfo = match.Groups["extra"].Value; if (ResourcesResolver.LocalizationResourceKeyRegex.IsMatch(urlToHash)) { return match.Value; } var normalizedHashUrl = urlToHash.NormalizeUrl(); var imageContentFile = sourceImages.TryGetValue(normalizedHashUrl); if (imageContentFile == null && !string.IsNullOrWhiteSpace(missingImage)) { imageContentFile = sourceImages.TryGetValue(missingImage); } if (imageContentFile == null) { throw new BuildWorkflowException("Could not find a matching source image for url: {0}".InvariantFormat(urlToHash)); } if (contentImagesToHash.Add(normalizedHashUrl)) { // Add the image as end result var imageContentItem = ContentItem.FromFile(imageContentFile, normalizedHashUrl); imageContentItem = imageHasher.Hash(imageContentItem); cacheSection.AddSourceDependency(imageContentFile); hashedContentItems.Add(imageContentItem); imageContentFile = Path.Combine( imageHasher.BasePrefixToAddToOutputPath ?? Path.AltDirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), imageContentItem.RelativeHashedContentPath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)); hashedImages.Add(normalizedHashUrl, imageContentFile); } else { imageContentFile = hashedImages[normalizedHashUrl]; } return "url(" + imageContentFile + extraInfo + ")"; }); return Tuple.Create(cssContent, (IEnumerable <ContentItem>)hashedContentItems); })); }
/// <summary> /// Gets or creates value according default cache behavior <see cref="CacheSettings{TValue}.Default"/>. /// </summary> /// <typeparam name="TValue">Value type.</typeparam> /// <param name="sectionName">Section name.</param> /// <param name="key">Cache key.</param> /// <param name="factory">Factory method to create and customize cache item.</param> /// <returns><see cref="CacheResult{TValue}"/>.</returns> public async Task <CacheResult <TValue> > GetOrCreateAsync <TValue>(string sectionName, string key, Func <ICacheEntryContext, Task <TValue> > factory) { ICacheSection <TValue> cacheSection = GetOrCreateSection(sectionName, CacheSettings <TValue> .Default); return(await cacheSection.GetOrCreateAsync(key, factory)); }
/// <summary> /// Gets or creates cache section by provided settings. /// </summary> /// <typeparam name="TValue">Value type.</typeparam> /// <param name="sectionDescriptor">CacheSectionDescriptor.</param> /// <returns>Cache section.</returns> public ICacheSection <TValue> GetOrCreateSection <TValue>(ICacheSectionDescriptor <TValue> sectionDescriptor) { ICacheSection cacheSection = _sections.GetOrAdd(sectionDescriptor.SectionName, sectionName => CreateCacheSection(sectionName, sectionDescriptor.CacheSettings)); return((ICacheSection <TValue>)cacheSection); }
/// <summary>Begins the section, create a new section and returns it.</summary> /// <param name="context">The context.</param> /// <param name="cacheCategory">The cache category.</param> /// <param name="uniqueKey">The unique Key.</param> /// <param name="parentCacheSection">The parent cache section.</param> /// <param name="autoLoad">The auto Load.</param> /// <returns>The <see cref="CacheSection"/>.</returns> public static CacheSection Begin(IWebGreaseContext context, string cacheCategory, string uniqueKey, ICacheSection parentCacheSection = null, bool autoLoad = true) { var cacheSection = new CacheSection { parent = parentCacheSection as CacheSection, cacheCategory = cacheCategory, context = context, UniqueKey = uniqueKey }; cacheSection.absolutePath = context.Cache.GetAbsoluteCacheFilePath(cacheSection.cacheCategory, context.GetValueHash(cacheSection.UniqueKey) + ".cache.json"); if (cacheSection.parent != null) { cacheSection.parent.AddChildCacheSection(cacheSection); } EnsureCachePath(context, cacheCategory); if (autoLoad) { cacheSection.Load(); } return(cacheSection); }
/// <summary>Sets the import source dependencies.</summary> /// <param name="fileContent">The file content.</param> /// <param name="workingFolder">The working folder.</param> /// <param name="cacheSection">The cache section.</param> private static void SetImportSourceDependencies(string fileContent, string workingFolder, ICacheSection cacheSection) { var matches = ImportPattern.Matches(fileContent); foreach (Match match in matches) { var path = Path.Combine(workingFolder, match.Groups["path"].Value); var fi = new FileInfo(path); cacheSection.AddSourceDependency(path); if (fi.Exists) { SetImportSourceDependencies(File.ReadAllText(fi.FullName), fi.DirectoryName, cacheSection); } } }
/// <summary> /// Gets or creates cache section by provided settings. /// </summary> /// <typeparam name="TValue">Value type.</typeparam> /// <param name="sectionName">Section name.</param> /// <param name="cacheSettings">Cache settings.</param> /// <returns>Cache section.</returns> public ICacheSection <TValue> GetOrCreateSection <TValue>(string sectionName, ICacheSettings <TValue> cacheSettings) { ICacheSection cacheSection = _sections.GetOrAdd(sectionName, name => CreateCacheSection(name, cacheSettings)); return((ICacheSection <TValue>)cacheSection); }
/// <summary>Initializes a new instance of the <see cref="WebGreaseContext"/> class. The web grease context.</summary> /// <param name="configuration">The configuration</param> /// <param name="logManager">The log Manager.</param> /// <param name="parentCacheSection">The parent Cache Section.</param> /// <param name="preprocessingManager">The preprocessing Manager.</param> public WebGreaseContext(WebGreaseConfiguration configuration, LogManager logManager, ICacheSection parentCacheSection = null, PreprocessingManager preprocessingManager = null) { var runStartTime = DateTimeOffset.Now; configuration.Validate(); var timeMeasure = configuration.Measure ? new TimeMeasure() as ITimeMeasure : new NullTimeMeasure(); var cacheManager = configuration.CacheEnabled ? new CacheManager(configuration, logManager, parentCacheSection) as ICacheManager : new NullCacheManager(); this.Initialize( configuration, logManager, cacheManager, preprocessingManager != null ? new PreprocessingManager(preprocessingManager) : new PreprocessingManager(configuration, logManager, timeMeasure), runStartTime, timeMeasure); }
/// <summary>Ends the cache section.</summary> /// <param name="cacheSection">The cache section.</param> public void EndSection(ICacheSection cacheSection) { }