/// <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); } }
public void Recover(Guid guid, DirectoryConfiguration directoryConfiguration) { string indexInfoFile = directoryConfiguration.GetIndexCheckpointMetaFileName(guid); using (var reader = new StreamReader(indexInfoFile)) { Initialize(reader); } }
protected void WriteIndexMetaFile() { string filename = DirectoryConfiguration.GetIndexCheckpointMetaFileName(_indexCheckpointToken); using (var file = new StreamWriter(filename, false)) { _indexCheckpoint.info.Write(file); file.Flush(); } }
protected void WriteHybridLogMetaInfo() { string filename = DirectoryConfiguration.GetHybridLogCheckpointMetaFileName(_hybridLogCheckpointToken); using (var file = new StreamWriter(filename, false)) { _hybridLogCheckpoint.info.Write(file); file.Flush(); } }
protected void WriteHybridLogContextInfo() { string filename = DirectoryConfiguration.GetHybridLogCheckpointContextFileName(_hybridLogCheckpointToken, prevThreadCtx.guid); using (var file = new StreamWriter(filename, false)) { prevThreadCtx.Write(file); file.Flush(); } }
/// <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; }
// 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); }
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); }
public void Recover(Guid token, DirectoryConfiguration directoryConfiguration) { info.Recover(token, directoryConfiguration); }
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); }
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; } } } }
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)); }
protected void InitializeIndexCheckpoint(Guid indexToken) { DirectoryConfiguration.CreateIndexCheckpointFolder(indexToken); _indexCheckpoint.Initialize(indexToken, state[resizeInfo.version].size); }
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; }
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); }
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); }