Example #1
0
        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);
        }
Example #3
0
        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());
 }