protected override void ReadAsync <TContext>( ulong alignedSourceAddress, int destinationPageIndex, uint aligned_read_length, IOCompletionCallback callback, PageAsyncReadResult <TContext> asyncResult, IDevice device, IDevice objlogDevice) { device.ReadAsync(alignedSourceAddress, (IntPtr)pointers[destinationPageIndex], aligned_read_length, callback, asyncResult); }
/// <summary> /// Read pages from specified device /// </summary> /// <typeparam name="TContext"></typeparam> /// <param name="readPageStart"></param> /// <param name="numPages"></param> /// <param name="callback"></param> /// <param name="context"></param> /// <param name="completed"></param> /// <param name="devicePageOffset"></param> /// <param name="device"></param> /// <param name="objectLogDevice"></param> public void AsyncReadPagesFromDevice <TContext>( long readPageStart, int numPages, IOCompletionCallback callback, TContext context, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null, IDevice objectLogDevice = null) { var usedDevice = device; IDevice usedObjlogDevice = objectLogDevice; if (device == null) { usedDevice = this.device; usedObjlogDevice = this.objectLogDevice; } if (pageHandlers.HasObjects()) { if (usedObjlogDevice == null) { throw new Exception("Object log device not provided"); } } completed = new CountdownEvent(numPages); for (long readPage = readPageStart; readPage < (readPageStart + numPages); readPage++) { int pageIndex = (int)(readPage % BufferSize); if (values[pageIndex] == null) { // Allocate a new page AllocatePage(pageIndex); } else { ClearPage(pageIndex, readPage == 0); } var asyncResult = new PageAsyncReadResult <TContext>() { page = readPage, context = context, handle = completed, count = 1 }; ulong offsetInFile = (ulong)(AlignedPageSizeBytes * readPage); if (device != null) { offsetInFile = (ulong)(AlignedPageSizeBytes * (readPage - devicePageOffset)); } ReadAsync(offsetInFile, (IntPtr)pointers[pageIndex], PageSize, callback, asyncResult, usedDevice, usedObjlogDevice); } }
/// <summary> /// Read pages from specified device /// </summary> /// <typeparam name="TContext"></typeparam> /// <param name="readPageStart"></param> /// <param name="numPages"></param> /// <param name="untilAddress"></param> /// <param name="callback"></param> /// <param name="context"></param> /// <param name="frame"></param> /// <param name="completed"></param> /// <param name="devicePageOffset"></param> /// <param name="device"></param> /// <param name="objectLogDevice"></param> internal void AsyncReadPagesFromDeviceToFrame <TContext>( long readPageStart, int numPages, long untilAddress, IOCompletionCallback callback, TContext context, BlittableFrame frame, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null, IDevice objectLogDevice = null) { var usedDevice = device; IDevice usedObjlogDevice = objectLogDevice; if (device == null) { usedDevice = this.device; } completed = new CountdownEvent(numPages); for (long readPage = readPageStart; readPage < (readPageStart + numPages); readPage++) { int pageIndex = (int)(readPage % frame.frameSize); if (frame.frame[pageIndex] == null) { frame.Allocate(pageIndex); } else { frame.Clear(pageIndex); } var asyncResult = new PageAsyncReadResult <TContext>() { page = readPage, context = context, handle = completed, frame = frame }; ulong offsetInFile = (ulong)(AlignedPageSizeBytes * readPage); uint readLength = (uint)AlignedPageSizeBytes; long adjustedUntilAddress = (AlignedPageSizeBytes * (untilAddress >> LogPageSizeBits) + (untilAddress & PageSizeMask)); if (adjustedUntilAddress > 0 && ((adjustedUntilAddress - (long)offsetInFile) < PageSize)) { readLength = (uint)(adjustedUntilAddress - (long)offsetInFile); readLength = (uint)((readLength + (sectorSize - 1)) & ~(sectorSize - 1)); } if (device != null) { offsetInFile = (ulong)(AlignedPageSizeBytes * (readPage - devicePageOffset)); } usedDevice.ReadAsync(offsetInFile, (IntPtr)frame.pointers[pageIndex], readLength, callback, asyncResult); } }
public void AsyncReadPageFromDiskRecovery <TContext>( long readPageStart, int numPages, IOCompletionCallback callback, TContext context, long recoveryDevicePageOffset = 0, IDevice recoveryDevice = null) { if (Key.HasObjectsToSerialize() || Value.HasObjectsToSerialize()) { throw new Exception("Reading pages with object log not yet supported"); } for (long readPage = readPageStart; readPage < (readPageStart + numPages); readPage++) { int pageIndex = (int)(readPage % BufferSize); if (values[pageIndex] == null) { // Allocate a new page AllocatePage(pageIndex); } else { //Clear an old used page Array.Clear(values[pageIndex], 0, values[pageIndex].Length); } var asyncResult = new PageAsyncReadResult <TContext>() { page = readPage, context = context }; if (recoveryDevice == null) { device.ReadAsync((ulong)(AlignedPageSizeBytes * readPage), pointers[pageIndex], (uint)(PageSize * PrivateRecordSize), callback, asyncResult); } else { ulong offsetInFile = (ulong)(AlignedPageSizeBytes * (readPage - recoveryDevicePageOffset)); recoveryDevice.ReadAsync(offsetInFile, pointers[pageIndex], (uint)(PageSize * PrivateRecordSize), callback, asyncResult); } } }
private void AsyncReadPageWithObjectsCallback <TContext>(uint errorCode, uint numBytes, NativeOverlapped *overlap) { if (errorCode != 0) { Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode); } PageAsyncReadResult <TContext> result = (PageAsyncReadResult <TContext>)Overlapped.Unpack(overlap).AsyncResult; long ptr = pointers[result.page % BufferSize]; // Correct for page 0 of HLOG if (result.page == 0) { ptr += Constants.kFirstValidAddress; } // Check if we are resuming if (result.resumeptr > ptr) { ptr = result.resumeptr; } // Deserialize all objects until untilptr if (ptr < result.untilptr) { MemoryStream ms = new MemoryStream(result.freeBuffer1.buffer); ms.Seek(result.freeBuffer1.offset + result.freeBuffer1.valid_offset, SeekOrigin.Begin); pageHandlers.Deserialize(ptr, result.untilptr, ms); ms.Dispose(); ptr = result.untilptr; result.freeBuffer1.Return(); result.freeBuffer1.buffer = null; result.resumeptr = ptr; } // If we have processed entire page, return if (ptr >= pointers[result.page % BufferSize] + PageSize) { result.Free(); // Call the "real" page read callback result.callback(errorCode, numBytes, overlap); return; } // We will be re-issuing I/O, so free current overlap Overlapped.Free(overlap); pageHandlers.GetObjectInfo(ref ptr, pointers[result.page % BufferSize] + PageSize, kObjectBlockSize, out long startptr, out long size);
/// <summary> /// Read pages from specified device /// </summary> /// <typeparam name="TContext"></typeparam> /// <param name="readPageStart"></param> /// <param name="numPages"></param> /// <param name="callback"></param> /// <param name="context"></param> /// <param name="frame"></param> /// <param name="completed"></param> /// <param name="devicePageOffset"></param> /// <param name="device"></param> /// <param name="objectLogDevice"></param> internal void AsyncReadPagesFromDeviceToFrame <TContext>( long readPageStart, int numPages, IOCompletionCallback callback, TContext context, BlittableFrame frame, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null, IDevice objectLogDevice = null) { var usedDevice = device; IDevice usedObjlogDevice = objectLogDevice; if (device == null) { usedDevice = this.device; } completed = new CountdownEvent(numPages); for (long readPage = readPageStart; readPage < (readPageStart + numPages); readPage++) { int pageIndex = (int)(readPage % frame.frameSize); if (frame.frame[pageIndex] == null) { frame.Allocate(pageIndex); } else { frame.Clear(pageIndex); } var asyncResult = new PageAsyncReadResult <TContext>() { page = readPage, context = context, handle = completed, count = 1, frame = frame }; ulong offsetInFile = (ulong)(AlignedPageSizeBytes * readPage); if (device != null) { offsetInFile = (ulong)(AlignedPageSizeBytes * (readPage - devicePageOffset)); } usedDevice.ReadAsync(offsetInFile, (IntPtr)frame.pointers[pageIndex], (uint)AlignedPageSizeBytes, callback, asyncResult); } }
public void AsyncReadPagesFromDevice <TContext>( long readPageStart, int numPages, IOCompletionCallback callback, TContext context, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null) { var usedDevice = (device != null) ? device : this.device; ISegmentedDevice usedObjlogDevice = null; if (Key.HasObjectsToSerialize() || Value.HasObjectsToSerialize()) { usedObjlogDevice = (device != null) ? CreateObjectLogDevice(device) : objlogDevice; } completed = new CountdownEvent(numPages); for (long readPage = readPageStart; readPage < (readPageStart + numPages); readPage++) { int pageIndex = (int)(readPage % BufferSize); if (values[pageIndex] == null) { // Allocate a new page AllocatePage(pageIndex); } else { ClearPage(pageIndex, readPage == 0); } var asyncResult = new PageAsyncReadResult <TContext>() { page = readPage, context = context, handle = completed, count = 1 }; ulong offsetInFile = (ulong)(AlignedPageSizeBytes * readPage); if (device != null) { offsetInFile = (ulong)(AlignedPageSizeBytes * (readPage - devicePageOffset)); } ReadAsync(offsetInFile, pointers[pageIndex], PageSize, callback, asyncResult, usedDevice, usedObjlogDevice); } }
private void ReadAsync <TContext>( ulong alignedSourceAddress, IntPtr alignedDestinationAddress, uint aligned_read_length, IOCompletionCallback callback, PageAsyncReadResult <TContext> asyncResult, IDevice device, ISegmentedDevice objlogDevice) { if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize()) { device.ReadAsync(alignedSourceAddress, alignedDestinationAddress, aligned_read_length, callback, asyncResult); return; } asyncResult.callback = callback; asyncResult.count++; asyncResult.objlogDevice = objlogDevice; device.ReadAsync(alignedSourceAddress, alignedDestinationAddress, aligned_read_length, AsyncReadPageCallback <TContext>, asyncResult); }
private void ReadAsync <TContext>( ulong alignedSourceAddress, IntPtr alignedDestinationAddress, uint aligned_read_length, IOCompletionCallback callback, PageAsyncReadResult <TContext> asyncResult, IDevice device, IDevice objlogDevice) { if (!pageHandlers.HasObjects()) { device.ReadAsync(alignedSourceAddress, alignedDestinationAddress, aligned_read_length, callback, asyncResult); return; } asyncResult.callback = callback; asyncResult.count++; asyncResult.objlogDevice = objlogDevice; device.ReadAsync(alignedSourceAddress, alignedDestinationAddress, aligned_read_length, AsyncReadPageWithObjectsCallback <TContext>, asyncResult); }
internal override void AsyncReadPagesFromDeviceToFrame <TContext>(long readPageStart, int numPages, long untilAddress, TContext context, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null, IDevice objectLogDevice = null, CancellationTokenSource cts = null) { IDevice usedDevice = deltaLogDevice; completed = new CountdownEvent(numPages); for (long readPage = readPageStart; readPage < (readPageStart + numPages); readPage++) { int pageIndex = (int)(readPage % frame.frameSize); if (frame.frame[pageIndex] == null) { frame.Allocate(pageIndex); } else { frame.Clear(pageIndex); } var asyncResult = new PageAsyncReadResult <TContext>() { page = readPage, context = context, handle = completed, frame = frame }; ulong offsetInFile = (ulong)(AlignedPageSizeBytes * readPage); uint readLength = (uint)AlignedPageSizeBytes; long adjustedUntilAddress = (AlignedPageSizeBytes * (untilAddress >> LogPageSizeBits) + (untilAddress & PageSizeMask)); if (adjustedUntilAddress > 0 && ((adjustedUntilAddress - (long)offsetInFile) < PageSize)) { readLength = (uint)(adjustedUntilAddress - (long)offsetInFile); readLength = (uint)(Align(readLength)); } if (device != null) { offsetInFile = (ulong)(AlignedPageSizeBytes * (readPage - devicePageOffset)); } usedDevice.ReadAsync(offsetInFile, (IntPtr)frame.pointers[pageIndex], readLength, AsyncReadPagesCallback, asyncResult); } }
private void AsyncReadPageCallback <TContext>(uint errorCode, uint numBytes, NativeOverlapped *overlap) { if (errorCode != 0) { Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode); } PageAsyncReadResult <TContext> result = (PageAsyncReadResult <TContext>)Overlapped.Unpack(overlap).AsyncResult; if (Interlocked.Decrement(ref result.count) == 1) { // We will be issuing another I/O, so free this overlap Overlapped.Free(overlap); long ptr = (long)pointers[result.page % BufferSize]; // Correct for page 0 of HLOG if (result.page == 0) { ptr += Constants.kFirstValidAddress; } long minObjAddress = long.MaxValue; long maxObjAddress = long.MinValue; while (ptr < (long)pointers[result.page % BufferSize] + PageSize) { if (!Layout.GetInfo(ptr)->Invalid) { if (Key.HasObjectsToSerialize()) { Key *key = Layout.GetKey(ptr); var addr = ((AddressInfo *)key)->Address; if (addr < minObjAddress) { minObjAddress = addr; } addr += ((AddressInfo *)key)->Size; if (addr > maxObjAddress) { maxObjAddress = addr; } } if (Value.HasObjectsToSerialize()) { Value *value = Layout.GetValue(ptr); var addr = ((AddressInfo *)value)->Address; if (addr < minObjAddress) { minObjAddress = addr; } addr += ((AddressInfo *)value)->Size; if (addr > maxObjAddress) { maxObjAddress = addr; } } } ptr += Layout.GetPhysicalSize(ptr); } // Object log fragment should be aligned by construction Debug.Assert(minObjAddress % sectorSize == 0); var to_read = (int)(maxObjAddress - minObjAddress); var objBuffer = ioBufferPool.Get(to_read); result.freeBuffer1 = objBuffer; var alignedLength = (to_read + (sectorSize - 1)) & ~(sectorSize - 1); // Request objects from objlog result.objlogDevice.ReadAsync( (int)(result.page >> (LogSegmentSizeBits - LogPageSizeBits)), (ulong)minObjAddress, (IntPtr)objBuffer.aligned_pointer, (uint)alignedLength, AsyncReadPageCallback <TContext>, result); } else { // Load objects from buffer into memory long ptr = (long)pointers[result.page % BufferSize]; // Correct for page 0 of HLOG if (result.page == 0) { ptr += Constants.kFirstValidAddress; } MemoryStream ms = new MemoryStream(result.freeBuffer1.buffer); ms.Seek(result.freeBuffer1.offset + result.freeBuffer1.valid_offset, SeekOrigin.Begin); while (ptr < (long)pointers[result.page % BufferSize] + PageSize) { if (!Layout.GetInfo(ptr)->Invalid) { if (Key.HasObjectsToSerialize()) { Key.Deserialize(Layout.GetKey(ptr), ms); } if (Value.HasObjectsToSerialize()) { Value.Deserialize(Layout.GetValue(ptr), ms); } } ptr += Layout.GetPhysicalSize(ptr); } ms.Dispose(); result.Free(); // Call the "real" page read callback result.callback(errorCode, numBytes, overlap); } }