Пример #1
0
 public Session AcquireEvictionCandidate()
 {
     try
     {
         SessionPoolEntry sessionEntry = default;
         lock (_sessionMruStack)
         {
             if (_sessionMruStack.Count > 0)
             {
                 sessionEntry = _sessionMruStack[_sessionMruStack.Count - 1];
                 _sessionMruStack.RemoveAt(_sessionMruStack.Count - 1);
                 Interlocked.Decrement(ref s_activeSessionsPooled);
                 LogSessionsPooled();
             }
         }
         if (sessionEntry.Session == null || sessionEntry.EvictTaskCancellationSource == null)
         {
             return(null);
         }
         sessionEntry.EvictTaskCancellationSource.Cancel();
         return(sessionEntry.Session);
     }
     finally
     {
         OnPriorityChanged();
     }
 }
Пример #2
0
        private async Task EvictImmediatelyAsync(Session session, CancellationToken cancellationToken)
        {
            Logger.Debug(() => "Evicting a session from the pool.");
            SessionPoolEntry entry = default;

            try
            {
                lock (_sessionMruStack)
                {
                    var found = _sessionMruStack.FindIndex(x => ReferenceEquals(x.Session, session));
                    if (found != -1)
                    {
                        entry = _sessionMruStack[found];
                        _sessionMruStack.RemoveAt(found);
                        Interlocked.Decrement(ref s_activeSessionsPooled);
                        LogSessionsPooled();
                    }
                }
            }
            finally
            {
                OnPriorityChanged();
            }
            if (entry.Session != null)
            {
                await Key.Client.DeleteSessionAsync(entry.Session.GetSessionName(), cancellationToken).ConfigureAwait(false);
            }
        }
Пример #3
0
 private void Push(SessionPoolEntry entry)
 {
     lock (_sessionMruStack)
     {
         _sessionMruStack.Insert(0, entry);
         Interlocked.Increment(ref s_activeSessionsPooled);
         LogSessionsPooled();
     }
 }
Пример #4
0
        private bool TryPop(TransactionOptions transactionOptions, out SessionPoolEntry entry)
        {
            try
            {
                //we make a reasonable attempt at obtaining a session with the given TransactionOptions.
                //but its not guaranteed.
                lock (_sessionMruStack)
                {
                    if (_sessionMruStack.Count > 0)
                    {
                        Logger.Debug(() => "Searching for a session with matching transaction semantics.");
                        int indexToUse = -1;
                        for (int i = 0; i < _sessionMruStack.Count && i < MaximumLinearSearchDepth; i++)
                        {
                            entry = _sessionMruStack[i];
                            // GetLastUsedTransactionOptions returns null if the transaction pool doesn't know about the session.
                            // Our transactionOptions parameter is never null, but may be the default options. It's fine to treat
                            // those as equivalent; they'd never be used for a "real" transaction.
                            var lastUsedOptions = TransactionPool.GetLastUsedTransactionOptions(entry.Session) ?? s_defaultTransactionOptions;
                            if (Equals(lastUsedOptions, transactionOptions))
                            {
                                Logger.Debug(() => "found a session with matching transaction semantics.");
                                indexToUse = i;
                                if (transactionOptions?.ModeCase != TransactionOptions.ModeOneofCase.ReadWrite ||
                                    TransactionPool.IsPreWarmedTransactionReady(entry.Session))
                                {
                                    //if our prewarmed tx is ready, we can jump out immediately.
                                    break;
                                }
                            }
                        }
                        if (indexToUse == -1)
                        {
                            Logger.Debug(
                                () => "did not find a session with matching transaction semantics - popping at top.");
                            indexToUse = 0;
                        }
                        entry = _sessionMruStack[indexToUse];
                        _sessionMruStack.RemoveAt(indexToUse);

                        Interlocked.Decrement(ref s_activeSessionsPooled);
                        LogSessionsPooled();
                        return(true);
                    }
                }
                entry = default;
                return(false);
            }
            finally
            {
                OnPriorityChanged();
            }
        }
Пример #5
0
        private bool TryPop(TransactionOptions transactionOptions, out SessionPoolEntry entry)
        {
            try
            {
                //we make a reasonable attempt at obtaining a session with the given TransactionOptions.
                //but its not guaranteed.
                lock (_sessionMruStack)
                {
                    if (_sessionMruStack.Count > 0)
                    {
                        Logger.Debug(() => "Searching for a session with matching transaction semantics.");
                        int indexToUse = -1;
                        for (int i = 0;
                             i < _sessionMruStack.Count && i < MaximumLinearSearchDepth;
                             i++)
                        {
                            entry = _sessionMruStack[i];
                            if (Equals(entry.Session.GetLastUsedTransactionOptions(), transactionOptions))
                            {
                                Logger.Debug(() => "found a session with matching transaction semantics.");
                                indexToUse = i;
                                if (transactionOptions?.ModeCase != TransactionOptions.ModeOneofCase.ReadWrite ||
                                    entry.Session.IsPreWarmedTransactionReady())
                                {
                                    //if our prewarmed tx is ready, we can jump out immediately.
                                    break;
                                }
                            }
                        }
                        if (indexToUse == -1)
                        {
                            Logger.Debug(
                                () => "did not find a session with matching transaction semantics - popping at top.");
                            indexToUse = 0;
                        }
                        entry = _sessionMruStack[indexToUse];
                        _sessionMruStack.RemoveAt(indexToUse);

                        Interlocked.Decrement(ref s_activeSessionsPooled);
                        LogSessionsPooled();
                        return(true);
                    }
                }
                entry = default;
                return(false);
            }
            finally
            {
                OnPriorityChanged();
            }
        }
Пример #6
0
        public void ReleaseSessionToPool(SpannerClient client, Session session)
        {
            Logger.Debug(() => "Placing session back into the pool and starting the evict timer.");
            //start evict timer.
            SessionPoolEntry entry = new SessionPoolEntry(session, new CancellationTokenSource());

            if (SessionPool.UseTransactionWarming)
            {
                Task.Run(() => client.PreWarmTransactionAsync(entry.Session));
            }
            Push(entry);
            //kick off the pool eviction timer.  This gets canceled when the item is pulled from the pool.
            Task.Run(() => EvictSessionPoolEntry(entry.Session, entry.EvictTaskCancellationSource.Token),
                     entry.EvictTaskCancellationSource.Token);
        }
Пример #7
0
 private void Push(SessionPoolEntry entry)
 {
     try
     {
         lock (_sessionMruStack)
         {
             _sessionMruStack.Insert(0, entry);
             Interlocked.Increment(ref s_activeSessionsPooled);
             LogSessionsPooled();
         }
     }
     finally
     {
         OnPriorityChanged();
     }
 }
Пример #8
0
        public void ReleaseSessionToPool(SpannerClient client, Session session)
        {
            Logger.Debug(() => "Placing session back into the pool and starting the evict timer.");
            //start evict timer.
            SessionPoolEntry entry = new SessionPoolEntry(session, new CancellationTokenSource());

            if (_options.UseTransactionWarming)
            {
                client.StartPreWarmTransaction(entry.Session);
            }
            //kick off the pool eviction timer.  This gets canceled when the item is pulled from the pool.
            Task.Run(() => EvictSessionPoolEntry(entry.Session, entry.EvictTaskCancellationSource.Token),
                     entry.EvictTaskCancellationSource.Token);

            //It's very important that before we allow the new session to be in the pool
            //that the state of the session is such that it can be immediately consumed.
            Push(entry);
        }
Пример #9
0
        private async Task EvictImmediatelyAsync(Session session, CancellationToken cancellationToken)
        {
            Logger.Debug(() => "Evicting a session from the pool.");
            SessionPoolEntry entry = default;

            try
            {
                lock (_sessionMruStack)
                {
                    var found = _sessionMruStack.FindIndex(x => ReferenceEquals(x.Session, session));
                    if (found != -1)
                    {
                        entry = _sessionMruStack[found];
                        _sessionMruStack.RemoveAt(found);
                        Interlocked.Decrement(ref s_activeSessionsPooled);
                        LogSessionsPooled();
                    }
                }
            }
            finally
            {
                OnPriorityChanged();
            }
            if (entry.Session != null)
            {
                try
                {
                    await Key.Client.DeleteSessionAsync(entry.Session.GetSessionName(), cancellationToken)
                    .ConfigureAwait(false);
                }
                catch (ObjectDisposedException)
                {
                    Logger.Info(() => "Unable to delete a pooled session because it was already disposed.");
                }
                catch (Exception e)
                {
                    //The session delete is best effort, but we will log an error if needed
                    //Note that this error can happen if a test deletes it's database and a later test clears
                    //out the session pool.
                    Logger.Error(() => "Unable to delete a pooled session.", e);
                }
            }
        }