Пример #1
0
        /// <summary>
        /// Retrieve an object from the deduplication index.
        /// This method will use the callbacks supplied in the method signature.
        /// </summary>
        /// <param name="objectName">The name of the object.</param>
        /// <param name="callbacks">CallbackMethods object containing callback methods.</param>
        /// <param name="contentLength">The length of the data.</param>
        /// <param name="stream">The stream containing the data.</param>
        /// <returns>True if successful.</returns>
        public bool RetrieveObject(string objectName, CallbackMethods callbacks, out long contentLength, out Stream stream)
        {
            stream        = null;
            contentLength = 0;
            if (String.IsNullOrEmpty(objectName))
            {
                throw new ArgumentNullException(nameof(objectName));
            }
            if (callbacks == null)
            {
                throw new ArgumentNullException(nameof(callbacks));
            }
            if (callbacks.ReadChunk == null)
            {
                throw new ArgumentException("ReadChunk callback must be specified.");
            }
            objectName = DedupeCommon.SanitizeString(objectName);

            ObjectMetadata md = null;

            lock (_ChunkLock)
            {
                if (!_Database.GetObjectMetadata(objectName, out md))
                {
                    Log("Unable to retrieve object metadata for object " + objectName);
                    return(false);
                }

                if (md.Chunks == null || md.Chunks.Count < 1)
                {
                    Log("No chunks returned");
                    return(false);
                }

                stream = new MemoryStream();

                foreach (Chunk curr in md.Chunks)
                {
                    byte[] chunkData = callbacks.ReadChunk(curr.Key);
                    if (chunkData == null || chunkData.Length < 1)
                    {
                        Log("Unable to read chunk " + curr.Key);
                        return(false);
                    }

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

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

            return(true);
        }
Пример #2
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);
            }


            Chunk chunk = null;

            if (!_Database.GetChunkForPosition(_Metadata.Name, _Position, out chunk))
            {
                return(0);
            }
            if (chunk == null)
            {
                return(0);
            }
            if (chunk.Address > Position)
            {
                throw new IOException("Data error while reading chunks from object.");
            }

            byte[] chunkData = _Callbacks.ReadChunk(chunk.Key);

            int chunkDataReadStart = 0;

            if (chunk.Address < Position)
            {
                chunkDataReadStart += (int)(Position - chunk.Address);
            }

            int bytesAvailInChunk = (int)(chunk.Length - 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);
            }
        }