private bool RetrievedObjects(byte *record, AsyncIOContext ctx) { if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize()) { return(true); } if (ctx.objBuffer.buffer == null) { // Issue IO for objects long startAddress = -1; long numBytes = 0; if (Key.HasObjectsToSerialize()) { var x = (AddressInfo *)Layout.GetKey((long)record); numBytes += x->Size; startAddress = x->Address; } if (Value.HasObjectsToSerialize()) { var x = (AddressInfo *)Layout.GetValue((long)record); numBytes += x->Size; if (startAddress == -1) { startAddress = x->Address; } } // We are limited to a 2GB size per key-value if (numBytes > int.MaxValue) { throw new Exception("Size of key-value exceeds max of 2GB: " + numBytes); } AsyncGetFromDisk(startAddress, (int)numBytes, AsyncGetFromDiskCallback, ctx, ctx.record); return(false); } // Parse the key and value objects MemoryStream ms = new MemoryStream(ctx.objBuffer.buffer); ms.Seek(ctx.objBuffer.offset + ctx.objBuffer.valid_offset, SeekOrigin.Begin); Key.Deserialize(Layout.GetKey((long)record), ms); Value.Deserialize(Layout.GetValue((long)record), ms); ctx.objBuffer.Return(); return(true); }
private bool RetrievedObjects(byte *record, AsyncIOContext ctx) { if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize()) { return(true); } if (ctx.objBuffer.buffer == null) { // Issue IO for objects long startAddress = -1; int numBytes = 0; if (Key.HasObjectsToSerialize()) { var x = (AddressInfo *)Layout.GetKey((long)record); if (x->IsDiskAddress) { numBytes += x->Size; startAddress = x->Address; } } if (Value.HasObjectsToSerialize()) { var x = (AddressInfo *)Layout.GetValue((long)record); if (x->IsDiskAddress) { numBytes += x->Size; if (startAddress == -1) { startAddress = x->Address; } } } AsyncGetFromDisk(startAddress, numBytes, AsyncGetFromDiskCallback, ctx, ctx.record); return(false); } // Parse the key and value objects MemoryStream ms = new MemoryStream(ctx.objBuffer.buffer); ms.Seek(ctx.objBuffer.offset + ctx.objBuffer.valid_offset, SeekOrigin.Begin); Key.Deserialize(Layout.GetKey((long)record), ms); Value.Deserialize(Layout.GetValue((long)record), ms); ctx.objBuffer.Return(); return(true); }
/// <summary> /// Deseialize part of page from stream /// </summary> /// <param name="ptr">From pointer</param> /// <param name="untilptr">Until pointer</param> /// <param name="stream">Stream</param> public void Deserialize(long ptr, long untilptr, Stream stream) { while (ptr < untilptr) { if (!Layout.GetInfo(ptr)->Invalid) { if (Key.HasObjectsToSerialize()) { Key.Deserialize(Layout.GetKey(ptr), stream); } if (Value.HasObjectsToSerialize()) { Value.Deserialize(Layout.GetValue(ptr), stream); } } ptr += Layout.GetPhysicalSize(ptr); } }
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); } }