/// <summary> /// stores the bitmap data on disk with filename key /// </summary> /// <param name="key"> /// filename </param> /// <param name="bitmap"> /// tile image </param> private void StoreData(Job key, ITileBitmap bitmap) { try { IFile file = GetOutputFile(key); if (file == null) { // if the file cannot be written, silently return return; } using (System.IO.Stream outputStream = file.OpenAsync(FileAccess.ReadAndWrite).Result) { bitmap.Compress(outputStream); try { //@lock.writeLock().@lock(); if (this.lruCache.Add(key.Key, file) != null) { LOGGER.Warn("overwriting cached entry: " + key.Key); } } finally { //@lock.writeLock().unlock(); } } } catch (Exception e) { // we are catching now any exception and then disable the file cache // this should ensure that no exception in the storage thread will // ever crash the main app. If there is a runtime exception, the thread // will exit (via destroy). LOGGER.Fatal("Disabling filesystem cache", e); // most likely cause is that the disk is full, just disable the // cache otherwise // more and more exceptions will be thrown. this.Destroy(); try { //@lock.writeLock().@lock(); this.lruCache = new FileWorkingSetCache <string>(0); } finally { //@lock.writeLock().unlock(); } } }
/// <summary> /// Creates a new FileSystemTileCache. /// <para> /// Use the {@code persistent} argument to specify whether cache contents should be kept across instances. A /// persistent cache will serve any tiles it finds in {@code cacheDirectory}. Calling <seealso cref="#destroy()"/> on a /// persistent cache will not delete the cache directory. Conversely, a non-persistent cache will serve only tiles /// added to it via the <seealso cref="#put(Job, TileBitmap)"/> method, and calling <seealso cref="#destroy()"/> on a non-persistent /// cache will delete {@code cacheDirectory}. /// /// </para> /// </summary> /// <param name="capacity"> /// the maximum number of entries in this cache. </param> /// <param name="cacheDirectory"> /// the directory where cached tiles will be stored. </param> /// <param name="graphicFactory"> /// the graphicFactory implementation to use. </param> /// <param name="persistent"> /// if cache data will be kept between instances </param> /// <exception cref="IllegalArgumentException"> /// if the capacity is negative. </exception> /// <exception cref="IllegalArgumentException"> /// if the capacity is negative. </exception> public FileSystemTileCache(int capacity, IFolder cacheDirectory, IGraphicFactory graphicFactory, bool persistent) { this.observable = new Observable(); this.persistent = persistent; this.lruCache = new FileWorkingSetCache <string>(capacity); //this.@lock = new ReentrantReadWriteLock(); if (IsValidCacheDirectory(cacheDirectory)) { this.cacheDirectory = cacheDirectory; if (this.persistent) { // this will start a new thread to read in the cache directory. // there is the potential that files will be recreated because they // are not yet in the cache, but this will not cause any corruption. Task.Run(() => (new CacheDirectoryReader(this)).Run()); } } else { this.cacheDirectory = null; } this.graphicFactory = graphicFactory; }