/// <summary> /// Performs a get synchronously /// </summary> /// <param name="id">The ID of the file to get</param> /// <param name="hash">The hash of the files contents</param> /// <returns>The result of the get operation</returns> public UnityCacheClientGetResult Get(Guid id, string hash) { UnityCacheClientGetResult result = new UnityCacheClientGetResult(); result.Id = id; result.Hash = hash; byte[] command = Encoding.ASCII.GetBytes("g"); this.stream.WriteByte(command[0]); UnityCacheUtilities.SendIdAndHashOnStream(this.stream, id, hash); this.stream.Read(command, 0, command.Length); string strResult = Encoding.ASCII.GetString(command); if (strResult == "-") { result.Result = CacheResult.CacheMiss; // Read and toss the hash since we don't need it UnityCacheUtilities.ReadGuid(this.stream); UnityCacheUtilities.ReadHash(this.stream); } else if (strResult == "+") { result.Result = CacheResult.CacheHit; // Read the length of the file byte[] buffer = new byte[16]; this.stream.Read(buffer, 0, 16); ulong bytesToBeRead = UnityCacheUtilities.GetAsciiBytesAsUInt64(buffer); // Read the ID and hash. Toss this, we don't need it UnityCacheUtilities.ReadGuid(this.stream); UnityCacheUtilities.ReadHash(this.stream); // Read the reply from the server buffer = new byte[bytesToBeRead]; result.Data = buffer; int offset = 0; while (bytesToBeRead > 0) { int len = (bytesToBeRead > (ulong)this.streamBlockSize) ? this.streamBlockSize : (int)bytesToBeRead; ulong bytesReturned = (ulong)this.stream.Read(buffer, offset, len); bytesToBeRead -= (ulong)bytesReturned; offset += (int)bytesReturned; } } return(result); }
/// <summary> /// Process the client put request /// </summary> /// <param name="stream">The stream to the client requesting the put</param> private void ProcessPut(NetworkStream stream) { byte[] buffer = new byte[16]; stream.Read(buffer, 0, 16); ulong bytesToBeRead = UnityCacheUtilities.GetAsciiBytesAsUInt64(buffer); // Read ID Guid id = UnityCacheUtilities.ReadGuid(stream); // Read HASH string hash = UnityCacheUtilities.ReadHash(stream); logger.Info("PUT: {0} {1}", id, hash); FileStream fileStream = this.fileManager.GetTemporaryFile(id, hash); buffer = new byte[this.streamBlockSize]; while (bytesToBeRead > 0) { int len = (bytesToBeRead > (ulong)this.streamBlockSize) ? this.streamBlockSize : (int)bytesToBeRead; ulong bytesReturned = (ulong)stream.Read(buffer, 0, len); fileStream.Write(buffer, 0, (int)bytesReturned); bytesToBeRead -= (ulong)bytesReturned; } fileStream.Close(); this.fileManager.CompleteFile(id, hash); // Notify listeners a get was processed if (this.OnPutProcessed != null) { this.OnPutProcessed(this, new EventArgs()); } }
/// <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()); } }