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