public void Bug5203_IncreaseSize() { MemoryStream ms = new MemoryStream(); BlockCacheSettings settings = new BlockCacheSettings { BlockSize = 64, LargeReadSize = 128, OptimumReadSize = 64, ReadCacheSize = 1024 }; BlockCacheStream bcs = new BlockCacheStream(SparseStream.FromStream(ms, Ownership.Dispose), Ownership.Dispose, settings); // Pre-load read cache with a 'short' block bcs.Write(new byte[11], 0, 11); bcs.Position = 0; bcs.Read(new byte[11], 0, 11); // Extend stream for (int i = 0; i < 20; ++i) { bcs.Write(new byte[11], 0, 11); } // Try to read from first block beyond length of original cached short length // Bug was throwing exception here bcs.Position = 60; bcs.Read(new byte[20], 0, 20); }
/// <summary> /// Opens the specified file. /// </summary> /// <param name="path">The full path of the file to open.</param> /// <param name="mode">The file mode for the created stream.</param> /// <param name="access">The access permissions for the created stream.</param> /// <returns>The new stream.</returns> public override SparseStream OpenFile(string path, FileMode mode, FileAccess access) { if (_readOnly && access != FileAccess.Read) { throw new UnauthorizedAccessException(); } if (path.StartsWith(@"\", StringComparison.OrdinalIgnoreCase)) { path = path.Substring(1); } FileShare fileShare = FileShare.None; if (access == FileAccess.Read) { fileShare = FileShare.Read; } var locator = new LocalFileLocator(BasePath); return(SparseStream.FromStream(locator.Open(path, mode, access, fileShare), Ownership.Dispose)); }
private void RunSparse() { SparseStream inStream = InputStream as SparseStream; if (inStream == null) { inStream = SparseStream.FromStream(InputStream, Ownership.None); } if (BufferSize > SparseChunkSize && BufferSize % SparseChunkSize != 0) { throw new InvalidOperationException("Buffer size is not a multiple of the sparse chunk size"); } byte[] copyBuffer = new byte[Math.Max(BufferSize, SparseChunkSize)]; BytesRead = 0; BytesWritten = 0; foreach (StreamExtent extent in inStream.Extents) { inStream.Position = extent.Start; long extentOffset = 0; while (extentOffset < extent.Length) { int toRead = (int)Math.Min(copyBuffer.Length, extent.Length - extentOffset); int numRead = Utilities.ReadFully(inStream, copyBuffer, 0, toRead); BytesRead += numRead; int copyBufferOffset = 0; for (int i = 0; i < numRead; i += SparseChunkSize) { if (IsAllZeros(copyBuffer, i, Math.Min(SparseChunkSize, numRead - i))) { if (copyBufferOffset < i) { OutputStream.Position = extent.Start + extentOffset + copyBufferOffset; OutputStream.Write(copyBuffer, copyBufferOffset, i - copyBufferOffset); BytesWritten += i - copyBufferOffset; } copyBufferOffset = i + SparseChunkSize; } } if (copyBufferOffset < numRead) { OutputStream.Position = extent.Start + extentOffset + copyBufferOffset; OutputStream.Write(copyBuffer, copyBufferOffset, numRead - copyBufferOffset); BytesWritten += numRead - copyBufferOffset; } extentOffset += numRead; RaiseProgressEvent(); } } // Ensure the output stream is at least as long as the input stream. This uses // read/write, rather than SetLength, to avoid failing on streams that can't be // explicitly resized. Side-effect of this, is that if outStream is an NTFS // file stream, then actual clusters will be allocated out to at least the // length of the input stream. if (OutputStream.Length < inStream.Length) { inStream.Position = inStream.Length - 1; int b = inStream.ReadByte(); if (b >= 0) { OutputStream.Position = inStream.Length - 1; OutputStream.WriteByte((byte)b); } } }
public void OpenView() { ThreadSafeStream tss = new ThreadSafeStream(SparseStream.FromStream(Stream.Null, Ownership.None)); SparseStream view = tss.OpenView(); }