示例#1
0
        /// <summary>
        /// Potentially expensive operation that restores available blocks after reading of filetable
        /// </summary>
        /// <returns></returns>
        private IEnumerable <DriveBlock> restoreAvailableContentBlocks()
        {
            lock (_entriesTableLock)
            {
                DriveBlock prevBlock       = null;
                var        processedBlocks = 0;
                foreach (var block in ReadEntries().OfType <FileEntry>().SelectMany(x => x.Blocks).OrderBy(x => x.Position))
                {
                    processedBlocks++;
                    if (prevBlock == null || block.Position == prevBlock.Position + prevBlock.Length)
                    {
                        prevBlock = block;
                        continue;
                    }

                    var position   = prevBlock.Position + prevBlock.Length;
                    var fullLength = block.Position - position;
                    do
                    {
                        var length = fullLength > int.MaxValue ? int.MaxValue : (int)fullLength;
                        var retv   = new DriveBlock
                        {
                            Position = position,
                            Length   = length
                        };

                        yield return(retv);

                        fullLength -= length;
                        position   += length;
                    } while (fullLength > 0);

                    prevBlock = block;
                }

                if (processedBlocks != 0 || _currentContentSector == null)
                {
                    yield break;
                }

                //if files blocks not found set all content sector as available block
                var restLength = _currentContentSector.Length;
                while (restLength > 0)
                {
                    var blockLength = (int)(_currentContentSector.Length > int.MaxValue
                        ? int.MaxValue
                        : _currentContentSector.Length);

                    restLength -= blockLength;
                    yield return(new DriveBlock
                    {
                        Position = _currentContentSector.StartPosition,
                        Length = blockLength
                    });
                }
            }
        }
示例#2
0
        public ReadOperation Read(FileEntry fileEntry, long filePosition, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            if (_isDisposing)
            {
                return(ReadOperation.Empty);
            }

            var blocks = new List <DriveBlock>();
            var currentFilePosition   = 0L;
            var allBlocksToReadLength = 0;
            var restReadCount         = count;

            foreach (var fileEntryBlock in fileEntry.Blocks)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                if (filePosition >= currentFilePosition + fileEntryBlock.Length)
                {
                    currentFilePosition += fileEntryBlock.Length;
                    continue;
                }

                var shift = (int)(filePosition - currentFilePosition);
                var restFileEntryBlockLength = fileEntryBlock.Length - shift;
                restFileEntryBlockLength = restFileEntryBlockLength > restReadCount ? restReadCount : restFileEntryBlockLength;
                var block = new DriveBlock
                {
                    Length   = restFileEntryBlockLength,
                    Position = fileEntryBlock.Position + shift
                };

                currentFilePosition += restFileEntryBlockLength;
                blocks.Add(block);
                allBlocksToReadLength += restFileEntryBlockLength;

                if (allBlocksToReadLength == count)
                {
                    break;
                }

                restReadCount -= restFileEntryBlockLength;
            }

            var reader = new ContentRawReader(_synchronizer, _currentContentSector.StartPosition, -1);

            if (!reader.CheckCanRead(count))
            {
                throw new InvalidOperationException("Unable to perform read operation. Trying to read protected memory");
            }

            return(reader.Read(blocks, buffer, offset, cancellationToken));
        }
示例#3
0
        public WriteOperation Write(FileEntry fileEntry, long filePosition, byte[] buffer, int offset, int count)
        {
            if (_isDisposing)
            {
                return(WriteOperation.Empty);
            }


            if (fileEntry.FileLength - (filePosition + count) < 0)
            {
                SetFileLength(fileEntry, filePosition + count);
            }

            var bytesToWrite        = count;
            var currentFilePosition = 0L;
            var blocksToWrite       = new List <DriveBlock>();

            foreach (var fileEntryBlock in fileEntry.Blocks)
            {
                if (filePosition > fileEntryBlock.Length + currentFilePosition)
                {
                    currentFilePosition += fileEntryBlock.Length;
                    continue;
                }

                var shift           = filePosition - currentFilePosition;
                var blockRestLength = (int)(fileEntryBlock.Length - shift);
                blockRestLength = blockRestLength > bytesToWrite ? bytesToWrite : blockRestLength;

                var block = new DriveBlock
                {
                    Position = fileEntryBlock.Position + shift,
                    Length   = blockRestLength
                };

                bytesToWrite -= blockRestLength;
                blocksToWrite.Add(block);
                currentFilePosition += blockRestLength;
                if (bytesToWrite <= 0)
                {
                    break;
                }
            }

            lock (_contentLock)
            {
                return(_contentWriter.Write(blocksToWrite, buffer, offset));
            }
        }
 public AvailableDriveBlock(DriveBlock block)
     : this(block?.Position ?? throw new ArgumentNullException(nameof(block)), block.Length)
 {
 }