Beispiel #1
0
 /// <summary>
 /// Reads data from the stream.
 /// </summary>
 /// <param name="buffer">The buffer to fill</param>
 /// <param name="offset">The first byte in buffer to fill</param>
 /// <param name="count">The requested number of bytes to read</param>
 /// <returns>The actual number of bytes read</returns>
 public override int Read(byte[] buffer, int offset, int count)
 {
     lock (_common)
     {
         SparseStream wrapped = Wrapped;
         wrapped.Position = _position;
         int numRead = wrapped.Read(buffer, offset, count);
         _position += numRead;
         return(numRead);
     }
 }
Beispiel #2
0
 public override int Read(byte[] buffer, int offset, int count)
 {
     return(_wrapped.Read(buffer, offset, count));
 }
Beispiel #3
0
 internal override int Read(long diskOffset, byte[] block, int offset, int count)
 {
     _stream.Position = diskOffset - Start;
     return(_stream.Read(block, offset, count));
 }
Beispiel #4
0
        /// <summary>
        /// Reads data from the stream.
        /// </summary>
        /// <param name="buffer">The buffer to fill</param>
        /// <param name="offset">The buffer offset to start from</param>
        /// <param name="count">The number of bytes to read</param>
        /// <returns>The number of bytes read</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            CheckDisposed();

            if (_position >= Length)
            {
                if (_atEof)
                {
                    throw new IOException("Attempt to read beyond end of stream");
                }
                else
                {
                    _atEof = true;
                    return(0);
                }
            }

            _stats.TotalReadsIn++;

            if (count > _settings.LargeReadSize)
            {
                _stats.LargeReadsIn++;
                _stats.TotalReadsOut++;
                _wrappedStream.Position = _position;
                int numRead = _wrappedStream.Read(buffer, offset, count);
                _position = _wrappedStream.Position;

                if (_position >= Length)
                {
                    _atEof = true;
                }

                return(numRead);
            }

            int  totalBytesRead       = 0;
            bool servicedFromCache    = false;
            bool servicedOutsideCache = false;
            int  blockSize            = _settings.BlockSize;

            long firstBlock        = _position / blockSize;
            int  offsetInNextBlock = (int)(_position % blockSize);
            long endBlock          = Utilities.Ceil(Math.Min(_position + count, Length), blockSize);
            int  numBlocks         = (int)(endBlock - firstBlock);

            if (offsetInNextBlock != 0)
            {
                _stats.UnalignedReadsIn++;
            }

            int blocksRead = 0;

            while (blocksRead < numBlocks)
            {
                Block block;

                // Read from the cache as much as possible
                while (blocksRead < numBlocks && _cache.TryGetBlock(firstBlock + blocksRead, out block))
                {
                    int bytesToRead = Math.Min(count - totalBytesRead, block.Available - offsetInNextBlock);

                    Array.Copy(block.Data, offsetInNextBlock, buffer, offset + totalBytesRead, bytesToRead);
                    offsetInNextBlock = 0;
                    totalBytesRead   += bytesToRead;
                    _position        += bytesToRead;
                    blocksRead++;

                    servicedFromCache = true;
                }

                // Now handle a sequence of (one or more) blocks that are not cached
                if (blocksRead < numBlocks && !_cache.ContainsBlock(firstBlock + blocksRead))
                {
                    servicedOutsideCache = true;

                    // Figure out how many blocks to read from the wrapped stream
                    int blocksToRead = 0;
                    while (blocksRead + blocksToRead < numBlocks &&
                           blocksToRead < _blocksInReadBuffer &&
                           !_cache.ContainsBlock(firstBlock + blocksRead + blocksToRead))
                    {
                        ++blocksToRead;
                    }

                    // Allow for the end of the stream not being block-aligned
                    long readPosition = (firstBlock + blocksRead) * (long)blockSize;
                    int  bytesToRead  = (int)Math.Min(blocksToRead * (long)blockSize, Length - readPosition);

                    // Do the read
                    _stats.TotalReadsOut++;
                    _wrappedStream.Position = readPosition;
                    int bytesRead = Utilities.ReadFully(_wrappedStream, _readBuffer, 0, bytesToRead);
                    if (bytesRead != bytesToRead)
                    {
                        throw new IOException("Short read before end of stream");
                    }

                    // Cache the read blocks
                    for (int i = 0; i < blocksToRead; ++i)
                    {
                        int copyBytes = Math.Min(blockSize, bytesToRead - (i * blockSize));
                        block = _cache.GetBlock(firstBlock + blocksRead + i);
                        Array.Copy(_readBuffer, i * blockSize, block.Data, 0, copyBytes);
                        block.Available = copyBytes;

                        if (copyBytes < blockSize)
                        {
                            Array.Clear(_readBuffer, (i * blockSize) + copyBytes, blockSize - copyBytes);
                        }
                    }

                    blocksRead += blocksToRead;

                    // Propogate the data onto the caller
                    int bytesToCopy = Math.Min(count - totalBytesRead, bytesRead - offsetInNextBlock);
                    Array.Copy(_readBuffer, offsetInNextBlock, buffer, offset + totalBytesRead, bytesToCopy);
                    totalBytesRead   += bytesToCopy;
                    _position        += bytesToCopy;
                    offsetInNextBlock = 0;
                }
            }

            if (_position >= Length && totalBytesRead == 0)
            {
                _atEof = true;
            }

            if (servicedFromCache)
            {
                _stats.ReadCacheHits++;
            }

            if (servicedOutsideCache)
            {
                _stats.ReadCacheMisses++;
            }

            return(totalBytesRead);
        }
Beispiel #5
0
 /// <summary>
 /// Reads from the buffer into a byte array.
 /// </summary>
 /// <param name="pos">The offset within the buffer to start reading.</param>
 /// <param name="buffer">The destination byte array.</param>
 /// <param name="offset">The start offset within the destination buffer.</param>
 /// <param name="count">The number of bytes to read.</param>
 /// <returns>The actual number of bytes read</returns>
 public override int Read(long pos, byte[] buffer, int offset, int count)
 {
     _stream.Position = pos;
     return(_stream.Read(buffer, offset, count));
 }