EnsureNotOnNetworkThread() static private method

Throws if the current thread is the Network Thread.
Should be used to ensure that we do not execute tasks continuations from the network thread, to avoid dead-locks.
static private EnsureNotOnNetworkThread ( [ callerMethod = null ) : void
callerMethod [
return void
Esempio n. 1
0
        /// <summary>Set an option on this cluster that does not take any parameter</summary>
        /// <param name="option">Option to set</param>
        public void SetOption(FdbClusterOption option)
        {
            ThrowIfDisposed();

            Fdb.EnsureNotOnNetworkThread();

            if (Logging.On && Logging.IsVerbose)
            {
                Logging.Verbose(this, "SetOption", $"Setting cluster option {option.ToString()}");
            }

            m_handler.SetOption(option, Slice.Nil);
        }
Esempio n. 2
0
        /// <summary>Set an option on this cluster that takes an integer value</summary>
        /// <param name="option">Option to set</param>
        /// <param name="value">Value of the parameter</param>
        public void SetOption(FdbClusterOption option, long value)
        {
            ThrowIfDisposed();

            Fdb.EnsureNotOnNetworkThread();

            if (Logging.On && Logging.IsVerbose)
            {
                Logging.Verbose(this, "SetOption", $"Setting cluster option {option.ToString()} to {value}");
            }

            var data = Slice.FromFixed64(value);

            m_handler.SetOption(option, data);
        }
Esempio n. 3
0
        /// <summary>Set an option on this cluster that takes a string value</summary>
        /// <param name="option">Option to set</param>
        /// <param name="value">Value of the parameter (can be null)</param>
        public void SetOption(FdbClusterOption option, string value)
        {
            ThrowIfDisposed();

            Fdb.EnsureNotOnNetworkThread();

            if (Logging.On && Logging.IsVerbose)
            {
                Logging.Verbose(this, "SetOption", $"Setting cluster option {option.ToString()} to '{value ?? "<null>"}'");
            }

            var data = FdbNative.ToNativeString(value, nullTerminated: true);

            m_handler.SetOption(option, data);
        }
        /// <summary>Throws if the transaction is not in a valid state (for reading/writing) and that we can proceed with a read or write operation</summary>
        /// <param name="allowFromNetworkThread">If true, this operation is allowed to run from a callback on the network thread and should NEVER block.</param>
        /// <param name="allowFailedState">If true, this operation can run even if the transaction is in a failed state.</param>
        /// <exception cref="System.ObjectDisposedException">If Dispose as already been called on the transaction</exception>
        /// <exception cref="System.InvalidOperationException">If CommitAsync() or Rollback() have already been called on the transaction, or if the database has been closed</exception>
        internal void EnsureStilValid(bool allowFromNetworkThread = false, bool allowFailedState = false)
        {
            // We must not be disposed
            if (allowFailedState ? this.State == STATE_DISPOSED : this.State != STATE_READY)
            {
                ThrowOnInvalidState(this);
            }

            // The cancellation token should not be signaled
            m_cancellation.ThrowIfCancellationRequested();

            // We cannot be called from the network thread (or else we will deadlock)
            if (!allowFromNetworkThread)
            {
                Fdb.EnsureNotOnNetworkThread();
            }

            // Ensure that the DB is still opened and that this transaction is still registered with it
            this.Database.EnsureTransactionIsValid(this);

            // we are ready to go !
        }
Esempio n. 5
0
        /// <summary>Stops the thread running the FDB event loop</summary>
        private static void StopEventLoop()
        {
            if (s_eventLoopStarted)
            {
                // We cannot be called from the network thread itself, or else we will dead lock !
                Fdb.EnsureNotOnNetworkThread();

                if (Logging.On)
                {
                    Logging.Verbose(typeof(Fdb), "StopEventLoop", "Stopping network thread...");
                }

                s_eventLoopStopRequested = true;

                var err = FdbNative.StopNetwork();
                if (err != FdbError.Success)
                {
                    if (Logging.On)
                    {
                        Logging.Warning(typeof(Fdb), "StopEventLoop", $"Failed to stop event loop: {err.ToString()}");
                    }
                }
                s_eventLoopStarted = false;

                var thread = s_eventLoop;
                if (thread != null && thread.IsAlive)
                {
                    // BUGBUG: specs says that we need to wait for the network thread to stop gracefuly, or else data integrity may not be guaranteed...
                    // We should wait for a bit, and only attempt to Abort() the thread after a timeout (30sec ? more ?)

                    // keep track of how much time it took to stop...
                    var duration = Stopwatch.StartNew();

                    try
                    {
                        //TODO: replace with a ManualResetEvent that would get signaled at the end of the event loop ?
                        while (thread.IsAlive && duration.Elapsed.TotalSeconds < 5)
                        {
                            // wait a bit...
                            Thread.Sleep(250);
                        }

                        if (thread.IsAlive)
                        {
                            if (Logging.On)
                            {
                                Logging.Warning(typeof(Fdb), "StopEventLoop", $"The fdb network thread has not stopped after {duration.Elapsed.TotalSeconds:N0} seconds. Forcing shutdown...");
                            }

                            // Force a shutdown
                            thread.Abort();

                            bool stopped = thread.Join(TimeSpan.FromSeconds(30));
                            //REVIEW: is this even usefull? If the thread is stuck in a native P/Invoke call, it won't get notified until it returns to managed code ...
                            // => in that case, we have a zombie thread on our hands...

                            if (!stopped)
                            {
                                if (Logging.On)
                                {
                                    Logging.Warning(typeof(Fdb), "StopEventLoop", $"The fdb network thread failed to stop after more than {duration.Elapsed.TotalSeconds:N0} seconds. Transaction integrity may not be guaranteed.");
                                }
                            }
                        }
                    }
                    catch (ThreadAbortException)
                    {
                        // Should not happen, unless we are called from a thread that is itself being stopped ?
                    }
                    finally
                    {
                        s_eventLoop = null;
                        duration.Stop();
                        if (duration.Elapsed.TotalSeconds >= 20)
                        {
                            if (Logging.On)
                            {
                                Logging.Warning(typeof(Fdb), "StopEventLoop", $"The fdb network thread took a long time to stop ({duration.Elapsed.TotalSeconds:N0} seconds).");
                            }
                        }
                    }
                }
            }
        }