Example #1
0
        /// <summary>
        /// Allocates a session from the pool if possible, or creates a new Spanner Session.
        /// </summary>
        /// <param name="spannerClient">The client to associate with the session. Must not be null.</param>
        /// <param name="project">The project of the session. Must not be null.</param>
        /// <param name="spannerInstance">The instance of the session. Must not be null.</param>
        /// <param name="spannerDatabase">The database of the session. Must not be null.</param>
        /// <param name="options">The transaction options for the session. Must not be null.</param>
        /// <param name="cancellationToken">A cancellation token for the asynchronous operation.</param>
        /// <returns>A task which, when completed, will return the session.</returns>
        public async Task <Session> CreateSessionFromPoolAsync(
            SpannerClient spannerClient,
            string project,
            string spannerInstance,
            string spannerDatabase,
            TransactionOptions options,
            CancellationToken cancellationToken)
        {
            GaxPreconditions.CheckNotNull(spannerClient, nameof(spannerClient));
            GaxPreconditions.CheckNotNull(project, nameof(project));
            GaxPreconditions.CheckNotNull(spannerInstance, nameof(spannerInstance));
            GaxPreconditions.CheckNotNull(spannerDatabase, nameof(spannerDatabase));
            GaxPreconditions.CheckNotNull(options, nameof(options));

            await StartSessionCreatingAsync(cancellationToken).ConfigureAwait(false);

            Session        sessionResult  = null;
            SessionPoolKey sessionPoolKey = default;

            try
            {
                sessionPoolKey = new SessionPoolKey(spannerClient, project, spannerInstance, spannerDatabase);
                SessionPoolImpl targetPool = _poolByClientAndDatabase.GetOrAdd(sessionPoolKey, key => new SessionPoolImpl(key, Options));

                sessionResult = await targetPool.AcquireSessionAsync(options, cancellationToken).ConfigureAwait(false);

                // Refresh the MRU list which tells us what sessions need to be trimmed from the pool when we want
                // to add another poolEntry.
                return(sessionResult);
            }
            finally
            {
                EndSessionCreating(sessionResult, sessionPoolKey);
            }
        }
Example #2
0
 private static void ReSortMru(SessionPoolImpl targetPool)
 {
     lock (s_priorityListSync)
     {
         if (s_priorityList.Count > 1)
         {
             s_priorityList.Remove(targetPool);
             s_priorityList.Add(targetPool, targetPool);
         }
     }
 }
Example #3
0
        // Only present for testing.
        internal int GetPoolSize(SpannerClient spannerClient, string project, string spannerInstance, string spannerDatabase)
        {
            GaxPreconditions.CheckNotNull(spannerClient, nameof(spannerClient));
            GaxPreconditions.CheckNotNull(project, nameof(project));
            GaxPreconditions.CheckNotNull(spannerInstance, nameof(spannerInstance));
            GaxPreconditions.CheckNotNull(spannerDatabase, nameof(spannerDatabase));
            var             sessionPoolKey = new SessionPoolKey(spannerClient, project, spannerInstance, spannerDatabase);
            SessionPoolImpl targetPool     = _poolByClientAndDatabase.GetOrAdd(sessionPoolKey, key => new SessionPoolImpl(key, Options));

            return(targetPool.GetPoolSize());
        }
Example #4
0
        /// <summary>
        /// Releases a session back into the pool, possibly causing another entry to be evicted if the maximum pool size has been
        /// reached.
        /// </summary>
        /// <param name="session"></param>
        /// <param name="client"></param>
        /// <returns></returns>
        public static void ReleaseToPool(this SpannerClient client, Session session)
        {
            session.ThrowIfNull(nameof(session));

            SessionPoolKey poolKey;

            if (s_sessionsInUse.TryRemove(session, out poolKey))
            {
                LogSessionsInUse();
                SignalAnyWaitingRequests();
                if (IsSessionExpired(session))
                {
                    bool unused;
                    s_blackListedSessions.TryRemove(session.Name, out unused);
                    return;
                }
                SessionPoolImpl targetPool = s_poolByClientAndDatabase.GetOrAdd(poolKey,
                                                                                key => new SessionPoolImpl(key));


                SpannerClient evictionClient  = poolKey.Client;
                Session       evictionSession = null;

                //Figure out if we want to pool this released session.
                lock (s_priorityListSync)
                {
                    targetPool.ReleaseSessionToPool(client, session);
                    if (CurrentPooledSessions > MaximumPooledSessions)
                    {
                        var evictionPool = s_priorityList.First().Value;
                        evictionClient  = evictionPool.Key.Client;
                        evictionSession = evictionPool.AcquireEvictionCandidate();
                        ReSortMru(evictionPool);
                    }
                    ReSortMru(targetPool);
                }
                if (evictionSession != null)
                {
                    Task.Run(() => EvictSessionAsync(evictionClient, evictionSession));
                }
            }
            else
            {
                Logger.Error(
                    () =>
                    "An attempt was made to release a session to the pool,"
                    + " but the session was not originally allocated from the pool.");
            }
        }
Example #5
0
        internal int GetPoolSize(
            SpannerClient spannerClient,
            string project,
            string spannerInstance,
            string spannerDatabase)
        {
            project.ThrowIfNullOrEmpty(nameof(project));
            spannerInstance.ThrowIfNullOrEmpty(nameof(spannerInstance));
            spannerDatabase.ThrowIfNullOrEmpty(nameof(spannerDatabase));
            var sessionPoolKey = new SessionPoolKey(spannerClient,
                                                    project,
                                                    spannerInstance,
                                                    spannerDatabase);
            SessionPoolImpl targetPool = _poolByClientAndDatabase.GetOrAdd(sessionPoolKey,
                                                                           key => new SessionPoolImpl(key, Options));

            return(targetPool.GetPoolSize());
        }
Example #6
0
        /// <summary>
        /// Allocates a session from the pool if possible, or creates a new Spanner Session.
        /// </summary>
        /// <param name="spannerClient"></param>
        /// <param name="project"></param>
        /// <param name="spannerInstance"></param>
        /// <param name="spannerDatabase"></param>
        /// <param name="options"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task <Session> CreateSessionFromPoolAsync(
            this SpannerClient spannerClient,
            string project,
            string spannerInstance,
            string spannerDatabase,
            TransactionOptions options,
            CancellationToken cancellationToken)
        {
            project.ThrowIfNullOrEmpty(nameof(project));
            spannerInstance.ThrowIfNullOrEmpty(nameof(spannerInstance));
            spannerDatabase.ThrowIfNullOrEmpty(nameof(spannerDatabase));

            await StartSessionCreatingAsync(cancellationToken).ConfigureAwait(false);

            Session        sessionResult  = null;
            SessionPoolKey sessionPoolKey = default(SessionPoolKey);

            try
            {
                sessionPoolKey = new SessionPoolKey(spannerClient,
                                                    project,
                                                    spannerInstance,
                                                    spannerDatabase);
                SessionPoolImpl targetPool = s_poolByClientAndDatabase.GetOrAdd(sessionPoolKey,
                                                                                key => new SessionPoolImpl(key));

                sessionResult = await targetPool.AcquireSessionAsync(options, cancellationToken).ConfigureAwait(false);

                //refresh the mru list which tells us what sessions need to be trimmed from the pool when we want
                // to add another poolEntry.
                ReSortMru(targetPool);
                return(sessionResult);
            } finally
            {
                EndSessionCreating(sessionResult, sessionPoolKey);
            }
        }