private byte[] GetBytesFromStorageFile(BinaryIndex index) { byte[] data = null; using (FileStream fs = File.Open(this.storageFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { fs.Seek(index.Reference.Offset, SeekOrigin.Begin); data = new byte[index.Reference.Length]; fs.Read(data, 0, data.Length); } return(data); }
private BinaryIndex CreateBinaryIndex(byte[] data, long[] compressedChunksLength, StreamInfo parameters) { long offset = GetStorageFileLength() + this.storageBufferLength; BinaryIndex result = new BinaryIndex() { Reference = new BinaryReference() { Offset = offset, Length = data.Length, CompressedChunksLength = compressedChunksLength }, Information = parameters }; return(result); }
public void Add(string key, Stream data, StreamInfo parameters) { if (key == null) { throw new ArgumentNullException("key is null"); } if (data == null) { throw new ArgumentNullException("data is null"); } if (parameters == null) { throw new ArgumentNullException("parameters is null"); } if (CheckContains(key)) { throw new ArgumentException("An element with the same key already exists or provided hash or length does not match the data"); } CheckMaxIndexFile(); StreamInfo cloneParameters = (StreamInfo)parameters.Clone(); long firstBufferLength = MAX_BUFFER_ADD_SIZE; if (this.storageConfiguration.CompressionThreshold > 0) { firstBufferLength = this.storageConfiguration.CompressionThreshold + 1; } List <byte> outputBytes = new List <byte>(); List <long> compressedChunksLength = new List <long>(); using (MD5 hasher = MD5.Create()) { hasher.Initialize(); byte[] buffer = new byte[firstBufferLength]; int read = data.Read(buffer, 0, (int)firstBufferLength); if (read < firstBufferLength) { buffer = buffer.Take(read).ToArray(); } bool needCompressed = false; if (!parameters.IsCompressed && (read > this.storageConfiguration.CompressionThreshold)) { needCompressed = true; outputBytes.AddRange(CompressBytes(buffer, 0, read)); cloneParameters.IsManuallyCompressed = true; compressedChunksLength.Add(outputBytes.Count); } else { outputBytes.AddRange(buffer); } hasher.TransformBlock(buffer, 0, read, null, 0); buffer = new byte[MAX_BUFFER_ADD_SIZE]; while ((read = data.Read(buffer, 0, MAX_BUFFER_ADD_SIZE)) > 0) { if (needCompressed) { byte[] compressedChunk = CompressBytes(buffer, 0, read); outputBytes.AddRange(compressedChunk); compressedChunksLength.Add(compressedChunk.Length); } else { outputBytes.AddRange(buffer); } hasher.TransformBlock(buffer, 0, read, null, 0); } // https://stackoverflow.com/questions/3621283/compute-a-hash-from-a-stream-of-unknown-length-in-c-sharp hasher.TransformFinalBlock(new byte[0], 0, 0); byte[] hash = hasher.Hash; if (parameters.Hash != null) { CheckHash(hash, parameters); } else { cloneParameters.Hash = hash; } } lock (_lockObject) { byte[] dataBytes = outputBytes.ToArray(); BinaryIndex index = FindBinaryIndexByHash(cloneParameters); bool isNew = false; if (index == null) { CheckMaxStorageFile(dataBytes); index = CreateBinaryIndex(dataBytes, compressedChunksLength.ToArray(), cloneParameters); isNew = true; } if (!this.indexTableBuffer.TryAdd(key, index)) { throw new ArgumentException("An element with the same key already exists"); } else if (isNew) { storageBufferLength += outputBytes.Count; this.storageBuffer.Enqueue(dataBytes); } FlushBuffer(); } }