public void Flush() { lock (locker) { foreach (var dirtyRegion in writtenRegions) { BasePageStorage.WriteTo(PageIndex, dirtyRegion.FirstIndex, this.cacheBuffer, dirtyRegion.FirstIndex, dirtyRegion.Length); } } }
public void Write(long dstOffset, byte[] buffer, long srcOffset, long length) { if (BasePageStorage.IsReadOnly) { throw new InvalidOperationException("Cannot write to a read-only " + nameof(CachedPage) + "."); } if (dstOffset < 0) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The destination offset cannot be less than zero."); } if (srcOffset < 0) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The source offset cannot be less than zero."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "The length cannot be less than zero."); } if (dstOffset + length > BasePageStorage.PageSize) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The sum of the destination offset and length cannot be greater than the page size."); } if (srcOffset + length > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The sum of the source offset and length cannot be greater than the size of the source buffer."); } lock (locker) { DataRegion dstRegion = new DataRegion(dstOffset, (dstOffset + length) - 1 /*-1 to go from count to index*/); //Copy the data to the cached buffer Buffer.BlockCopy(buffer, (int)srcOffset, cacheBuffer, (int)dstOffset, (int)length); //Writes affect read cache too readRegions.Add(dstRegion); if (WriteMode == CachedPageStorage.CacheWriteMode.WriteThrough) { //Write directly to the base storage BasePageStorage.WriteTo(PageIndex, dstOffset, buffer, srcOffset, length); } else { //Update the 'dirty' write regions writtenRegions.Add(dstRegion); } } //Mark this page as more recent UpdateUseCounter(); }
/// <summary> /// Reads from the page, updating cache where necessary. /// </summary> /// <param name="srcOffset">The source offset within the page's payload.</param> /// <param name="buffer">The destination buffer.</param> /// <param name="dstOffset">The offset within the destination <paramref name="buffer"/>.</param> /// <param name="length">The number of bytes to read.</param> public void Read(long srcOffset, byte[] buffer, long dstOffset, long length) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } if (srcOffset < 0) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The source offset cannot be less than zero."); } if (dstOffset < 0) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The destination offset cannot be less than zero."); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "The length cannot be less than zero."); } if (srcOffset + length > BasePageStorage.PageSize) { throw new ArgumentOutOfRangeException(nameof(srcOffset), "The sum of the source offset and length cannot be greater than the size of each page."); } if (dstOffset + length > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(dstOffset), "The sum of the destination offset and length cannot be greater than the size of the destination buffer."); } lock (locker) { if (length != 0) { DataRegion srcRegion = new DataRegion(srcOffset, (srcOffset + length) - 1 /*-1 to go from count to index*/); //Determine which DataRegions are not currently cached (if any), and load them into cache foreach (var missing in readRegions.GetMissingRegions(srcRegion)) { //Read this missing DataRegion into cache BasePageStorage.ReadFrom(PageIndex, missing.FirstIndex, cacheBuffer, missing.FirstIndex, missing.Length); readRegions.Add(missing); } //Copy the data from the cached buffer Buffer.BlockCopy(cacheBuffer, (int)srcOffset, buffer, (int)dstOffset, (int)length); } //Else we don't need to do anything, read 0 bytes is meaningless } //Mark this page as more recent UpdateUseCounter(); }