Beispiel #1
0
 private Task RunInsertionInSeparateThread(ICacheKey key, IWriterCallback callback)
 {
     return(Task.Run(() =>
     {
         _cache.Insert(key, callback);
     }));
 }
        /// <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();
            }
        }
Beispiel #3
0
            /// <summary>
            /// Update the contents of the resource to be inserted. Executes
            /// outside the session lock. The writer callback will be provided
            /// with an output Stream to write to. For high efficiency client
            /// should make sure that data is written in big chunks (for example
            /// by employing BufferedInputStream or writing all data at once).
            /// </summary>
            /// <param name="callback">The write callback.</param>
            /// <param name="debugInfo">Helper object for debugging.</param>
            public void WriteData(IWriterCallback callback, object debugInfo)
            {
                FileStream fileStream;

                try
                {
                    fileStream = _temporaryFile.Create();
                }
                catch (Exception)
                {
                    _parent._cacheErrorLogger.LogError(
                        CacheErrorCategory.WRITE_UPDATE_FILE_NOT_FOUND,
                        typeof(DefaultDiskStorage),
                        "updateResource");

                    throw;
                }

                long length;

                try
                {
                    callback.Write(fileStream);

                    // Just in case underlying stream's close method doesn't flush:
                    // we flush it manually and inside the try/catch
                    fileStream.Flush();
                    length = fileStream.Position;
                }
                finally
                {
                    // If it fails to close (or write the last piece) we really want
                    // to know. Normally we would want this to be quiet because a
                    // closing exception would hide one inside the try, but now we
                    // really want to know if something fails at Flush or Close
                    fileStream.Dispose();
                }

                // This code should never throw, but if filesystem doesn't fail on a
                // failing /uncomplete close we want to know and manually fail
                if (_temporaryFile.Length != length)
                {
                    throw new IncompleteFileException(length, _temporaryFile.Length);
                }
            }
Beispiel #4
0
        public void TestSizeEvictionClearsIndex()
        {
            _clock.SetDateTime(DateTime.Now.Add(TimeSpan.FromDays(1)));
            ICacheKey key1 = PutOneThingInCache();
            ICacheKey key2 = new SimpleCacheKey("bar");
            ICacheKey key3 = new SimpleCacheKey("duck");

            byte[] value2 = new byte[(int)FILE_CACHE_MAX_SIZE_HIGH_LIMIT];
            value2[80] = 99; // 'c'
            IWriterCallback callback = WriterCallbacks.From(value2);

            _clock.SetDateTime(DateTime.Now.Add(TimeSpan.FromDays(2)));
            _cache.Insert(key2, callback);

            // Now over limit. Next write will evict key1
            _clock.SetDateTime(DateTime.Now.Add(TimeSpan.FromDays(3)));
            _cache.Insert(key3, callback);
            Assert.IsFalse(_cache.HasKeySync(key1));
            Assert.IsFalse(_cache.HasKey(key1));
            Assert.IsTrue(_cache.HasKeySync(key3));
            Assert.IsTrue(_cache.HasKey(key3));
        }