Beispiel #1
0
        /// <summary>
        /// Read data from the stream into the specified buffer and increment the stream position.
        /// </summary>
        /// <param name="buffer">Byte array to use as a buffer.</param>
        /// <param name="offset">The offset within the buffer indicating where to copy the read data.</param>
        /// <param name="count">The number of bytes to populate within the buffer.</param>
        /// <returns>An integer representing the number of bytes read.</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException("Offset must be zero or greater.");
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("Count must be zero or greater.");
            }
            if ((offset + count) > buffer.Length)
            {
                throw new ArgumentOutOfRangeException("Offset and count combined must not exceed buffer length.");
            }
            if (offset >= Length)
            {
                return(0);
            }

            DedupeObjectMap map = _Database.GetObjectMapForPosition(_Metadata.Key, _Position);

            if (map == null)
            {
                return(0);
            }

            if (map.ChunkAddress > Position)
            {
                throw new IOException("Data error while reading chunks from object.");
            }

            byte[] chunkData = _Callbacks.ReadChunk(map.ChunkKey);

            int chunkDataReadStart = 0;

            if (map.ChunkAddress < Position)
            {
                chunkDataReadStart += (int)(Position - map.ChunkAddress);
            }

            int bytesAvailInChunk = (int)(map.ChunkLength - chunkDataReadStart);

            if (count >= bytesAvailInChunk)
            {
                Buffer.BlockCopy(chunkData, chunkDataReadStart, buffer, offset, bytesAvailInChunk);
                _Position += bytesAvailInChunk;
                return(bytesAvailInChunk);
            }
            else
            {
                Buffer.BlockCopy(chunkData, chunkDataReadStart, buffer, offset, count);
                _Position += count;
                return(count);
            }
        }
        /// <summary>
        /// Retrieve an object from the deduplication index.
        /// This method will use the callbacks supplied in the method signature.
        /// </summary>
        /// <param name="key">The object key.</param>
        /// <param name="callbacks">CallbackMethods object containing callback methods.</param>
        /// <returns>Object data.</returns>
        public DedupeObject Get(string key, DedupeCallbacks callbacks)
        {
            if (String.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (callbacks == null)
            {
                throw new ArgumentNullException(nameof(callbacks));
            }
            if (callbacks.ReadChunk == null)
            {
                throw new ArgumentException("ReadChunk callback must be specified.");
            }
            key = DedupeCommon.SanitizeString(key);

            DedupeObject md = _Database.GetObjectMetadata(key);

            if (md == null)
            {
                throw new KeyNotFoundException("Object key '" + key + "' not found.");
            }
            if (md.Chunks == null || md.Chunks.Count < 1)
            {
                throw new IOException("No chunks returned for object key '" + key + "'.");
            }

            MemoryStream stream        = new MemoryStream();
            long         contentLength = 0;

            foreach (DedupeObjectMap curr in md.ObjectMap)
            {
                byte[] chunkData = callbacks.ReadChunk(curr.ChunkKey);
                if (chunkData == null || chunkData.Length < 1)
                {
                    throw new IOException("Unable to read chunk '" + curr.ChunkKey + "'.");
                }

                stream.Write(chunkData, 0, chunkData.Length);
                contentLength += chunkData.Length;
            }

            if (contentLength > 0)
            {
                stream.Seek(0, SeekOrigin.Begin);
            }

            md.DataStream = stream;
            return(md);
        }