/// <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 }); } } }
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)); }
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) { }