public override int Read(long pos, byte[] buffer, int offset, int count) { int totalRead = 0; int limitedCount = (int)Math.Min(count, Math.Max(0, Capacity - pos)); while (totalRead < limitedCount) { long extentLogicalStart; ExtentDescriptor extent = FindExtent(pos, out extentLogicalStart); long extentStreamStart = extent.StartBlock * (long)_context.VolumeHeader.BlockSize; long extentSize = extent.BlockCount * (long)_context.VolumeHeader.BlockSize; long extentOffset = (pos + totalRead) - extentLogicalStart; int toRead = (int)Math.Min(limitedCount - totalRead, extentSize - extentOffset); // Remaining in extent can create a situation where amount to read is zero, and that appears // to be OK, just need to exit thie while loop to avoid infinite loop. if (toRead == 0) { break; } Stream volStream = _context.VolumeStream; volStream.Position = extentStreamStart + extentOffset; int numRead = volStream.Read(buffer, offset + totalRead, toRead); totalRead += numRead; } return(totalRead); }
private ExtentDescriptor FindExtent(long pos, out long extentLogicalStart) { uint blocksSeen = 0; uint block = (uint)(pos / _context.VolumeHeader.BlockSize); for (int i = 0; i < _baseData.Extents.Length; ++i) { if (blocksSeen + _baseData.Extents[i].BlockCount > block) { extentLogicalStart = blocksSeen * (long)_context.VolumeHeader.BlockSize; return(_baseData.Extents[i]); } blocksSeen += _baseData.Extents[i].BlockCount; } while (blocksSeen < _baseData.TotalBlocks) { byte[] extentData = _context.ExtentsOverflow.Find(new ExtentKey(_cnid, blocksSeen, false)); if (extentData != null) { int extentDescriptorCount = extentData.Length / 8; for (int a = 0; a < extentDescriptorCount; a++) { ExtentDescriptor extentDescriptor = new ExtentDescriptor(); int bytesRead = extentDescriptor.ReadFrom(extentData, a * 8); if ((blocksSeen + extentDescriptor.BlockCount) > block) { extentLogicalStart = blocksSeen * (long)_context.VolumeHeader.BlockSize; return(extentDescriptor); } blocksSeen += extentDescriptor.BlockCount; } } else { throw new IOException("Missing extent from extent overflow file: cnid=" + _cnid + ", blocksSeen=" + blocksSeen); } } throw new InvalidOperationException("Requested file fragment beyond EOF"); }
private ExtentDescriptor FindExtent(long pos, out long extentLogicalStart) { uint blocksSeen = 0; uint block = (uint)(pos / _context.VolumeHeader.BlockSize); for (int i = 0; i < _baseData.Extents.Length; ++i) { if (blocksSeen + _baseData.Extents[i].BlockCount > block) { extentLogicalStart = blocksSeen * (long)_context.VolumeHeader.BlockSize; return _baseData.Extents[i]; } blocksSeen += _baseData.Extents[i].BlockCount; } while (blocksSeen < _baseData.TotalBlocks) { byte[] extentData = _context.ExtentsOverflow.Find(new ExtentKey(_cnid, blocksSeen, false)); if (extentData != null) { int extentDescriptorCount = extentData.Length / 8; for (int a = 0; a < extentDescriptorCount; a++) { ExtentDescriptor extentDescriptor = new ExtentDescriptor(); int bytesRead = extentDescriptor.ReadFrom(extentData, a * 8); if ((blocksSeen + extentDescriptor.BlockCount) > block) { extentLogicalStart = blocksSeen * (long)_context.VolumeHeader.BlockSize; return extentDescriptor; } blocksSeen += extentDescriptor.BlockCount; } } else { throw new IOException("Missing extent from extent overflow file: cnid=" + _cnid + ", blocksSeen=" + blocksSeen); } } throw new InvalidOperationException("Requested file fragment beyond EOF"); }