/// <summary>
        /// Gets the file size of a given file
        /// </summary>
        /// <param name="root">The root folder of the cache</param>
        /// <param name="id">The Id of the file to get the size of</param>
        /// <param name="hash">The has of the file</param>
        /// <returns>The file size in bytes</returns>
        public static ulong GetFileSizeBytes(string root, Guid id, string hash)
        {
            // TODO: Replace all string.Format with Path.Join
            FileInfo info = new FileInfo(CacheFile.GetFullFilePath(root, id, hash));

            return((ulong)info.Length);
        }
Example #2
0
        /// <summary>
        /// Walks through all assets in the file system and evicts any items that occur in the past
        /// to take the cache file system below the requested limit.
        /// This should only be called in a background thread since this is a time intensive operation.
        /// </summary>
        /// <param name="state">Ignored, object state</param>
        private void Evict(object state)
        {
            ulong cacheLimitBytes = (ulong)Settings.Default.MaxCacheSizeMB * 1048576;

            if (this.cacheSizeBytes < cacheLimitBytes)
            {
                // Cache isn't big enough to evict
                logger.Info(
                    "Cache isn't large enough to require eviction.  Max: {0} MB, Current: {1} MB",
                    Settings.Default.MaxCacheSizeMB,
                    this.cacheSizeBytes / 1048576);
                return;
            }

            logger.Warn(
                "Cache eviction is starting to prune.  Max: {0} MB, Current: {1} MB",
                Settings.Default.MaxCacheSizeMB,
                this.cacheSizeBytes / 1048576);

            List <CacheFile> fileData = this.EnumerateAllCacheFiles();

            // Run the list of elements and delete the files that were accessed the furthest in the past
            var filesSorted = from a in fileData
                              orderby a.LastAccessed ascending
                              select a;
            IEnumerator <CacheFile> fileEnumerator = filesSorted.GetEnumerator();

            fileEnumerator.MoveNext();

            // Delete files until we are within 90% of the limit
            while (this.cacheSizeBytes > (cacheLimitBytes * Settings.Default.CacheFreePercentage))
            {
                CacheFile file = fileEnumerator.Current;

                lock (this.cacheSizeBytesLock)
                {
                    this.cacheSizeBytes -= (ulong)file.Length;
                }

                logger.Warn(
                    "Deleting last accessed {1} file {0}",
                    file.LastAccessed,
                    CacheFile.GetFileName(file.Id, file.Hash));
                File.Delete(CacheFile.GetFullFilePath(this.root, file.Id, file.Hash));

                if (!fileEnumerator.MoveNext())
                {
                    // There are no more files to clean
                    break;
                }
            }

            logger.Warn(
                "Cache eviction is complete.  Max: {0} MB, Current: {1} MB",
                Settings.Default.MaxCacheSizeMB,
                this.cacheSizeBytes / 1048576);
            this.evictingCache = false;
        }
        /// <summary>
        /// Loads the details of the files
        /// </summary>
        /// <param name="root">The root folder of the cache</param>
        /// <param name="id">The id of the file</param>
        /// <param name="hash">The hash of the file</param>
        public void Load(string root, Guid id, string hash)
        {
            string path = CacheFile.GetFullFilePath(root, id, hash);

            FileInfo info = new FileInfo(path);

            this.Id           = id;
            this.Hash         = hash;
            this.LastAccessed = File.GetLastAccessTime(path);
            this.Length       = (int)info.Length;
        }
Example #4
0
        /// <summary>
        /// Moves the file from the incoming temporary folder and moves it to permanent storage.
        /// The file is automatically marked as recently accessed in order to prevent it from being evicted.
        /// </summary>
        /// <param name="id">The Id of the file</param>
        /// <param name="hash">The hash of the file</param>
        public void CompleteFile(Guid id, string hash)
        {
            string fileName = CacheFile.GetFileName(id, hash);

            string src  = Path.Combine(this.incoming, fileName);
            string dest = CacheFile.GetFullFilePath(this.root, id, hash);

            if (!Directory.Exists(Path.GetDirectoryName(dest)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(dest));
            }

            // For some reason the cache server is asking to overwrite the file,
            if (CacheFile.IsFileCached(this.root, id, hash))
            {
                File.Delete(CacheFile.GetFullFilePath(this.root, id, hash));
            }

            File.Move(src, dest);
            File.SetLastAccessTime(dest, DateTime.Now);

            FileInfo info = new FileInfo(dest);

            lock (this.cacheSizeBytesLock)
            {
                // Increment the cache size by adding a file
                this.cacheSizeBytes += (ulong)info.Length;
                int limit = Settings.Default.MaxCacheSizeMB * 1048576;

                // Check we haven't exceeded the cap
                if (this.cacheSizeBytes > (ulong)limit && !this.evictingCache)
                {
                    // We've exceeded the cache cap, request a cleanup
                    this.evictingCache = true;
                    ThreadPool.QueueUserWorkItem(new WaitCallback(this.Evict));
                }
            }

            // Store a hit on the ojbect
            File.SetLastAccessTime(dest, DateTime.Now);

            logger.Info(CultureInfo.CurrentCulture, "Moving {0} to permanent cache", fileName);
        }
 /// <summary>
 /// Determines if the given file is cached or not
 /// </summary>
 /// <param name="root">The root folder of the cache</param>
 /// <param name="id">The Id of the file</param>
 /// <param name="hash">The hash of the file</param>
 /// <returns>True if the file is cached, false otherwise</returns>
 public static bool IsFileCached(string root, Guid id, string hash)
 {
     return(File.Exists(CacheFile.GetFullFilePath(root, id, hash)));
 }