Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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();
            }
        }