/// <summary>
        /// Performs key-value loop up in staging area and file cache.
        /// Any error manifests itself as a miss, i.e. returns false.
        /// </summary>
        /// <param name="key">The cache key.</param>
        /// <returns>
        /// true if the image is found in staging area or File cache,
        /// false if not found.
        /// </returns>
        private bool CheckInStagingAreaAndFileCache(ICacheKey key)
        {
            EncodedImage result = _stagingArea.Get(key);

            if (result != null)
            {
                result.Dispose();
                Debug.WriteLine($"Found image for { key.ToString() } in staging area");
                _imageCacheStatsTracker.OnStagingAreaHit();
                return(true);
            }
            else
            {
                Debug.WriteLine($"Did not find image for { key.ToString() } in staging area");
                _imageCacheStatsTracker.OnStagingAreaMiss();

                try
                {
                    return(_fileCache.HasKey(key));
                }
                catch (Exception)
                {
                    return(false);
                }
            }
        }
        private Task <EncodedImage> GetAsync(ICacheKey key, AtomicBoolean isCancelled)
        {
            try
            {
                if (isCancelled.Value)
                {
                    throw new OperationCanceledException();
                }

                EncodedImage result = _stagingArea.Get(key);
                if (result != null)
                {
                    Debug.WriteLine($"Found image for { key.ToString() } in staging area");
                    _imageCacheStatsTracker.OnStagingAreaHit();
                }
                else
                {
                    Debug.WriteLine($"Did not find image for { key.ToString() } in staging area");
                    _imageCacheStatsTracker.OnStagingAreaMiss();
                    try
                    {
                        IPooledByteBuffer buffer = ReadFromDiskCache(key);
                        if (buffer == null)
                        {
                            return(Task.FromResult(default(EncodedImage)));
                        }

                        CloseableReference <IPooledByteBuffer> reference =
                            CloseableReference <IPooledByteBuffer> .of(buffer);

                        try
                        {
                            result = new EncodedImage(reference);
                        }
                        finally
                        {
                            CloseableReference <IPooledByteBuffer> .CloseSafely(reference);
                        }
                    }
                    catch (Exception)
                    {
                        return(Task.FromResult(default(EncodedImage)));
                    }
                }

                return(Task.FromResult(result));
            }
            catch (Exception)
            {
                // Log failure
                // TODO: 3697790
                Debug.WriteLine($"Failed to schedule disk-cache read for { key.ToString() }");
                throw;
            }
        }
        /// <summary>
        /// Removes the item from the disk cache and the staging area.
        /// </summary>
        public Task Remove(ICacheKey key)
        {
            Preconditions.CheckNotNull(key);
            _stagingArea.Remove(key);

            Task writeTask = default(Task);

            _writeToDiskCacheTasks.TryRemove(key, out writeTask);

            try
            {
                return(_writeExecutor.Execute(() =>
                {
                    _stagingArea.Remove(key);
                    _fileCache.Remove(key);
                }));
            }
            catch (Exception)
            {
                // Log failure
                // TODO: 3697790
                Debug.WriteLine($"Failed to schedule disk-cache remove for { key.ToString() }");
                throw;
            }
        }
        /// <summary>
        /// Writes to disk cache.
        /// </summary>
        private void WriteToDiskCache(ICacheKey key, EncodedImage encodedImage)
        {
            Debug.WriteLine($"About to write to disk-cache for key { key.ToString() }");

            try
            {
                _fileCache.Insert(key, new WriterCallbackImpl(os =>
                {
                    _pooledByteStreams.Copy(encodedImage.GetInputStream(), os);
                }));

                Debug.WriteLine($"Successful disk-cache write for key { key.ToString() }");
            }
            catch (IOException)
            {
                // Log failure
                // TODO: 3697790
                Debug.WriteLine($"Failed to write to disk-cache for key { key.ToString() }");
            }
        }
        /// <summary>
        /// Performs disk cache read. In case of any exception null is returned.
        /// </summary>
        private IPooledByteBuffer ReadFromDiskCache(ICacheKey key)
        {
            try
            {
                Debug.WriteLine($"Disk cache read for { key.ToString() }");
                IBinaryResource diskCacheResource = _fileCache.GetResource(key);
                if (diskCacheResource == null)
                {
                    Debug.WriteLine($"Disk cache miss for { key.ToString() }");
                    _imageCacheStatsTracker.OnDiskCacheMiss();
                    return(null);
                }
                else
                {
                    Debug.WriteLine($"Found entry in disk cache for { key.ToString() }");
                    _imageCacheStatsTracker.OnDiskCacheHit();
                }

                IPooledByteBuffer byteBuffer;
                using (Stream inputStream = diskCacheResource.OpenStream())
                {
                    byteBuffer = _pooledByteBufferFactory.NewByteBuffer(
                        inputStream,
                        (int)diskCacheResource.GetSize());
                }

                Debug.WriteLine($"Successful read from disk cache for { key.ToString() }");
                return(byteBuffer);
            }
            catch (Exception)
            {
                // TODO: 3697790 log failures
                // TODO: 5258772 - uncomment line below
                // _fileCache.Remove(key);
                Debug.WriteLine($"Exception reading from cache for { key.ToString() }");
                _imageCacheStatsTracker.OnDiskCacheGetFail();
                throw;
            }
        }
예제 #6
0
        public async Task AddAsync <TItem>(ICacheKey key, TItem item)
        {
            _logger.LogTrace($"{TAG} AddAsync called for {key.ToString()}");
            if (item == null)
            {
                return;
            }

            var cacheOptions = new MemoryCacheEntryOptions();

            cacheOptions.SetSlidingExpiration(TimeSpan.FromMinutes(30));
            _logger.LogTrace($"{TAG} Adding item to cache.");
            await Task.Run(() => _cache.Set(key.Key, item, cacheOptions));
        }
 private Task <bool> ContainsAsync(ICacheKey key)
 {
     try
     {
         return(_readExecutor.Execute(() => CheckInStagingAreaAndFileCache(key)));
     }
     catch (Exception)
     {
         // Log failure
         // TODO: 3697790
         Debug.WriteLine($"Failed to schedule disk-cache read for { key.ToString() }");
         throw;
     }
 }
        /// <summary>
        /// Associates encodedImage with given key in disk cache.
        /// Disk write is performed on background thread, so the
        /// caller of this method is not blocked.
        /// </summary>
        public Task Put(ICacheKey key, EncodedImage encodedImage)
        {
            Preconditions.CheckNotNull(key);
            Preconditions.CheckArgument(EncodedImage.IsValid(encodedImage));

            // Store encodedImage in staging area
            _stagingArea.Put(key, encodedImage);

            // Write to disk cache. This will be executed on background thread,
            // so increment the ref count. When this write completes
            // (with success/failure), then we will bump down the ref count again.
            EncodedImage finalEncodedImage = EncodedImage.CloneOrNull(encodedImage);

            try
            {
                Task writeTask = _writeExecutor.Execute(() =>
                {
                    try
                    {
                        WriteToDiskCache(key, finalEncodedImage);
                    }
                    finally
                    {
                        _stagingArea.Remove(key, finalEncodedImage);
                        EncodedImage.CloseSafely(finalEncodedImage);

                        // Removes write task after it's completed.
                        Task writeTaskCompleted = default(Task);
                        _writeToDiskCacheTasks.TryRemove(key, out writeTaskCompleted);
                    }
                });

                _writeToDiskCacheTasks.TryAdd(key, writeTask);
                return(writeTask);
            }
            catch (Exception)
            {
                // We failed to enqueue cache write. Log failure and decrement ref count
                // TODO: 3697790
                Debug.WriteLine($"Failed to schedule disk-cache write for { key.ToString() }");
                _stagingArea.Remove(key, encodedImage);
                EncodedImage.CloseSafely(finalEncodedImage);

                // Removes write task due to error.
                Task writeTaskCompleted = default(Task);
                _writeToDiskCacheTasks.TryRemove(key, out writeTaskCompleted);
                throw;
            }
        }
예제 #9
0
 private static string SecureHashKey(ICacheKey key)
 {
     byte[] utf8Bytes = Encoding.UTF8.GetBytes(key.ToString());
     return(SecureHashUtil.MakeSHA1HashBase64(utf8Bytes));
 }
예제 #10
0
        /// <summary>
        /// Determine if an valid entry for the key exists in the staging area.
        /// </summary>
        public bool ContainsKey(ICacheKey key)
        {
            lock (_mapGate)
            {
                Preconditions.CheckNotNull(key);
                EncodedImage storedEncodedImage = default(EncodedImage);
                if (!_map.TryGetValue(key, out storedEncodedImage))
                {
                    return(false);
                }

                if (!EncodedImage.IsValid(storedEncodedImage))
                {
                    // Reference is not valid, this means that someone cleared reference
                    // while it was still in use.
                    // Log error TODO: 3697790
                    _map.Remove(key);
                    Debug.WriteLine($"Found closed reference { storedEncodedImage.GetHashCode() } for key { key.ToString() } ({ key.GetHashCode() })");
                    return(false);
                }

                return(true);
            }
        }
예제 #11
0
 public async Task <TItem> GetAsync <TItem>(ICacheKey key) where TItem : class
 {
     _logger.LogTrace($"{TAG} GetAsync called for {key.ToString()}");
     return(await Task.Run(() => _cache.Get <TItem>(key.Key)));
 }
 private Task <EncodedImage> FoundPinnedImage(ICacheKey key, EncodedImage pinnedImage)
 {
     Debug.WriteLine($"Found image for { key.ToString() } in staging area");
     _imageCacheStatsTracker.OnStagingAreaHit();
     return(Task.FromResult(pinnedImage));
 }