public PersistentBlobCache( string cacheDirectory = null, IFilesystemProvider filesystemProvider = null, IScheduler scheduler = null, Action <AsyncSubject <byte[]> > invalidateCallback = null) { BlobCache.EnsureInitialized(); this.filesystem = filesystemProvider ?? Locator.Current.GetService <IFilesystemProvider>(); if (this.filesystem == null) { throw new Exception("No IFilesystemProvider available. This should never happen, your DependencyResolver is broken"); } this.CacheDirectory = cacheDirectory ?? filesystem.GetDefaultRoamingCacheDirectory(); this.Scheduler = scheduler ?? BlobCache.TaskpoolScheduler; // Here, we're not actually caching the requests directly (i.e. as // byte[]s), but as the "replayed result of the request", in the // AsyncSubject - this makes the code infinitely simpler because // we don't have to keep a separate list of "in-flight reads" vs // "already completed and cached reads" memoizedRequests = new MemoizingMRUCache <string, AsyncSubject <byte[]> >( (x, c) => FetchOrWriteBlobFromDisk(x, c, false), 20, invalidateCallback); var cacheIndex = FetchOrWriteBlobFromDisk(BlobCacheIndexKey, null, true) .Catch(Observable.Return(new byte[0])) .Select(x => Encoding.UTF8.GetString(x, 0, x.Length).Split('\n') .SelectMany(ParseCacheIndexEntry) .ToDictionary(y => y.Key, y => y.Value)) .Select(x => new ConcurrentDictionary <string, CacheIndexEntry>(x)); cacheIndex.Subscribe(x => CacheIndex = x); flushThreadSubscription = Disposable.Empty; if (!ModeDetector.InUnitTestRunner()) { flushThreadSubscription = actionTaken .Where(_ => CacheIndex != null) .Throttle(TimeSpan.FromSeconds(30), Scheduler) .SelectMany(_ => FlushCacheIndex(true)) .Subscribe(_ => this.Log().Debug("Flushing cache")); } this.Log().Info("{0} entries in blob cache index", CacheIndex.Count); }
public PersistentBlobCache( string cacheDirectory = null, IFilesystemProvider filesystemProvider = null, IScheduler scheduler = null, Action<AsyncSubject<byte[]>> invalidateCallback = null) { BlobCache.EnsureInitialized(); this.filesystem = filesystemProvider ?? Locator.Current.GetService<IFilesystemProvider>(); if (this.filesystem == null) { throw new Exception("No IFilesystemProvider available. This should never happen, your DependencyResolver is broken"); } this.CacheDirectory = cacheDirectory ?? filesystem.GetDefaultRoamingCacheDirectory(); this.Scheduler = scheduler ?? BlobCache.TaskpoolScheduler; // Here, we're not actually caching the requests directly (i.e. as // byte[]s), but as the "replayed result of the request", in the // AsyncSubject - this makes the code infinitely simpler because // we don't have to keep a separate list of "in-flight reads" vs // "already completed and cached reads" memoizedRequests = new MemoizingMRUCache<string, AsyncSubject<byte[]>>( (x, c) => FetchOrWriteBlobFromDisk(x, c, false), 20, invalidateCallback); var cacheIndex = FetchOrWriteBlobFromDisk(BlobCacheIndexKey, null, true) .Catch(Observable.Return(new byte[0])) .Select(x => Encoding.UTF8.GetString(x, 0, x.Length).Split('\n') .SelectMany(ParseCacheIndexEntry) .ToDictionary(y => y.Key, y => y.Value)) .Select(x => new ConcurrentDictionary<string, CacheIndexEntry>(x)); cacheIndex.Subscribe(x => CacheIndex = x); flushThreadSubscription = Disposable.Empty; if (!ModeDetector.InUnitTestRunner()) { flushThreadSubscription = actionTaken .Where(_ => CacheIndex != null) .Throttle(TimeSpan.FromSeconds(30), Scheduler) .SelectMany(_ => FlushCacheIndex(true)) .Subscribe(_ => this.Log().Debug("Flushing cache")); } this.Log().Info("{0} entries in blob cache index", CacheIndex.Count); }
protected PersistentBlobCache( string cacheDirectory = null, IFilesystemProvider filesystemProvider = null, IScheduler scheduler = null, Action<AsyncSubject<byte[]>> invalidateCallback = null) { #if SILVERLIGHT this.filesystem = filesystemProvider ?? new IsolatedStorageProvider(); #else this.filesystem = filesystemProvider ?? new SimpleFilesystemProvider(); #endif this.CacheDirectory = cacheDirectory ?? filesystem.GetDefaultRoamingCacheDirectory(); this.Scheduler = scheduler ?? RxApp.TaskpoolScheduler; // Here, we're not actually caching the requests directly (i.e. as // byte[]s), but as the "replayed result of the request", in the // AsyncSubject - this makes the code infinitely simpler because // we don't have to keep a separate list of "in-flight reads" vs // "already completed and cached reads" memoizedRequests = new MemoizingMRUCache<string, AsyncSubject<byte[]>>( (x, c) => FetchOrWriteBlobFromDisk(x, c, false), 20, invalidateCallback); try { var dir = filesystem.CreateRecursive(CacheDirectory); #if WINRT // NB: I don't want to talk about it. dir.Wait(); #endif } catch (Exception ex) { this.Log().FatalException("Couldn't create cache directory", ex); } var cacheIndex = FetchOrWriteBlobFromDisk(BlobCacheIndexKey, null, true) .Catch(Observable.Return(new byte[0])) .Select(x => Encoding.UTF8.GetString(x, 0, x.Length).Split('\n') .SelectMany(ParseCacheIndexEntry) .ToDictionary(y => y.Key, y => y.Value)) .Select(x => new ConcurrentDictionary<string, CacheIndexEntry>(x)); #if WINRT CacheIndex = cacheIndex.First(); #else cacheIndex.Subscribe(x => CacheIndex = x); #endif flushThreadSubscription = Disposable.Empty; if (!RxApp.InUnitTestRunner()) { flushThreadSubscription = actionTaken .Where(_ => CacheIndex != null) .Throttle(TimeSpan.FromSeconds(30), Scheduler) .SelectMany(_ => FlushCacheIndex(true)) .Subscribe(_ => this.Log().Debug("Flushing cache")); } this.Log().Info("{0} entries in blob cache index", CacheIndex.Count); }
public string GetDefaultRoamingCacheDirectory() { return(_inner.GetDefaultRoamingCacheDirectory()); }