Example #1
0
 /// <summary>
 /// Provide device to store delta log for incremental snapshot checkpoints
 /// </summary>
 /// <param name="token"></param>
 /// <returns></returns>
 public IDevice GetDeltaLogDevice(Guid token)
 {
     return(Devices.CreateLogDevice(directoryConfiguration.GetDeltaLogFileName(token), false));
 }
Example #2
0
 /// <summary>
 /// Provide device to store index checkpoint (including overflow buckets)
 /// </summary>
 /// <param name="indexToken"></param>
 /// <returns></returns>
 public IDevice GetIndexDevice(Guid indexToken)
 {
     return(Devices.CreateLogDevice(directoryConfiguration.GetPrimaryHashTableFileName(indexToken), false));
 }
Example #3
0
 /// <summary>
 /// Provide device to store snapshot of object log (required only for snapshot checkpoints)
 /// </summary>
 /// <param name="token"></param>
 /// <returns></returns>
 public IDevice GetSnapshotObjectLogDevice(Guid token)
 {
     return(Devices.CreateLogDevice(directoryConfiguration.GetObjectLogSnapshotFileName(token), false));
 }
Example #4
0
        private void RecoverHybridLogFromSnapshotFile(
            IndexRecoveryInfo indexRecoveryInfo,
            HybridLogRecoveryInfo recoveryInfo)
        {
            var fileStartAddress = recoveryInfo.flushedLogicalAddress;
            var fromAddress      = indexRecoveryInfo.startLogicalAddress;
            var untilAddress     = recoveryInfo.finalLogicalAddress;

            // Compute startPage and endPage
            var startPage = hlog.GetPage(fileStartAddress);
            var endPage   = hlog.GetPage(untilAddress);

            if (untilAddress > hlog.GetStartLogicalAddress(endPage))
            {
                endPage++;
            }

            // By default first page has one extra record
            var capacity                = hlog.GetCapacityNumPages();
            var recoveryDevice          = Devices.CreateLogDevice(directoryConfiguration.GetHybridLogCheckpointFileName(recoveryInfo.guid), false);
            var objectLogRecoveryDevice = Devices.CreateLogDevice(directoryConfiguration.GetHybridLogObjectCheckpointFileName(recoveryInfo.guid), false);

            recoveryDevice.Initialize(hlog.GetSegmentSize());
            objectLogRecoveryDevice.Initialize(hlog.GetSegmentSize());
            var recoveryStatus = new RecoveryStatus(capacity, startPage, endPage)
            {
                recoveryDevice           = recoveryDevice,
                objectLogRecoveryDevice  = objectLogRecoveryDevice,
                recoveryDevicePageOffset = startPage
            };

            // Initially issue read request for all pages that can be held in memory
            int totalPagesToRead    = (int)(endPage - startPage);
            int numPagesToReadFirst = Math.Min(capacity, totalPagesToRead);

            hlog.AsyncReadPagesFromDevice(startPage, numPagesToReadFirst,
                                          AsyncReadPagesCallbackForRecovery,
                                          recoveryStatus,
                                          recoveryStatus.recoveryDevicePageOffset,
                                          recoveryStatus.recoveryDevice, recoveryStatus.objectLogRecoveryDevice);


            for (long page = startPage; page < endPage; page++)
            {
                // Ensure the page is read from file
                int pageIndex = hlog.GetPageIndexForPage(page);
                while (recoveryStatus.readStatus[pageIndex] == ReadStatus.Pending)
                {
                    Thread.Sleep(10);
                }

                // Page at hand
                var startLogicalAddress = hlog.GetStartLogicalAddress(page);
                var endLogicalAddress   = hlog.GetStartLogicalAddress(page + 1);

                // Perform recovery if page in fuzzy portion of the log
                if ((fromAddress < endLogicalAddress) && (fromAddress < untilAddress))
                {
                    /*
                     * Handling corner-cases:
                     * ----------------------
                     * When fromAddress is in the middle of the page,
                     * then start recovery only from corresponding offset
                     * in page. Similarly, if untilAddress falls in the
                     * middle of the page, perform recovery only until that
                     * offset. Otherwise, scan the entire page [0, PageSize)
                     */
                    var pageFromAddress = 0L;
                    if (fromAddress > startLogicalAddress && fromAddress < endLogicalAddress)
                    {
                        pageFromAddress = hlog.GetOffsetInPage(fromAddress);
                    }

                    var pageUntilAddress = hlog.GetPageSize();
                    if (endLogicalAddress > untilAddress)
                    {
                        pageUntilAddress = hlog.GetOffsetInPage(untilAddress);
                    }

                    var physicalAddress = hlog.GetPhysicalAddress(startLogicalAddress);
                    RecoverFromPage(fromAddress, pageFromAddress, pageUntilAddress,
                                    startLogicalAddress, physicalAddress, recoveryInfo.version);
                }

                // OS thread flushes current page and issues a read request if necessary
                recoveryStatus.readStatus[pageIndex]  = ReadStatus.Pending;
                recoveryStatus.flushStatus[pageIndex] = FlushStatus.Pending;

                // Write back records from snapshot to main hybrid log
                hlog.AsyncFlushPages(page, 1, AsyncFlushPageCallbackForRecovery, recoveryStatus);
            }

            // Assert and wait until all pages have been flushed
            var done = false;

            while (!done)
            {
                done = true;
                for (long page = startPage; page < endPage; page++)
                {
                    int pageIndex = hlog.GetPageIndexForPage(page);
                    if (recoveryStatus.flushStatus[pageIndex] == FlushStatus.Pending)
                    {
                        done = false;
                        break;
                    }
                }
            }

            recoveryStatus.recoveryDevice.Close();
            recoveryStatus.objectLogRecoveryDevice.Close();
        }