Exemplo n.º 1
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>
        /// Processes the get command
        /// </summary>
        /// <param name="stream">The stream to the client</param>
        private void ProcessGet(NetworkStream stream)
        {
            // Read ID
            Guid   id   = UnityCacheUtilities.ReadGuid(stream);
            string hash = UnityCacheUtilities.ReadHash(stream);

            if (!CacheFile.IsFileCached(this.fileManager.Root, id, hash))
            {
                logger.Info("GET: Cache miss. {0} {1}", id, hash);

                // File is not cached
                // Send command it's not cached
                byte[] code = new byte[1];
                code[0] = 45;
                stream.Write(code, 0, 1);

                // Send id and hash
                UnityCacheUtilities.SendIdAndHashOnStream(stream, id, hash);
            }
            else
            {
                logger.Info("GET: Cache hit. {0} {1}", id, hash);

                using (MemoryStream memoryStream = new MemoryStream(49))
                {
                    // File is cached, send the response
                    byte[] code = new byte[1];
                    code[0] = 43;
                    memoryStream.Write(code, 0, 1);

                    // Send the file size in bytes
                    ulong  bytesToBeWritten = CacheFile.GetFileSizeBytes(this.fileManager.Root, id, hash);  // Dumb off by 1 hack
                    byte[] fileSizeBytes    = UnityCacheUtilities.GetUlongAsAsciiBytes(bytesToBeWritten);
                    memoryStream.Write(fileSizeBytes, 0, fileSizeBytes.Length);

                    // Send id and hash
                    UnityCacheUtilities.SendIdAndHashOnStream(memoryStream, id, hash);

                    // Send the file bytes
                    FileStream fileStream = this.fileManager.GetReadFileStream(id, hash);
                    byte[]     buffer     = new byte[this.streamBlockSize];

                    // Workaround to get enough bytes into a single packet so the Unity client doesn't choke
                    byte[] header = memoryStream.GetBuffer();
                    stream.Write(header, 0, header.Length);

                    while (bytesToBeWritten > 0)
                    {
                        int byteCount = (bytesToBeWritten > (ulong)this.streamBlockSize) ? this.streamBlockSize : (int)bytesToBeWritten;
                        fileStream.Read(buffer, 0, byteCount);
                        bytesToBeWritten -= (ulong)byteCount;
                        stream.Write(buffer, 0, byteCount);
                    }

                    fileStream.Close();
                }
            }

            // Notify listeners a get was processed
            if (this.OnGetProcessed != null)
            {
                this.OnGetProcessed(this, new EventArgs());
            }
        }