Пример #1
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)
            {
                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");
                }
            }

            this.inputVariableLengthStruct = sessionVariableLengthStructSettings?.inputLength;

            // Session runs on a single thread
            if (!supportAsync)
            {
                UnsafeResumeThread();
            }
        }
Пример #2
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();
            }
        }
Пример #3
0
            /// <summary>
            /// Resume (continue) prior client session with FASTER, used during
            /// recovery from failure.
            /// </summary>
            /// <param name="sessionName">Name of previous session to resume</param>
            /// <param name="commitPoint">Prior commit point of durability for session</param>
            /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
            /// <param name="readFlags">ReadFlags for this session; override those specified at FasterKV level, and may be overridden on individual Read operations</param>
            /// <returns>Session instance</returns>
            public ClientSession <Key, Value, Input, Output, Context, Functions> ResumeSession <Functions>(string sessionName, out CommitPoint commitPoint,
                                                                                                           SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null, ReadFlags readFlags = ReadFlags.Default)
                where Functions : IFunctions <Key, Value, Input, Output, Context>
            {
                if (_functions == null)
                {
                    throw new FasterException("Functions not provided for session");
                }

                return(_fasterKV.ResumeSession <Input, Output, Context, Functions>((Functions)_functions, sessionName, out commitPoint, sessionVariableLengthStructSettings, readFlags));
            }
Пример #4
0
 /// <summary>
 /// Compact the log until specified address, moving active records to the tail of the log. BeginAddress is shifted, but the physical log
 /// is not deleted from disk. Caller is responsible for truncating the physical log on disk by taking a checkpoint or calling Log.Truncate
 /// </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="input">Input for SingleWriter</param>
 /// <param name="output">Output from SingleWriter; it will be called all records that are moved, before Compact() returns, so the user must supply buffering or process each output completely</param>
 /// <param name="untilAddress">Compact log until this address</param>
 /// <param name="compactionType">Compaction type (whether we lookup records or scan log for liveness checking)</param>
 /// <param name="sessionVariableLengthStructSettings">Session variable length struct settings</param>
 /// <returns>Address until which compaction was done</returns>
 internal long Compact <Input, Output, Context, Functions, CompactionFunctions>(Functions functions, CompactionFunctions cf, ref Input input, ref Output output, long untilAddress, CompactionType compactionType, SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
     where Functions : IFunctions <Key, Value, Input, Output, Context>
     where CompactionFunctions : ICompactionFunctions <Key, Value>
 {
     return(compactionType switch
     {
         CompactionType.Scan => CompactScan <Input, Output, Context, Functions, CompactionFunctions>(functions, cf, ref input, ref output, untilAddress, sessionVariableLengthStructSettings),
         CompactionType.Lookup => CompactLookup <Input, Output, Context, Functions, CompactionFunctions>(functions, cf, ref input, ref output, untilAddress, sessionVariableLengthStructSettings),
         _ => throw new FasterException("Invalid compaction type"),
     });
Пример #5
0
            /// <summary>
            /// Resume (continue) prior client session with FASTER, used during
            /// recovery from failure.
            /// </summary>
            /// <param name="sessionId">ID/name of previous session to resume</param>
            /// <param name="commitPoint">Prior commit point of durability for session</param>
            /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
            ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
            /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
            /// <returns>Session instance</returns>
            public ClientSession <Key, Value, Input, Output, Context, Functions> ResumeSession <Functions>(string sessionId, out CommitPoint commitPoint, bool threadAffinitized = false,
                                                                                                           SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
                where Functions : IFunctions <Key, Value, Input, Output, Context>
            {
                if (_functions == null)
                {
                    throw new FasterException("Functions not provided for session");
                }

                return(_fasterKV.ResumeSession <Input, Output, Context, Functions>((Functions)_functions, sessionId, out commitPoint, threadAffinitized, sessionVariableLengthStructSettings));
            }
Пример #6
0
 /// <summary>
 /// Resume (continue) prior client session with FASTER; used during recovery from failure.
 /// </summary>
 /// <param name="functions">Callback functions</param>
 /// <param name="sessionName">Name of previous session to resume</param>
 /// <param name="commitPoint">Prior commit point of durability for session</param>
 /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
 /// <param name="readFlags">ReadFlags for this session; override those specified at FasterKV level, and may be overridden on individual Read operations</param>
 /// <returns>Session instance</returns>
 public ClientSession <Key, Value, Input, Output, Context, Functions> ResumeSession <Functions>(Functions functions, string sessionName, out CommitPoint commitPoint,
                                                                                                SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null, ReadFlags readFlags = ReadFlags.Default)
     where Functions : IFunctions <Key, Value, Input, Output, Context>
 {
     return(_fasterKV.ResumeSession <Input, Output, Context, Functions>(functions, sessionName, out commitPoint, sessionVariableLengthStructSettings, readFlags));
 }
Пример #7
0
        /// <summary>
        /// Resume (continue) prior client session with FASTER using advanced functions; used during recovery from failure.
        /// </summary>
        /// <param name="functions">Callback functions</param>
        /// <param name="sessionId">ID/name of previous session to resume</param>
        /// <param name="commitPoint">Prior commit point of durability for session</param>
        /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
        ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
        /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
        /// <returns>Session instance</returns>

        internal AdvancedClientSession <Key, Value, Input, Output, Context, Functions> ResumeAdvancedSession <Input, Output, Context, Functions>(Functions functions, string sessionId, out CommitPoint commitPoint,
                                                                                                                                                 bool threadAffinitized = false, SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
            where Functions : IAdvancedFunctions <Key, Value, Input, Output, Context>
        {
            return(InternalResumeSession <Input, Output, Context, Functions, AdvancedClientSession <Key, Value, Input, Output, Context, Functions> >(functions, sessionId, out commitPoint, threadAffinitized,
                                                                                                                                                     ctx => new AdvancedClientSession <Key, Value, Input, Output, Context, Functions>(this, ctx, functions, !threadAffinitized, sessionVariableLengthStructSettings)));
        }
Пример #8
0
 /// <summary>
 /// Resume (continue) prior client session with FASTER; used during recovery from failure.
 /// </summary>
 /// <param name="functions">Callback functions</param>
 /// <param name="sessionId">ID/name of previous session to resume</param>
 /// <param name="commitPoint">Prior commit point of durability for session</param>
 /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
 ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
 /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
 /// <returns>Session instance</returns>
 public ClientSession <Key, Value, Input, Output, Context, Functions> ResumeSession <Functions>(Functions functions, string sessionId, out CommitPoint commitPoint, bool threadAffinitized = false,
                                                                                                SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings     = null)
     where Functions : IFunctions <Key, Value, Input, Output, Context>
 {
     return(_fasterKV.ResumeSession <Input, Output, Context, Functions>(functions, sessionId, out commitPoint, threadAffinitized, sessionVariableLengthStructSettings));
 }
Пример #9
0
 /// <summary>
 /// Start a new advanced client session with FASTER.
 /// </summary>
 /// <param name="functions">Callback functions</param>
 /// <param name="sessionId">ID/name of session (auto-generated if not provided)</param>
 /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
 ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
 /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
 /// <returns>Session instance</returns>
 internal AdvancedClientSession <Key, Value, Input, Output, Context, Functions> NewAdvancedSession <Input, Output, Context, Functions>(Functions functions, string sessionId = null, bool threadAffinitized = false,
                                                                                                                                       SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
     where Functions : IAdvancedFunctions <Key, Value, Input, Output, Context>
 => InternalNewSession <Input, Output, Context, Functions, AdvancedClientSession <Key, Value, Input, Output, Context, Functions> >(functions, sessionId, threadAffinitized,
                                                                                                                                   ctx => new AdvancedClientSession <Key, Value, Input, Output, Context, Functions>(this, ctx, functions, !threadAffinitized, sessionVariableLengthStructSettings));
Пример #10
0
 /// <summary>
 /// Resume (continue) prior client session with FASTER using advanced functions; used during recovery from failure.
 /// For performance reasons this overload is not recommended if functions is value type (struct).
 /// </summary>
 /// <param name="functions">Callback functions</param>
 /// <param name="sessionId">ID/name of previous session to resume</param>
 /// <param name="commitPoint">Prior commit point of durability for session</param>
 /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
 ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
 /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
 /// <returns>Session instance</returns>
 public AdvancedClientSession <Key, Value, Input, Output, Context, IAdvancedFunctions <Key, Value, Input, Output, Context> > ResumeSession <Input, Output, Context>(IAdvancedFunctions <Key, Value, Input, Output, Context> functions,
                                                                                                                                                                    string sessionId, out CommitPoint commitPoint, bool threadAffinitized = false, SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
 {
     return(ResumeAdvancedSession <Input, Output, Context, IAdvancedFunctions <Key, Value, Input, Output, Context> >(functions, sessionId, out commitPoint, threadAffinitized, sessionVariableLengthStructSettings));
 }
Пример #11
0
 /// <summary>
 /// Start a new advanced client session with FASTER.
 /// For performance reasons, please use FasterKV&lt;Key, Value&gt;.For(functions).NewSession&lt;Functions&gt;(...) instead of this overload.
 /// </summary>
 /// <param name="functions">Callback functions</param>
 /// <param name="sessionId">ID/name of session (auto-generated if not provided)</param>
 /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
 ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
 /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
 /// <returns>Session instance</returns>
 public AdvancedClientSession <Key, Value, Input, Output, Context, IAdvancedFunctions <Key, Value, Input, Output, Context> > NewSession <Input, Output, Context>(IAdvancedFunctions <Key, Value, Input, Output, Context> functions,
                                                                                                                                                                 string sessionId = null, bool threadAffinitized = false, SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
 {
     return(NewAdvancedSession <Input, Output, Context, IAdvancedFunctions <Key, Value, Input, Output, Context> >(functions, sessionId, threadAffinitized, sessionVariableLengthStructSettings));
 }
Пример #12
0
            /// <summary>
            /// Start a new advanced client session with FASTER.
            /// </summary>
            /// <param name="sessionId">ID/name of session (auto-generated if not provided)</param>
            /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
            ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
            /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
            /// <returns>Session instance</returns>
            public AdvancedClientSession <Key, Value, Input, Output, Context, Functions> NewSession <Functions>(string sessionId = null, bool threadAffinitized = false,
                                                                                                                SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
                where Functions : IAdvancedFunctions <Key, Value, Input, Output, Context>
            {
                if (_functions == null)
                {
                    throw new FasterException("Functions not provided for session");
                }

                return(_fasterKV.NewAdvancedSession <Input, Output, Context, Functions>((Functions)_functions, sessionId, threadAffinitized, sessionVariableLengthStructSettings));
            }
Пример #13
0
 /// <summary>
 /// Start a new advanced client session with FASTER.
 /// </summary>
 /// <param name="functions">Callback functions</param>
 /// <param name="sessionId">ID/name of session (auto-generated if not provided)</param>
 /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code.
 ///     Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
 /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
 /// <returns>Session instance</returns>
 public AdvancedClientSession <Key, Value, Input, Output, Context, Functions> NewSession <Functions>(Functions functions, string sessionId = null, bool threadAffinitized = false,
                                                                                                     SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
     where Functions : IAdvancedFunctions <Key, Value, Input, Output, Context>
 {
     return(_fasterKV.NewAdvancedSession <Input, Output, Context, Functions>(functions, sessionId, threadAffinitized, sessionVariableLengthStructSettings));
 }
Пример #14
0
        /// <summary>
        /// Resume (continue) prior client session with FASTER, used during
        /// recovery from failure.
        /// </summary>
        /// <param name="functions">Callback functions</param>
        /// <param name="sessionId">ID/name of previous session to resume</param>
        /// <param name="commitPoint">Prior commit point of durability for session</param>
        /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code. Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
        /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
        /// <returns>Session instance</returns>

        public ClientSession <Key, Value, Input, Output, Context, Functions> ResumeSession <Input, Output, Context, Functions>(Functions functions, string sessionId, out CommitPoint commitPoint, bool threadAffinitized = false, SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            if (functions == null)
            {
                throw new ArgumentNullException(nameof(functions));
            }

            if (!threadAffinitized)
            {
                UseRelaxedCPR();
            }

            commitPoint = InternalContinue <Input, Output, Context>(sessionId, out var ctx);
            if (commitPoint.UntilSerialNo == -1)
            {
                throw new Exception($"Unable to find session {sessionId} to recover");
            }


            var session = new ClientSession <Key, Value, Input, Output, Context, Functions>(this, ctx, functions, !threadAffinitized, sessionVariableLengthStructSettings);

            if (_activeSessions == null)
            {
                Interlocked.CompareExchange(ref _activeSessions, new Dictionary <string, IClientSession>(), null);
            }
            lock (_activeSessions)
                _activeSessions.Add(sessionId, session);
            return(session);
        }
Пример #15
0
        /// <summary>
        /// Start a new client session with FASTER.
        /// </summary>
        /// <param name="functions">Callback functions</param>
        /// <param name="sessionId">ID/name of session (auto-generated if not provided)</param>
        /// <param name="threadAffinitized">For advanced users. Specifies whether session holds the thread epoch across calls. Do not use with async code. Ensure thread calls session Refresh periodically to move the system epoch forward.</param>
        /// <param name="sessionVariableLengthStructSettings">Session-specific variable-length struct settings</param>
        /// <returns>Session instance</returns>
        public ClientSession <Key, Value, Input, Output, Context, Functions> NewSession <Input, Output, Context, Functions>(Functions functions, string sessionId = null, bool threadAffinitized = false, SessionVariableLengthStructSettings <Value, Input> sessionVariableLengthStructSettings = null)
            where Functions : IFunctions <Key, Value, Input, Output, Context>
        {
            if (functions == null)
            {
                throw new ArgumentNullException(nameof(functions));
            }

            if (!threadAffinitized)
            {
                UseRelaxedCPR();
            }

            if (sessionId == null)
            {
                sessionId = Guid.NewGuid().ToString();
            }
            var ctx = new FasterExecutionContext <Input, Output, Context>();

            InitContext(ctx, sessionId);
            var prevCtx = new FasterExecutionContext <Input, Output, Context>();

            InitContext(prevCtx, sessionId);
            prevCtx.version--;

            ctx.prevCtx = prevCtx;

            if (_activeSessions == null)
            {
                Interlocked.CompareExchange(ref _activeSessions, new Dictionary <string, IClientSession>(), null);
            }

            var session = new ClientSession <Key, Value, Input, Output, Context, Functions>(this, ctx, functions, !threadAffinitized, sessionVariableLengthStructSettings);

            lock (_activeSessions)
                _activeSessions.Add(sessionId, session);
            return(session);
        }