/// <summary>
        /// Inserts resource into file with key.
        /// </summary>
        /// <param name="key">Cache key.</param>
        /// <param name="callback">
        /// Callback that writes to an output stream.
        /// </param>
        /// <returns>A sequence of bytes.</returns>
        public IBinaryResource Insert(ICacheKey key, IWriterCallback callback)
        {
            // Write to a temp file, then move it into place.
            // This allows more parallelism when writing files.
            SettableCacheEvent cacheEvent = SettableCacheEvent.Obtain().SetCacheKey(key);

            _cacheEventListener.OnWriteAttempt(cacheEvent);
            string resourceId;

            lock (_lock)
            {
                // For multiple resource ids associated with the same image,
                // we only write one file
                resourceId = CacheKeyUtil.GetFirstResourceId(key);
            }

            cacheEvent.SetResourceId(resourceId);

            try
            {
                // Getting the file is synchronized
                IInserter inserter = StartInsert(resourceId, key);

                try
                {
                    inserter.WriteData(callback, key);

                    // Committing the file is synchronized
                    IBinaryResource resource = EndInsert(inserter, key, resourceId);
                    cacheEvent.SetItemSize(resource.GetSize())
                    .SetCacheSize(_cacheStats.Size);

                    _cacheEventListener.OnWriteSuccess(cacheEvent);
                    return(resource);
                }
                finally
                {
                    if (!inserter.CleanUp())
                    {
                        Debug.WriteLine("Failed to delete temp file");
                    }
                }
            }
            catch (IOException ioe)
            {
                cacheEvent.SetException(ioe);
                _cacheEventListener.OnWriteException(cacheEvent);
                Debug.WriteLine("Failed inserting a file into the cache");
                throw;
            }
            finally
            {
                cacheEvent.Recycle();
            }
        }
 /// <summary>
 /// Commits the provided temp file to the cache, renaming it to match
 /// the cache's hashing convention.
 /// </summary>
 private IBinaryResource EndInsert(
     IInserter inserter,
     ICacheKey key,
     string resourceId)
 {
     lock (_lock)
     {
         IBinaryResource resource = inserter.Commit(key);
         _resourceIndex.Add(resourceId);
         _cacheStats.Increment(resource.GetSize(), 1);
         return(resource);
     }
 }
        /// <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;
            }
        }