Exemple #1
0
        private void Compact <T>(T functions, long untilAddress, VariableLengthStructSettings <Key, Value> variableLengthStructSettings)
            where T : IFunctions <Key, Value, Input, Output, Context>
        {
            var fhtSession = fht.NewSession();

            var originalUntilAddress = untilAddress;

            var tempKv = new FasterKV <Key, Value, Input, Output, Context, T>
                             (fht.IndexSize, functions, new LogSettings(), comparer: fht.Comparer, variableLengthStructSettings: variableLengthStructSettings);
            var tempKvSession = tempKv.NewSession();

            using (var iter1 = fht.Log.Scan(fht.Log.BeginAddress, untilAddress))
            {
                while (iter1.GetNext(out RecordInfo recordInfo))
                {
                    ref var key   = ref iter1.GetKey();
                    ref var value = ref iter1.GetValue();

                    if (recordInfo.Tombstone)
                    {
                        tempKvSession.Delete(ref key, default, 0);
        /// <inheritdoc />
        public void OnThreadState <Key, Value, Input, Output, Context, FasterSession>(
            SystemState current,
            SystemState prev,
            FasterKV <Key, Value> faster,
            FasterKV <Key, Value> .FasterExecutionContext <Input, Output, Context> ctx,
            FasterSession fasterSession,
            List <ValueTask> valueTasks,
            CancellationToken token = default)
            where FasterSession : IFasterSession
        {
            switch (current.phase)
            {
            case Phase.PREPARE_GROW:
            case Phase.IN_PROGRESS_GROW:
            case Phase.REST:
                return;

            default:
                throw new FasterException("Invalid Enum Argument");
            }
        }
        protected void CollectMetadata <Key, Value>(SystemState next, FasterKV <Key, Value> faster)
        {
            // Collect object log offsets only after flushes
            // are completed
            var seg = faster.hlog.GetSegmentOffsets();

            if (seg != null)
            {
                faster._hybridLogCheckpoint.info.objectLogSegmentOffsets = new long[seg.Length];
                Array.Copy(seg, faster._hybridLogCheckpoint.info.objectLogSegmentOffsets, seg.Length);
            }

            // Temporarily block new sessions from starting, which may add an entry to the table and resize the
            // dictionary. There should be minimal contention here.
            lock (faster._activeSessions)
                // write dormant sessions to checkpoint
                foreach (var kvp in faster._activeSessions)
                {
                    kvp.Value.AtomicSwitch(next.version - 1);
                }
        }
Exemple #4
0
        internal ClientSession(
            FasterKV <Key, Value> fht,
            FasterKV <Key, Value> .FasterExecutionContext <Input, Output, Context> ctx,
            Functions functions,
            bool supportAsync)
        {
            this.fht          = fht;
            this.ctx          = ctx;
            this.functions    = functions;
            SupportAsync      = supportAsync;
            LatestCommitPoint = new CommitPoint {
                UntilSerialNo = -1, ExcludedSerialNos = null
            };
            FasterSession = new AsyncFasterSession(this);

            // Session runs on a single thread
            if (!supportAsync)
            {
                UnsafeResumeThread();
            }
        }
        /// <inheritdoc />
        public void GlobalAfterEnteringState <Key, Value>(
            SystemState next,
            FasterKV <Key, Value> faster)
            where Key : new()
            where Value : new()
        {
            switch (next.phase)
            {
            case Phase.PREPARE_GROW:
                faster.epoch.BumpCurrentEpoch(() => faster.GlobalStateMachineStep(next));
                break;

            case Phase.IN_PROGRESS_GROW:
            case Phase.REST:
                // nothing to do
                break;

            default:
                throw new FasterException("Invalid Enum Argument");
            }
        }
Exemple #6
0
        /// <summary>
        /// Compact the log until specified address, moving active records to the tail of the log.
        /// </summary>
        /// <param name="functions">Functions used to manage key-values during compaction</param>
        /// <param name="cf">User provided compaction functions (see <see cref="ICompactionFunctions{Key, Value}"/>).</param>
        /// <param name="untilAddress">Compact log until this address</param>
        /// <param name="shiftBeginAddress">Whether to shift begin address to untilAddress after compaction. To avoid
        /// data loss on failure, set this to false, and shift begin address only after taking a checkpoint. This
        /// ensures that records written to the tail during compaction are first made stable.</param>
        /// <returns>Address until which compaction was done</returns>
        public long Compact <Input, Output, Context, Functions, CompactionFunctions>(Functions functions, CompactionFunctions cf, long untilAddress, bool shiftBeginAddress)
            where Functions : IFunctions <Key, Value, Input, Output, Context>
            where CompactionFunctions : ICompactionFunctions <Key, Value>
        {
            if (untilAddress > fht.Log.SafeReadOnlyAddress)
            {
                throw new FasterException("Can compact only until Log.SafeReadOnlyAddress");
            }
            var originalUntilAddress = untilAddress;

            var lf = new LogCompactionFunctions <Key, Value, Input, Output, Context, Functions>(functions);

            using var fhtSession = fht.For(lf).NewSession <LogCompactionFunctions <Key, Value, Input, Output, Context, Functions> >();

            VariableLengthStructSettings <Key, Value> variableLengthStructSettings = null;

            if (allocator is VariableLengthBlittableAllocator <Key, Value> varLen)
            {
                variableLengthStructSettings = new VariableLengthStructSettings <Key, Value>
                {
                    keyLength   = varLen.KeyLength,
                    valueLength = varLen.ValueLength,
                };
            }

            using (var tempKv = new FasterKV <Key, Value>(fht.IndexSize, new LogSettings {
                LogDevice = new NullDevice(), ObjectLogDevice = new NullDevice()
            }, comparer: fht.Comparer, variableLengthStructSettings: variableLengthStructSettings))
                using (var tempKvSession = tempKv.NewSession <Input, Output, Context, Functions>(functions))
                {
                    using (var iter1 = fht.Log.Scan(fht.Log.BeginAddress, untilAddress))
                    {
                        while (iter1.GetNext(out var recordInfo))
                        {
                            ref var key   = ref iter1.GetKey();
                            ref var value = ref iter1.GetValue();

                            if (recordInfo.Tombstone || cf.IsDeleted(key, value))
                            {
                                tempKvSession.Delete(ref key, default, 0);
Exemple #7
0
        private void LogScanForValidity(ref long untilAddress, ref long scanUntil, ref FasterKV <Key, Value, Input, Output, Context, LogCompactFunctions> tempKv)
        {
            while (scanUntil < fht.Log.SafeReadOnlyAddress)
            {
                untilAddress = scanUntil;
                scanUntil    = fht.Log.SafeReadOnlyAddress;
                int cnt = 0;
                using (var iter2 = fht.Log.Scan(untilAddress, scanUntil))
                {
                    while (iter2.GetNext(out RecordInfo recordInfo, out Key key, out Value value))
                    {
                        tempKv.Delete(ref key, default(Context), 0);

                        if (++cnt % 1000 == 0)
                        {
                            fht.Refresh();
                        }
                    }
                }
                fht.Refresh();
            }
        }
Exemple #8
0
        public FasterKVIterator(FasterKV <Key, Value> fht, Functions functions, long untilAddress)
        {
            this.fht         = fht;
            enumerationPhase = 0;

            VariableLengthStructSettings <Key, Value> variableLengthStructSettings = null;

            if (fht.hlog is VariableLengthBlittableAllocator <Key, Value> varLen)
            {
                variableLengthStructSettings = new VariableLengthStructSettings <Key, Value>
                {
                    keyLength   = varLen.KeyLength,
                    valueLength = varLen.ValueLength,
                };
            }

            tempKv = new FasterKV <Key, Value>(fht.IndexSize, new LogSettings {
                LogDevice = new NullDevice(), ObjectLogDevice = new NullDevice(), MutableFraction = 1
            }, comparer: fht.Comparer, variableLengthStructSettings: variableLengthStructSettings);
            tempKvSession = tempKv.NewSession <Input, Output, Context, Functions>(functions);
            iter1         = fht.Log.Scan(fht.Log.BeginAddress, untilAddress);
        }
Exemple #9
0
        internal ClientSession(
            FasterKV <Key, Value> fht,
            FasterKV <Key, Value> .FasterExecutionContext <Input, Output, Context> ctx,
            Functions functions,
            bool supportAsync,
            IVariableLengthStruct <Value, Input> variableLengthStruct)
        {
            this.fht          = fht;
            this.ctx          = ctx;
            this.functions    = functions;
            SupportAsync      = supportAsync;
            LatestCommitPoint = new CommitPoint {
                UntilSerialNo = -1, ExcludedSerialNos = null
            };
            FasterSession = new AsyncFasterSession(this);

            this.variableLengthStruct = variableLengthStruct;
            if (this.variableLengthStruct == default)
            {
                if (fht.hlog is VariableLengthBlittableAllocator <Key, Value> allocator)
                {
                    Debug.WriteLine("Warning: Session did not specify Input-specific functions for variable-length values via IVariableLengthStruct<Value, Input>");
                    this.variableLengthStruct = new DefaultVariableLengthStruct <Value, Input>(allocator.ValueLength);
                }
            }
            else
            {
                if (!(fht.hlog is VariableLengthBlittableAllocator <Key, Value>))
                {
                    Debug.WriteLine("Warning: Session param of variableLengthStruct provided for non-varlen allocator");
                }
            }

            // Session runs on a single thread
            if (!supportAsync)
            {
                UnsafeResumeThread();
            }
        }
        /// <inheritdoc />
        public virtual void GlobalBeforeEnteringState <Key, Value>(SystemState next,
                                                                   FasterKV <Key, Value> faster)
        {
            switch (next.Phase)
            {
            case Phase.PREPARE:
                lastVersion = faster.systemState.Version;
                if (faster._hybridLogCheckpoint.IsDefault())
                {
                    faster._hybridLogCheckpointToken = Guid.NewGuid();
                    faster.InitializeHybridLogCheckpoint(faster._hybridLogCheckpointToken, next.Version);
                }
                faster._hybridLogCheckpoint.info.version = next.Version;
                faster.ObtainCurrentTailAddress(ref faster._hybridLogCheckpoint.info.startLogicalAddress);
                break;

            case Phase.WAIT_FLUSH:
                faster._hybridLogCheckpoint.info.headAddress  = faster.hlog.HeadAddress;
                faster._hybridLogCheckpoint.info.beginAddress = faster.hlog.BeginAddress;
                faster._hybridLogCheckpoint.info.nextVersion  = next.Version;
                break;

            case Phase.PERSISTENCE_CALLBACK:
                CollectMetadata(next, faster);
                faster.WriteHybridLogMetaInfo();
                faster.lastVersion = lastVersion;
                break;

            case Phase.REST:
                faster._hybridLogCheckpoint.Dispose();
                var nextTcs = new TaskCompletionSource <LinkedCheckpointInfo>(TaskCreationOptions.RunContinuationsAsynchronously);
                faster.checkpointTcs.SetResult(new LinkedCheckpointInfo {
                    NextTask = nextTcs.Task
                });
                faster.checkpointTcs = nextTcs;
                break;
            }
        }
        /// <inheritdoc />
        public void GlobalBeforeEnteringState <Key, Value, Input, Output, Context, Functions>(
            SystemState next,
            FasterKV <Key, Value, Input, Output, Context, Functions> faster)
            where Key : new()
            where Value : new()
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            switch (next.phase)
            {
            case Phase.PREP_INDEX_CHECKPOINT:
                Debug.Assert(faster._indexCheckpointToken == default &&
                             faster._hybridLogCheckpointToken == default);
                var fullCheckpointToken = Guid.NewGuid();
                faster._indexCheckpointToken     = fullCheckpointToken;
                faster._hybridLogCheckpointToken = fullCheckpointToken;
                faster.InitializeIndexCheckpoint(faster._indexCheckpointToken);
                faster.InitializeHybridLogCheckpoint(faster._hybridLogCheckpointToken, next.version);
                break;

            case Phase.PREPARE:
                if (faster.UseReadCache && faster.ReadCache.BeginAddress != faster.ReadCache.TailAddress)
                {
                    throw new FasterException("Index checkpoint with read cache is not supported");
                }
                faster.TakeIndexFuzzyCheckpoint();
                break;

            case Phase.WAIT_FLUSH:
                faster._indexCheckpoint.info.num_buckets = faster.overflowBucketsAllocator.GetMaxValidAddress();
                faster.ObtainCurrentTailAddress(ref faster._indexCheckpoint.info.finalLogicalAddress);
                break;

            case Phase.PERSISTENCE_CALLBACK:
                faster.WriteIndexMetaInfo();
                faster._indexCheckpointToken = default;
                break;
            }
        }
Exemple #12
0
        /// <inheritdoc />
        public void GlobalBeforeEnteringState <Key, Value>(
            SystemState next,
            FasterKV <Key, Value> faster)
        {
            switch (next.phase)
            {
            case Phase.PREP_INDEX_CHECKPOINT:
                if (faster._indexCheckpoint.IsDefault())
                {
                    faster._indexCheckpointToken = Guid.NewGuid();
                    faster.InitializeIndexCheckpoint(faster._indexCheckpointToken);
                }

                faster.ObtainCurrentTailAddress(ref faster._indexCheckpoint.info.startLogicalAddress);
                faster.TakeIndexFuzzyCheckpoint();
                break;

            case Phase.WAIT_INDEX_CHECKPOINT:
            case Phase.WAIT_INDEX_ONLY_CHECKPOINT:
                break;

            case Phase.REST:
                // If the tail address has already been obtained, because another task on the state machine
                // has done so earlier (e.g. FullCheckpoint captures log tail at WAIT_FLUSH), don't update
                // the tail address.
                if (faster.ObtainCurrentTailAddress(ref faster._indexCheckpoint.info.finalLogicalAddress))
                {
                    faster._indexCheckpoint.info.num_buckets = faster.overflowBucketsAllocator.GetMaxValidAddress();
                }
                if (!faster._indexCheckpoint.IsDefault())
                {
                    faster.WriteIndexMetaInfo();
                    faster._indexCheckpoint.Reset();
                }

                break;
            }
        }
Exemple #13
0
        /// <inheritdoc />
        public ValueTask OnThreadState <Key, Value, Input, Output, Context, Functions>(
            SystemState current,
            SystemState prev,
            FasterKV <Key, Value, Input, Output, Context, Functions> faster,
            FasterKV <Key, Value, Input, Output, Context, Functions> .FasterExecutionContext ctx,
            ClientSession <Key, Value, Input, Output, Context, Functions> clientSession,
            bool async = true,
            CancellationToken token = default)
            where Key : new()
            where Value : new()
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            switch (current.phase)
            {
            case Phase.PREPARE_GROW:
            case Phase.IN_PROGRESS_GROW:
            case Phase.REST:
                return(default);

            default:
                throw new FasterException("Invalid Enum Argument");
            }
        }
Exemple #14
0
        /// <inheritdoc />
        public void GlobalBeforeEnteringState <Key, Value, Input, Output, Context, Functions>(
            SystemState next,
            FasterKV <Key, Value, Input, Output, Context, Functions> faster)
            where Key : new()
            where Value : new()
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            switch (next.phase)
            {
            case Phase.PREPARE_GROW:
                // nothing to do
                break;

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

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

                faster.resizeInfo.version = 1 - faster.resizeInfo.version;
                break;

            case Phase.REST:
                // nothing to do
                break;

            default:
                throw new FasterException("Invalid Enum Argument");
            }
        }
Exemple #15
0
        private static async ValueTask <ReadAsyncResult <Input, Output, Context, Functions> > SlowReadAsync <Input, Output, Context, Functions>(
            FasterKV <Key, Value> @this,
            ClientSession <Key, Value, Input, Output, Context, Functions> clientSession,
            PendingContext <Input, Output, Context> pendingContext, CancellationToken token = default)
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            var diskRequest = @this.ScheduleGetFromDisk(clientSession.ctx, ref pendingContext);

            clientSession.ctx.ioPendingRequests.Add(pendingContext.id, pendingContext);
            clientSession.ctx.asyncPendingCount++;
            clientSession.ctx.pendingReads.Add();

            try
            {
                token.ThrowIfCancellationRequested();

                if (@this.epoch.ThisInstanceProtected())
                {
                    throw new NotSupportedException("Async operations not supported over protected epoch");
                }

                diskRequest = await diskRequest.asyncOperation.Task;
            }
            catch
            {
                clientSession.ctx.ioPendingRequests.Remove(pendingContext.id);
                clientSession.ctx.asyncPendingCount--;
                throw;
            }
            finally
            {
                clientSession.ctx.pendingReads.Remove();
            }

            return(new ReadAsyncResult <Input, Output, Context, Functions>(@this, clientSession, pendingContext, diskRequest));
        }
Exemple #16
0
 public LegacyFasterSession(FasterKV <Key, Value, Input, Output, Context, Functions> fasterKV)
 {
     _fasterKV = fasterKV;
 }
Exemple #17
0
        internal ClientSession(
            FasterKV <Key, Value> fht,
            FasterKV <Key, Value> .FasterExecutionContext <Input, Output, Context> ctx,
            Functions functions,
            bool supportAsync,
            SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
        {
            this.fht          = fht;
            this.ctx          = ctx;
            this.functions    = functions;
            SupportAsync      = supportAsync;
            LatestCommitPoint = new CommitPoint {
                UntilSerialNo = -1, ExcludedSerialNos = null
            };
            FasterSession = new AsyncFasterSession(this);

            this.variableLengthStruct = sessionVariableLengthStructSettings?.valueLength;
            if (this.variableLengthStruct == default)
            {
                UpdateVarlen(ref this.variableLengthStruct);

                if ((this.variableLengthStruct == default) && (fht.hlog is VariableLengthBlittableAllocator <Key, Value> allocator))
                {
                    Debug.WriteLine("Warning: Session did not specify Input-specific functions for variable-length values via IVariableLengthStruct<Value, Input>");
                    this.variableLengthStruct = new DefaultVariableLengthStruct <Value, Input>(allocator.ValueLength);
                }
            }
            else
            {
                if (!(fht.hlog is VariableLengthBlittableAllocator <Key, Value>))
                {
                    Debug.WriteLine("Warning: Session param of variableLengthStruct provided for non-varlen allocator");
                }
            }

            this.inputVariableLengthStruct = sessionVariableLengthStructSettings?.inputLength;

            if (inputVariableLengthStruct == default)
            {
                if (typeof(Input) == typeof(SpanByte))
                {
                    inputVariableLengthStruct = new SpanByteVarLenStruct() as IVariableLengthStruct <Input>;
                }
                else if (typeof(Input).IsGenericType && (typeof(Input).GetGenericTypeDefinition() == typeof(Memory <>)) && Utility.IsBlittableType(typeof(Input).GetGenericArguments()[0]))
                {
                    var    m = typeof(MemoryVarLenStruct <>).MakeGenericType(typeof(Input).GetGenericArguments());
                    object o = Activator.CreateInstance(m);
                    inputVariableLengthStruct = o as IVariableLengthStruct <Input>;
                }
                else if (typeof(Input).IsGenericType && (typeof(Input).GetGenericTypeDefinition() == typeof(ReadOnlyMemory <>)) && Utility.IsBlittableType(typeof(Input).GetGenericArguments()[0]))
                {
                    var    m = typeof(ReadOnlyMemoryVarLenStruct <>).MakeGenericType(typeof(Input).GetGenericArguments());
                    object o = Activator.CreateInstance(m);
                    inputVariableLengthStruct = o as IVariableLengthStruct <Input>;
                }
            }

            // Session runs on a single thread
            if (!supportAsync)
            {
                UnsafeResumeThread();
            }
        }
Exemple #18
0
        /// <inheritdoc />
        public void OnThreadState <Key, Value, Input, Output, Context, FasterSession>(
            SystemState current, SystemState prev,
            FasterKV <Key, Value> faster,
            FasterKV <Key, Value> .FasterExecutionContext <Input, Output, Context> ctx,
            FasterSession fasterSession,
            List <ValueTask> valueTasks,
            CancellationToken token = default)
            where FasterSession : IFasterSession
        {
            switch (current.phase)
            {
            case Phase.PREPARE:
                if (ctx != null)
                {
                    if (!ctx.markers[EpochPhaseIdx.Prepare])
                    {
                        if (!faster.RelaxedCPR)
                        {
                            faster.AcquireSharedLatchesForAllPendingRequests(ctx);
                        }
                        ctx.markers[EpochPhaseIdx.Prepare] = true;
                    }

                    faster.epoch.Mark(EpochPhaseIdx.Prepare, current.version);
                }

                if (faster.epoch.CheckIsComplete(EpochPhaseIdx.Prepare, current.version))
                {
                    faster.GlobalStateMachineStep(current);
                }
                break;

            case Phase.IN_PROGRESS:
                if (ctx != null)
                {
                    // Need to be very careful here as threadCtx is changing
                    var _ctx   = prev.phase == Phase.IN_PROGRESS ? ctx.prevCtx : ctx;
                    var tokens = faster._hybridLogCheckpoint.info.checkpointTokens;
                    if (!faster.SameCycle(current) || tokens == null)
                    {
                        return;
                    }

                    if (!_ctx.markers[EpochPhaseIdx.InProgress])
                    {
                        faster.AtomicSwitch(ctx, ctx.prevCtx, _ctx.version, tokens);
                        faster.InitContext(ctx, ctx.prevCtx.guid, ctx.prevCtx.serialNum);

                        // Has to be prevCtx, not ctx
                        ctx.prevCtx.markers[EpochPhaseIdx.InProgress] = true;
                    }

                    faster.epoch.Mark(EpochPhaseIdx.InProgress, current.version);
                }

                // Has to be prevCtx, not ctx
                if (faster.epoch.CheckIsComplete(EpochPhaseIdx.InProgress, current.version))
                {
                    faster.GlobalStateMachineStep(current);
                }
                break;

            case Phase.WAIT_PENDING:
                if (ctx != null)
                {
                    if (!faster.RelaxedCPR && !ctx.prevCtx.markers[EpochPhaseIdx.WaitPending])
                    {
                        if (ctx.prevCtx.HasNoPendingRequests)
                        {
                            ctx.prevCtx.markers[EpochPhaseIdx.WaitPending] = true;
                        }
                        else
                        {
                            break;
                        }
                    }

                    faster.epoch.Mark(EpochPhaseIdx.WaitPending, current.version);
                }

                if (faster.epoch.CheckIsComplete(EpochPhaseIdx.WaitPending, current.version))
                {
                    faster.GlobalStateMachineStep(current);
                }
                break;

            case Phase.REST:
                break;
            }
        }
Exemple #19
0
 /// <inheritdoc />
 public void GlobalAfterEnteringState <Key, Value>(
     SystemState start,
     FasterKV <Key, Value> faster)
 {
 }
Exemple #20
0
 /// <inheritdoc />
 public void GlobalBeforeEnteringState <Key, Value>(
     SystemState next,
     FasterKV <Key, Value> faster)
 {
 }
        /// <summary>
        /// Compact the log until specified address, moving active
        /// records to the tail of the log
        /// </summary>
        /// <param name="untilAddress"></param>
        public void Compact(long untilAddress)
        {
            long originalUntilAddress = untilAddress;

            var tempKv = new FasterKV <Key, Value, Input, Output, Context, LogCompactFunctions>
                             (fht.IndexSize, new LogCompactFunctions(), new LogSettings(), comparer: fht.Comparer);

            tempKv.StartSession();

            int cnt = 0;

            using (var iter1 = fht.Log.Scan(fht.Log.BeginAddress, untilAddress))
            {
                while (iter1.GetNext(out RecordInfo recordInfo, out Key key, out Value value))
                {
                    if (recordInfo.Tombstone)
                    {
                        tempKv.Delete(ref key, default(Context), 0);
                    }
                    else
                    {
                        tempKv.Upsert(ref key, ref value, default(Context), 0);
                    }

                    if (++cnt % 1000 == 0)
                    {
                        fht.Refresh();
                        tempKv.Refresh();
                    }
                }
            }

            // TODO: Scan until SafeReadOnlyAddress
            long scanUntil = untilAddress;

            LogScanForValidity(ref untilAddress, ref scanUntil, ref tempKv);

            // Make sure key wasn't inserted between SafeReadOnlyAddress and TailAddress

            cnt = 0;
            using (var iter3 = tempKv.Log.Scan(tempKv.Log.BeginAddress, tempKv.Log.TailAddress))
            {
                while (iter3.GetNext(out RecordInfo recordInfo, out Key key, out Value value))
                {
                    if (!recordInfo.Tombstone)
                    {
                        if (fht.ContainsKeyInMemory(ref key, scanUntil) == Status.NOTFOUND)
                        {
                            fht.Upsert(ref key, ref value, default(Context), 0);
                        }
                    }
                    if (++cnt % 1000 == 0)
                    {
                        fht.Refresh();
                        tempKv.Refresh();
                    }
                    if (scanUntil < fht.Log.SafeReadOnlyAddress)
                    {
                        LogScanForValidity(ref untilAddress, ref scanUntil, ref tempKv);
                    }
                }
            }
            tempKv.StopSession();
            tempKv.Dispose();

            ShiftBeginAddress(originalUntilAddress);
        }
Exemple #22
0
 internal ReadAsyncResult(Status status, Output output)
 {
     this.status       = status;
     this.output       = output;
     readAsyncInternal = default;
 }
 /// <inheritdoc />
 public virtual void GlobalAfterEnteringState <Key, Value>(SystemState next,
                                                           FasterKV <Key, Value> faster)
 {
 }
        /// <inheritdoc />
        public override void GlobalBeforeEnteringState <Key, Value>(SystemState next, FasterKV <Key, Value> faster)
        {
            switch (next.Phase)
            {
            case Phase.PREPARE:
                faster._hybridLogCheckpoint = faster._lastSnapshotCheckpoint;
                base.GlobalBeforeEnteringState(next, faster);
                faster._hybridLogCheckpoint.info.startLogicalAddress = faster.hlog.FlushedUntilAddress;
                faster._hybridLogCheckpoint.prevVersion = next.Version;
                break;

            case Phase.WAIT_FLUSH:
                base.GlobalBeforeEnteringState(next, faster);
                faster._hybridLogCheckpoint.info.finalLogicalAddress = 0;
                faster.ObtainCurrentTailAddress(ref faster._hybridLogCheckpoint.info.finalLogicalAddress);

                if (faster._hybridLogCheckpoint.deltaLog == null)
                {
                    faster._hybridLogCheckpoint.deltaFileDevice = faster.checkpointManager.GetDeltaLogDevice(faster._hybridLogCheckpointToken);
                    faster._hybridLogCheckpoint.deltaFileDevice.Initialize(-1);
                    faster._hybridLogCheckpoint.deltaLog = new DeltaLog(faster._hybridLogCheckpoint.deltaFileDevice, faster.hlog.LogPageSizeBits, -1);
                    faster._hybridLogCheckpoint.deltaLog.InitializeForWrites(faster.hlog.bufferPool);
                }

                faster.hlog.AsyncFlushDeltaToDevice(
                    faster._hybridLogCheckpoint.info.startLogicalAddress,
                    faster._hybridLogCheckpoint.info.finalLogicalAddress,
                    faster._lastSnapshotCheckpoint.info.finalLogicalAddress,
                    faster._hybridLogCheckpoint.prevVersion,
                    faster._hybridLogCheckpoint.deltaLog);
                break;

            case Phase.PERSISTENCE_CALLBACK:
                faster._hybridLogCheckpoint.info.flushedLogicalAddress = faster.hlog.FlushedUntilAddress;
                CollectMetadata(next, faster);
                faster.WriteHybridLogIncrementalMetaInfo(faster._hybridLogCheckpoint.deltaLog);
                faster._hybridLogCheckpoint.info.deltaTailAddress = faster._hybridLogCheckpoint.deltaLog.TailAddress;
                faster._lastSnapshotCheckpoint = faster._hybridLogCheckpoint.Transfer();
                faster._hybridLogCheckpoint.Dispose();
                break;
            }
        }
Exemple #25
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="fht"></param>
 /// <param name="allocator"></param>
 public LogAccessor(FasterKV <Key, Value, Input, Output, Context, Functions> fht, AllocatorBase <Key, Value> allocator)
 {
     this.fht       = fht;
     this.allocator = allocator;
 }
Exemple #26
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="fht"></param>
 /// <param name="allocator"></param>
 public LogAccessor(FasterKV <Key, Value> fht, AllocatorBase <Key, Value> allocator)
 {
     this.fht       = fht;
     this.allocator = allocator;
 }
Exemple #27
0
        /// <inheritdoc />
        public ValueTask OnThreadState <Key, Value, Input, Output, Context, Functions>(
            SystemState current, SystemState prev,
            FasterKV <Key, Value, Input, Output, Context, Functions> faster,
            FasterKV <Key, Value, Input, Output, Context, Functions> .FasterExecutionContext ctx,
            ClientSession <Key, Value, Input, Output, Context, Functions> clientSession,
            bool async = true,
            CancellationToken token = default)
            where Key : new()
            where Value : new()
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            switch (current.phase)
            {
            case Phase.PREPARE:
                if (ctx != null)
                {
                    if (!ctx.markers[EpochPhaseIdx.Prepare])
                    {
                        if (!faster.RelaxedCPR)
                        {
                            faster.AcquireSharedLatchesForAllPendingRequests(ctx);
                        }
                        ctx.markers[EpochPhaseIdx.Prepare] = true;
                    }

                    faster.epoch.Mark(EpochPhaseIdx.Prepare, current.version);
                }

                if (faster.epoch.CheckIsComplete(EpochPhaseIdx.Prepare, current.version))
                {
                    faster.GlobalStateMachineStep(current);
                }
                break;

            case Phase.IN_PROGRESS:
                if (ctx != null)
                {
                    // Need to be very careful here as threadCtx is changing
                    var _ctx = prev.phase == Phase.IN_PROGRESS ? ctx.prevCtx : ctx;

                    if (!_ctx.markers[EpochPhaseIdx.InProgress])
                    {
                        faster.AtomicSwitch(ctx, ctx.prevCtx, _ctx.version);
                        faster.InitContext(ctx, ctx.prevCtx.guid, ctx.prevCtx.serialNum);

                        // Has to be prevCtx, not ctx
                        ctx.prevCtx.markers[EpochPhaseIdx.InProgress] = true;
                    }

                    faster.epoch.Mark(EpochPhaseIdx.InProgress, current.version);
                }

                // Has to be prevCtx, not ctx
                if (faster.epoch.CheckIsComplete(EpochPhaseIdx.InProgress, current.version))
                {
                    faster.GlobalStateMachineStep(current);
                }
                break;

            case Phase.WAIT_PENDING:
                if (ctx != null)
                {
                    if (!faster.RelaxedCPR && !ctx.prevCtx.markers[EpochPhaseIdx.WaitPending])
                    {
                        if (ctx.prevCtx.HasNoPendingRequests)
                        {
                            ctx.prevCtx.markers[EpochPhaseIdx.WaitPending] = true;
                        }
                        else
                        {
                            break;
                        }
                    }

                    faster.epoch.Mark(EpochPhaseIdx.WaitPending, current.version);
                }

                if (faster.epoch.CheckIsComplete(EpochPhaseIdx.WaitPending, current.version))
                {
                    faster.GlobalStateMachineStep(current);
                }
                break;

            case Phase.REST:
                break;
            }

            return(default);
Exemple #28
0
 /// <inheritdoc />
 public void GlobalAfterEnteringState <Key, Value, Input, Output, Context, Functions>(SystemState next,
                                                                                      FasterKV <Key, Value, Input, Output, Context, Functions> faster) where Key : new()
     where Value : new()
     where Functions : IFunctions <Key, Value, Input, Output, Context>
 {
     foreach (var task in tasks)
     {
         task.GlobalAfterEnteringState(next, faster);
     }
 }
        /// <inheritdoc />
        public async ValueTask OnThreadState <Key, Value, Input, Output, Context, Functions>(SystemState current,
                                                                                             SystemState prev,
                                                                                             FasterKV <Key, Value, Input, Output, Context, Functions> faster,
                                                                                             FasterKV <Key, Value, Input, Output, Context, Functions> .FasterExecutionContext ctx,
                                                                                             ClientSession <Key, Value, Input, Output, Context, Functions> clientSession, bool async = true,
                                                                                             CancellationToken token = default) where Key : new()
            where Value : new()
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            if (current.phase != Phase.WAIT_INDEX_CHECKPOINT)
            {
                return;
            }

            if (async && !faster.IsIndexFuzzyCheckpointCompleted())
            {
                clientSession?.UnsafeSuspendThread();
                await faster.IsIndexFuzzyCheckpointCompletedAsync(token);

                clientSession?.UnsafeResumeThread();
            }

            faster.GlobalStateMachineStep(current);
        }
        /// <inheritdoc />
        public override void GlobalBeforeEnteringState <Key, Value>(SystemState next, FasterKV <Key, Value> faster)
        {
            switch (next.Phase)
            {
            case Phase.PREPARE:
                faster._lastSnapshotCheckpoint.Dispose();
                base.GlobalBeforeEnteringState(next, faster);
                faster._hybridLogCheckpoint.info.startLogicalAddress = faster.hlog.FlushedUntilAddress;
                faster._hybridLogCheckpoint.info.useSnapshotFile     = 1;
                break;

            case Phase.WAIT_FLUSH:
                base.GlobalBeforeEnteringState(next, faster);
                faster.ObtainCurrentTailAddress(ref faster._hybridLogCheckpoint.info.finalLogicalAddress);
                faster._hybridLogCheckpoint.info.snapshotFinalLogicalAddress = faster._hybridLogCheckpoint.info.finalLogicalAddress;

                faster._hybridLogCheckpoint.snapshotFileDevice =
                    faster.checkpointManager.GetSnapshotLogDevice(faster._hybridLogCheckpointToken);
                faster._hybridLogCheckpoint.snapshotFileObjectLogDevice =
                    faster.checkpointManager.GetSnapshotObjectLogDevice(faster._hybridLogCheckpointToken);
                faster._hybridLogCheckpoint.snapshotFileDevice.Initialize(faster.hlog.GetSegmentSize());
                faster._hybridLogCheckpoint.snapshotFileObjectLogDevice.Initialize(-1);

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

                // We are writing pages outside epoch protection, so callee should be able to
                // handle corrupted or unexpected concurrent page changes during the flush, e.g., by
                // resuming epoch protection if necessary. Correctness is not affected as we will
                // only read safe pages during recovery.
                faster.hlog.AsyncFlushPagesToDevice(
                    startPage,
                    endPage,
                    faster._hybridLogCheckpoint.info.finalLogicalAddress,
                    faster._hybridLogCheckpoint.snapshotFileDevice,
                    faster._hybridLogCheckpoint.snapshotFileObjectLogDevice,
                    out faster._hybridLogCheckpoint.flushedSemaphore);
                break;

            case Phase.PERSISTENCE_CALLBACK:
                // update flushed-until address to the latest
                faster._hybridLogCheckpoint.info.flushedLogicalAddress = faster.hlog.FlushedUntilAddress;
                base.GlobalBeforeEnteringState(next, faster);
                faster._lastSnapshotCheckpoint = faster._hybridLogCheckpoint.Transfer();
                break;

            default:
                base.GlobalBeforeEnteringState(next, faster);
                break;
            }
        }