Exemple #1
0
        /// <summary>
        ///  Recover info from token
        /// </summary>
        /// <param name="token"></param>
        /// <param name="directoryConfiguration"></param>
        /// <returns></returns>
        internal bool Recover(Guid token, DirectoryConfiguration directoryConfiguration)
        {
            string checkpointInfoFile = directoryConfiguration.GetHybridLogCheckpointMetaFileName(token);

            using (var reader = new StreamReader(checkpointInfoFile))
            {
                Initialize(reader);
            }

            int num_threads = numThreads;

            for (int i = 0; i < num_threads; i++)
            {
                var guid = guids[i];
                using (var reader = new StreamReader(directoryConfiguration.GetHybridLogCheckpointContextFileName(token, guid)))
                {
                    var ctx = new SerializedFasterExecutionContext();
                    ctx.Load(reader);
                    continueTokens.Add(ctx.guid, ctx.serialNum);
                }
            }

            if (continueTokens.Count == num_threads)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #2
0
        public void Recover(Guid guid, DirectoryConfiguration directoryConfiguration)
        {
            string indexInfoFile = directoryConfiguration.GetIndexCheckpointMetaFileName(guid);

            using (var reader = new StreamReader(indexInfoFile))
            {
                Initialize(reader);
            }
        }
Exemple #3
0
        protected void WriteIndexMetaFile()
        {
            string filename = DirectoryConfiguration.GetIndexCheckpointMetaFileName(_indexCheckpointToken);

            using (var file = new StreamWriter(filename, false))
            {
                _indexCheckpoint.info.Write(file);
                file.Flush();
            }
        }
Exemple #4
0
        protected void WriteHybridLogMetaInfo()
        {
            string filename = DirectoryConfiguration.GetHybridLogCheckpointMetaFileName(_hybridLogCheckpointToken);

            using (var file = new StreamWriter(filename, false))
            {
                _hybridLogCheckpoint.info.Write(file);
                file.Flush();
            }
        }
Exemple #5
0
        protected void WriteHybridLogContextInfo()
        {
            string filename = DirectoryConfiguration.GetHybridLogCheckpointContextFileName(_hybridLogCheckpointToken, prevThreadCtx.guid);

            using (var file = new StreamWriter(filename, false))
            {
                prevThreadCtx.Write(file);
                file.Flush();
            }
        }
Exemple #6
0
        /// <summary>
        /// Create FASTER instance
        /// </summary>
        /// <param name="size">Size of core index (#cache lines)</param>
        /// <param name="comparer">FASTER equality comparer for key</param>
        /// <param name="functions">Callback functions</param>
        /// <param name="logSettings">Log settings</param>
        /// <param name="checkpointSettings">Checkpoint settings</param>
        /// <param name="serializerSettings">Serializer settings</param>
        public FasterKV(long size, Functions functions, LogSettings logSettings, CheckpointSettings checkpointSettings = null, SerializerSettings <Key, Value> serializerSettings = null, IFasterEqualityComparer <Key> comparer = null)
        {
            if (comparer != null)
            {
                this.comparer = comparer;
            }
            else
            {
                if (typeof(IFasterEqualityComparer <Key>).IsAssignableFrom(typeof(Key)))
                {
                    this.comparer = new Key() as IFasterEqualityComparer <Key>;
                }
                else
                {
                    Console.WriteLine("***WARNING*** Creating default FASTER key equality comparer based on potentially slow EqualityComparer<Key>.Default. To avoid this, provide a comparer (IFasterEqualityComparer<Key>) as an argument to FASTER's constructor, or make Key implement the interface IFasterEqualityComparer<Key>");
                    this.comparer = FasterEqualityComparer <Key> .Default;
                }
            }

            if (checkpointSettings == null)
            {
                checkpointSettings = new CheckpointSettings();
            }

            directoryConfiguration = new DirectoryConfiguration(checkpointSettings.CheckpointDir);

            FoldOverSnapshot = checkpointSettings.CheckPointType == core.CheckpointType.FoldOver;
            CopyReadsToTail  = logSettings.CopyReadsToTail;
            this.functions   = functions;

            if (Utility.IsBlittable <Key>() && Utility.IsBlittable <Value>())
            {
                hlog = new BlittableAllocator <Key, Value>(logSettings, this.comparer);
            }
            else
            {
                hlog = new GenericAllocator <Key, Value>(logSettings, serializerSettings, this.comparer);
            }

            hlog.Initialize();

            sectorSize = (int)logSettings.LogDevice.SectorSize;
            Initialize(size, sectorSize);

            _systemState         = default(SystemState);
            _systemState.phase   = Phase.REST;
            _systemState.version = 1;
            _checkpointType      = CheckpointType.HYBRID_LOG_ONLY;
        }
Exemple #7
0
        // Derived class exposed API
        protected void RecoverFuzzyIndex(IndexRecoveryInfo info)
        {
            var ht_version = resizeInfo.version;
            var token      = info.token;

            Debug.Assert(state[ht_version].size == info.table_size);

            BeginMainIndexRecovery(ht_version,
                                   DirectoryConfiguration.GetPrimaryHashTableFileName(token),
                                   info.num_ht_bytes);

            overflowBucketsAllocator.Recover(
                DirectoryConfiguration.GetOverflowBucketsFileName(token),
                info.num_buckets,
                info.num_ofb_bytes);
        }
Exemple #8
0
        private void InternalRecover(Guid indexToken, Guid hybridLogToken)
        {
            _indexCheckpoint.Recover(indexToken);
            _hybridLogCheckpoint.Recover(hybridLogToken);

            // Recover segment offsets for object log
            if (_hybridLogCheckpoint.info.objectLogSegmentOffsets != null)
            {
                Array.Copy(_hybridLogCheckpoint.info.objectLogSegmentOffsets, hlog.segmentOffsets, _hybridLogCheckpoint.info.objectLogSegmentOffsets.Length);
            }

            _indexCheckpoint.main_ht_device = new LocalStorageDevice(DirectoryConfiguration.GetPrimaryHashTableFileName(_indexCheckpoint.info.token));
            _indexCheckpoint.ofb_device     = new LocalStorageDevice(DirectoryConfiguration.GetOverflowBucketsFileName(_indexCheckpoint.info.token));

            var l1 = _indexCheckpoint.info.finalLogicalAddress;
            var l2 = _hybridLogCheckpoint.info.finalLogicalAddress;
            var v  = _hybridLogCheckpoint.info.version;

            if (l1 > l2)
            {
                throw new Exception("Cannot recover from (" + indexToken.ToString() + "," + hybridLogToken.ToString() + ") checkpoint pair!\n");
            }

            _systemState.phase   = Phase.REST;
            _systemState.version = (v + 1);

            RecoverFuzzyIndex(_indexCheckpoint);

            IsFuzzyIndexRecoveryComplete(true);

            DeleteTentativeEntries();

            if (FoldOverSnapshot)
            {
                RecoverHybridLog(_indexCheckpoint.info, _hybridLogCheckpoint.info);
            }
            else
            {
                RecoverHybridLogFromSnapshotFile(_indexCheckpoint.info, _hybridLogCheckpoint.info);
            }

            _indexCheckpoint.Reset();

            RestoreHybridLog(_hybridLogCheckpoint.info.finalLogicalAddress);
        }
Exemple #9
0
 public void Recover(Guid token, DirectoryConfiguration directoryConfiguration)
 {
     info.Recover(token, directoryConfiguration);
 }
Exemple #10
0
 public void Initialize(Guid token, long _size, DirectoryConfiguration directoryConfiguration)
 {
     info.Initialize(token, _size);
     main_ht_device = Devices.CreateLogDevice(directoryConfiguration.GetPrimaryHashTableFileName(token), false);
     ofb_device     = Devices.CreateLogDevice(directoryConfiguration.GetOverflowBucketsFileName(token), false);
 }
Exemple #11
0
        protected 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 recoveryStatus = new RecoveryStatus(capacity, startPage, endPage);

            recoveryStatus.recoveryDevice           = new LocalStorageDevice(DirectoryConfiguration.GetHybridLogCheckpointFileName(recoveryInfo.guid), false, false, true);
            recoveryStatus.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);



            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)
                {
                    /*
                     * 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;
                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;
                    }
                }
            }
        }
Exemple #12
0
 public void Initialize(Guid token, long _size)
 {
     info.Initialize(token, _size);
     main_ht_device = new LocalStorageDevice(DirectoryConfiguration.GetPrimaryHashTableFileName(token));
     ofb_device     = new LocalStorageDevice(DirectoryConfiguration.GetOverflowBucketsFileName(token));
 }
Exemple #13
0
 protected void InitializeIndexCheckpoint(Guid indexToken)
 {
     DirectoryConfiguration.CreateIndexCheckpointFolder(indexToken);
     _indexCheckpoint.Initialize(indexToken, state[resizeInfo.version].size);
 }
Exemple #14
0
        protected bool GlobalMoveToNextState(SystemState currentState, SystemState nextState, ref long context)
        {
            var intermediateState = SystemState.Make(Phase.INTERMEDIATE, currentState.version);

            // Move from S1 to I
            if (MakeTransition(currentState, intermediateState))
            {
                // Acquired ownership to make the transition from S1 to S2
                switch (nextState.phase)
                {
                case Phase.PREP_INDEX_CHECKPOINT:
                {
                    _checkpointType = (CheckpointType)context;
                    switch (_checkpointType)
                    {
                    case CheckpointType.INDEX_ONLY:
                    {
                        _indexCheckpointToken = Guid.NewGuid();
                        InitializeIndexCheckpoint(_indexCheckpointToken);
                        break;
                    }

                    case CheckpointType.FULL:
                    {
                        var fullCheckpointToken = Guid.NewGuid();
                        _indexCheckpointToken     = fullCheckpointToken;
                        _hybridLogCheckpointToken = fullCheckpointToken;
                        InitializeIndexCheckpoint(_indexCheckpointToken);
                        InitializeHybridLogCheckpoint(_hybridLogCheckpointToken, currentState.version);
                        break;
                    }

                    default:
                        throw new Exception();
                    }

                    ObtainCurrentTailAddress(ref _indexCheckpoint.info.startLogicalAddress);

                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.INDEX_CHECKPOINT:
                {
                    TakeIndexFuzzyCheckpoint();

                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.PREPARE:
                {
                    switch (currentState.phase)
                    {
                    case Phase.REST:
                    {
                        _checkpointType = (CheckpointType)context;
                        Debug.Assert(_checkpointType == CheckpointType.HYBRID_LOG_ONLY);
                        _hybridLogCheckpointToken = Guid.NewGuid();
                        InitializeHybridLogCheckpoint(_hybridLogCheckpointToken, currentState.version);
                        break;
                    }

                    case Phase.PREP_INDEX_CHECKPOINT:
                    {
                        TakeIndexFuzzyCheckpoint();
                        break;
                    }

                    default:
                        throw new Exception();
                    }

                    ObtainCurrentTailAddress(ref _hybridLogCheckpoint.info.startLogicalAddress);

                    if (!Constants.kFoldOverSnapshot)
                    {
                        _hybridLogCheckpoint.info.flushedLogicalAddress = hlog.FlushedUntilAddress;
                        _hybridLogCheckpoint.info.useSnapshotFile       = 1;
                    }

                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.IN_PROGRESS:
                {
                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.WAIT_PENDING:
                {
                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.WAIT_FLUSH:
                {
                    if (_checkpointType == CheckpointType.FULL)
                    {
                        _indexCheckpoint.info.num_buckets = overflowBucketsAllocator.GetMaxValidAddress();
                        ObtainCurrentTailAddress(ref _indexCheckpoint.info.finalLogicalAddress);
                        WriteIndexMetaFile();
                    }

                    if (Constants.kFoldOverSnapshot)
                    {
                        hlog.ShiftReadOnlyToTail(out long tailAddress);

                        _hybridLogCheckpoint.info.finalLogicalAddress = tailAddress;
                    }
                    else
                    {
                        ObtainCurrentTailAddress(ref _hybridLogCheckpoint.info.finalLogicalAddress);

                        var fileName = DirectoryConfiguration.GetHybridLogCheckpointFileName(_hybridLogCheckpointToken);
                        _hybridLogCheckpoint.snapshotFileDevice = new LocalStorageDevice(fileName, false, false, true);

                        long startPage = hlog.GetPage(_hybridLogCheckpoint.info.flushedLogicalAddress);
                        long endPage   = hlog.GetPage(_hybridLogCheckpoint.info.finalLogicalAddress);
                        if (_hybridLogCheckpoint.info.finalLogicalAddress > hlog.GetStartLogicalAddress(endPage))
                        {
                            endPage++;
                        }

                        new Thread(() =>
                                   hlog.AsyncFlushPagesToDevice(startPage,
                                                                endPage,
                                                                _hybridLogCheckpoint.snapshotFileDevice,
                                                                out _hybridLogCheckpoint.flushed)).Start();
                    }

                    WriteHybridLogMetaInfo();

                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.PERSISTENCE_CALLBACK:
                {
                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.GC:
                {
                    var tmp = hlog.BeginAddress;
                    hlog.BeginAddress = context;
                    context           = tmp;

                    int numChunks = (int)(state[resizeInfo.version].size / Constants.kSizeofChunk);
                    if (numChunks == 0)
                    {
                        numChunks = 1;                         // at least one chunk
                    }
                    numPendingChunksToBeGCed = numChunks;
                    gcStatus = new long[numChunks];

                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.PREPARE_GROW:
                {
                    // Note that the transition must be done before bumping epoch here!
                    MakeTransition(intermediateState, nextState);
                    epoch.BumpCurrentEpoch(() =>
                        {
                            long _context = 0;
                            GlobalMoveToNextState(nextState, SystemState.Make(Phase.IN_PROGRESS_GROW, nextState.version), ref _context);
                        });
                    break;
                }

                case Phase.IN_PROGRESS_GROW:
                {
                    // Set up the transition to new version of HT
                    int numChunks = (int)(state[resizeInfo.version].size / Constants.kSizeofChunk);
                    if (numChunks == 0)
                    {
                        numChunks = 1;                         // at least one chunk
                    }
                    numPendingChunksToBeSplit = numChunks;
                    splitStatus = new long[numChunks];

                    Initialize(1 - resizeInfo.version, state[resizeInfo.version].size * 2, hlog.GetSectorSize());

                    resizeInfo.version = 1 - resizeInfo.version;

                    MakeTransition(intermediateState, nextState);
                    break;
                }

                case Phase.REST:
                {
                    switch (_checkpointType)
                    {
                    case CheckpointType.INDEX_ONLY:
                    {
                        _indexCheckpoint.info.num_buckets = overflowBucketsAllocator.GetMaxValidAddress();
                        ObtainCurrentTailAddress(ref _indexCheckpoint.info.finalLogicalAddress);
                        WriteIndexMetaFile();
                        _indexCheckpoint.Reset();
                        break;
                    }

                    case CheckpointType.FULL:
                    {
                        _indexCheckpoint.Reset();
                        _hybridLogCheckpoint.Reset();
                        break;
                    }

                    case CheckpointType.HYBRID_LOG_ONLY:
                    {
                        _hybridLogCheckpoint.Reset();
                        break;
                    }

                    case CheckpointType.NONE:
                        break;

                    default:
                        throw new Exception();
                    }

                    _checkpointType = CheckpointType.NONE;

                    MakeTransition(intermediateState, nextState);
                    break;
                }
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Create FASTER instance
        /// </summary>
        /// <param name="size">Size of core index (#cache lines)</param>
        /// <param name="comparer">FASTER equality comparer for key</param>
        /// <param name="functions">Callback functions</param>
        /// <param name="logSettings">Log settings</param>
        /// <param name="checkpointSettings">Checkpoint settings</param>
        /// <param name="serializerSettings">Serializer settings</param>
        public FasterKV(long size, Functions functions, LogSettings logSettings, CheckpointSettings checkpointSettings = null, SerializerSettings <Key, Value> serializerSettings = null, IFasterEqualityComparer <Key> comparer = null)
        {
            threadCtx     = new FastThreadLocal <FasterExecutionContext>();
            prevThreadCtx = new FastThreadLocal <FasterExecutionContext>();

            if (comparer != null)
            {
                this.comparer = comparer;
            }
            else
            {
                if (typeof(IFasterEqualityComparer <Key>).IsAssignableFrom(typeof(Key)))
                {
                    this.comparer = new Key() as IFasterEqualityComparer <Key>;
                }
                else
                {
                    Console.WriteLine("***WARNING*** Creating default FASTER key equality comparer based on potentially slow EqualityComparer<Key>.Default. To avoid this, provide a comparer (IFasterEqualityComparer<Key>) as an argument to FASTER's constructor, or make Key implement the interface IFasterEqualityComparer<Key>");
                    this.comparer = FasterEqualityComparer <Key> .Default;
                }
            }

            if (checkpointSettings == null)
            {
                checkpointSettings = new CheckpointSettings();
            }

            directoryConfiguration = new DirectoryConfiguration(checkpointSettings.CheckpointDir);

            FoldOverSnapshot = checkpointSettings.CheckPointType == core.CheckpointType.FoldOver;
            CopyReadsToTail  = logSettings.CopyReadsToTail;
            this.functions   = functions;

            if (logSettings.ReadCacheSettings != null)
            {
                CopyReadsToTail = false;
                UseReadCache    = true;
            }

            if (Utility.IsBlittable <Key>() && Utility.IsBlittable <Value>())
            {
                hlog = new BlittableAllocator <Key, Value>(logSettings, this.comparer, null, epoch);
                Log  = new LogAccessor <Key, Value, Input, Output, Context>(this, hlog);
                if (UseReadCache)
                {
                    readcache = new BlittableAllocator <Key, Value>(
                        new LogSettings {
                        PageSizeBits    = logSettings.ReadCacheSettings.PageSizeBits,
                        MemorySizeBits  = logSettings.ReadCacheSettings.MemorySizeBits,
                        SegmentSizeBits = logSettings.ReadCacheSettings.MemorySizeBits,
                        MutableFraction = logSettings.ReadCacheSettings.SecondChanceFraction
                    }, this.comparer, ReadCacheEvict, epoch);
                    readcache.Initialize();
                    ReadCache = new LogAccessor <Key, Value, Input, Output, Context>(this, readcache);
                }
            }
            else
            {
                hlog = new GenericAllocator <Key, Value>(logSettings, serializerSettings, this.comparer, null, epoch);
                Log  = new LogAccessor <Key, Value, Input, Output, Context>(this, hlog);
                if (UseReadCache)
                {
                    readcache = new GenericAllocator <Key, Value>(
                        new LogSettings
                    {
                        PageSizeBits    = logSettings.ReadCacheSettings.PageSizeBits,
                        MemorySizeBits  = logSettings.ReadCacheSettings.MemorySizeBits,
                        SegmentSizeBits = logSettings.ReadCacheSettings.MemorySizeBits,
                        MutableFraction = logSettings.ReadCacheSettings.SecondChanceFraction
                    }, serializerSettings, this.comparer, ReadCacheEvict, epoch);
                    readcache.Initialize();
                    ReadCache = new LogAccessor <Key, Value, Input, Output, Context>(this, readcache);
                }
            }

            hlog.Initialize();

            sectorSize = (int)logSettings.LogDevice.SectorSize;
            Initialize(size, sectorSize);

            _systemState         = default(SystemState);
            _systemState.phase   = Phase.REST;
            _systemState.version = 1;
            _checkpointType      = CheckpointType.HYBRID_LOG_ONLY;
        }
Exemple #16
0
 protected void InitializeHybridLogCheckpoint(Guid hybridLogToken, int version)
 {
     DirectoryConfiguration.CreateHybridLogCheckpointFolder(hybridLogToken);
     _hybridLogCheckpoint.Initialize(hybridLogToken, version);
 }
 /// <summary>
 /// Create new instance of local checkpoint manager at given base directory
 /// </summary>
 /// <param name="CheckpointDir"></param>
 public LocalCheckpointManager(string CheckpointDir)
 {
     directoryConfiguration = new DirectoryConfiguration(CheckpointDir);
 }
Exemple #18
0
 public void Initialize(Guid token, long _size)
 {
     info.Initialize(token, _size);
     main_ht_device = new WrappedDevice(new SegmentedLocalStorageDevice(DirectoryConfiguration.GetPrimaryHashTableFileName(token), 1L << 30, false, false, true));
     ofb_device     = new LocalStorageDevice(DirectoryConfiguration.GetOverflowBucketsFileName(token), false, false, true);
 }