예제 #1
0
        private void WriteAsync(IntPtr alignedSourceAddress, ulong alignedDestinationAddress, uint numBytesToWrite,
                                IOCompletionCallback callback, PageAsyncFlushResult asyncResult,
                                IDevice device, ISegmentedDevice objlogDevice)
        {
            // Debugger.Break();

            if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize())
            {
                device.WriteAsync(alignedSourceAddress, alignedDestinationAddress,
                                  numBytesToWrite, callback, asyncResult);
                return;
            }

            // need to write both page and object cache
            asyncResult.count++;
            //if (alignedDestinationAddress == 0)
            //    Debugger.Break();
            MemoryStream ms     = new MemoryStream();
            var          buffer = ioBufferPool.Get(PageSize);

            Buffer.MemoryCopy((void *)alignedSourceAddress, buffer.aligned_pointer, numBytesToWrite, numBytesToWrite);

            long        ptr  = (long)buffer.aligned_pointer;
            List <long> addr = new List <long>();

            asyncResult.freeBuffer1 = buffer;

            // Correct for page 0 of HLOG
            if (alignedDestinationAddress >> LogPageSizeBits == 0)
            {
                ptr += Constants.kFirstValidAddress;
            }

            while (ptr < (long)buffer.aligned_pointer + numBytesToWrite)
            {
                if (!Layout.GetInfo(ptr)->Invalid)
                {
                    long pos = ms.Position;

                    Key *key = Layout.GetKey(ptr);
                    Key.Serialize(key, ms);
                    ((AddressInfo *)key)->IsDiskAddress = true;
                    ((AddressInfo *)key)->Address       = pos;
                    ((AddressInfo *)key)->Size          = (int)(ms.Position - pos);
                    addr.Add((long)key);

                    pos = ms.Position;
                    Value *value = Layout.GetValue(ptr);
                    Value.Serialize(value, ms);
                    ((AddressInfo *)value)->IsDiskAddress = true;
                    ((AddressInfo *)value)->Address       = pos;
                    ((AddressInfo *)value)->Size          = (int)(ms.Position - pos);
                    addr.Add((long)value);
                }
                ptr += Layout.GetPhysicalSize(ptr);
            }


            var s         = ms.ToArray();
            var objBuffer = ioBufferPool.Get(s.Length);

            asyncResult.freeBuffer2 = objBuffer;

            var alignedLength = (s.Length + (sectorSize - 1)) & ~(sectorSize - 1);

            var objAddr = Interlocked.Add(ref segmentOffsets[(alignedDestinationAddress >> LogSegmentSizeBits) % SegmentBufferSize], alignedLength) - alignedLength;

            fixed(void *src = s)
            Buffer.MemoryCopy(src, objBuffer.aligned_pointer, s.Length, s.Length);

            foreach (var address in addr)
            {
                *((long *)address) += objAddr;
            }

            objlogDevice.WriteAsync(
                (IntPtr)objBuffer.aligned_pointer,
                (int)(alignedDestinationAddress >> LogSegmentSizeBits),
                (ulong)objAddr, (uint)alignedLength, callback, asyncResult);

            device.WriteAsync((IntPtr)buffer.aligned_pointer, alignedDestinationAddress,
                              numBytesToWrite, callback, asyncResult);
        }
예제 #2
0
        protected void AsyncGetFromDiskCallback(
            uint errorCode,
            uint numBytes,
            NativeOverlapped *overlap)
        {
            //Debugger.Break();
            var result = (AsyncGetFromDiskResult <AsyncIOContext>)Overlapped.Unpack(overlap).AsyncResult;

            try
            {
                if (errorCode != 0)
                {
                    Trace.TraceError("OverlappedStream GetQueuedCompletionStatus error: {0}", errorCode);
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError("Completion Callback error, {0}", ex.Message);
            }
            finally
            {
                Interlocked.Decrement(ref numPendingReads);

                var ctx    = result.context;
                var record = ctx.record.GetValidPointer();
                if (Layout.HasTotalRecord(record, ctx.record.available_bytes, out int requiredBytes))
                {
                    //We have the complete record.
                    if (RetrievedObjects(record, ctx))
                    {
                        if (Key.Equals(ctx.key, Layout.GetKey((long)record)))
                        {
                            //The keys are same, so I/O is complete
                            // ctx.record = result.record;
                            ctx.callbackQueue.Add(ctx);
                        }
                        else
                        {
                            var oldAddress = ctx.logicalAddress;

                            //keys are not same. I/O is not complete
                            ctx.logicalAddress = ((RecordInfo *)record)->PreviousAddress;
                            if (ctx.logicalAddress != Constants.kInvalidAddress)
                            {
                                // Delete key, value, record
                                if (Key.HasObjectsToSerialize())
                                {
                                    var physicalAddress = (long)ctx.record.GetValidPointer();
                                    Key.Free(Layout.GetKey(physicalAddress));
                                }
                                if (Value.HasObjectsToSerialize())
                                {
                                    var physicalAddress = (long)ctx.record.GetValidPointer();
                                    Value.Free(Layout.GetValue(physicalAddress));
                                }
                                ctx.record.Return();
                                AsyncGetFromDisk(ctx.logicalAddress, requiredBytes, AsyncGetFromDiskCallback, ctx);
                            }
                            else
                            {
                                ctx.callbackQueue.Add(ctx);
                            }
                        }
                    }
                }
                else
                {
                    ctx.record.Return();
                    AsyncGetFromDisk(ctx.logicalAddress, requiredBytes, AsyncGetFromDiskCallback, ctx);
                }

                Overlapped.Free(overlap);
            }
        }
예제 #3
0
        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);
            }
           
        }