Exemplo n.º 1
0
 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);
 }
Exemplo n.º 2
0
        /// <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);
            }
        }
Exemplo n.º 3
0
        /// <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);
            }
        }
Exemplo n.º 4
0
        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);
                }
            }
        }
Exemplo n.º 5
0
        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);
Exemplo n.º 6
0
        /// <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);
            }
        }
Exemplo n.º 7
0
        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);
            }
        }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        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);
            }
        }
Exemplo n.º 11
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);
            }
        }