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(); } }
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); } }
private void Push(SessionPoolEntry entry) { lock (_sessionMruStack) { _sessionMruStack.Insert(0, entry); Interlocked.Increment(ref s_activeSessionsPooled); LogSessionsPooled(); } }
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(); } }
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(); } }
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); }
private void Push(SessionPoolEntry entry) { try { lock (_sessionMruStack) { _sessionMruStack.Insert(0, entry); Interlocked.Increment(ref s_activeSessionsPooled); LogSessionsPooled(); } } finally { OnPriorityChanged(); } }
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); }
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); } } }