From 622680d058cf7811d3e6128d92fe998e3667b873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Hofman?= Date: Wed, 13 Sep 2023 10:34:28 +0200 Subject: [PATCH] SNOW-902611 Extract SessionPool to a separate file + naming conventions (#775) ### Description Extracted session pool to a separate file. Initial changes to apply naming conventions. ### Checklist - [x] Code compiles correctly - [x] Code is formatted according to [Coding Conventions](../CodingConventions.md) - [ ] Created tests which fail without the change (if possible) - [x] All tests passing (`dotnet test`) - [x] Extended the README / documentation, if necessary - [x] Provide JIRA issue id (if possible) or GitHub issue id in PR name --- .../Client/SnowflakeDbConnection.cs | 8 +- .../Client/SnowflakeDbConnectionPool.cs | 201 +----------------- Snowflake.Data/Core/Session/SessionPool.cs | 185 ++++++++++++++++ 3 files changed, 199 insertions(+), 195 deletions(-) create mode 100644 Snowflake.Data/Core/Session/SessionPool.cs diff --git a/Snowflake.Data/Client/SnowflakeDbConnection.cs b/Snowflake.Data/Client/SnowflakeDbConnection.cs index 38185ed26..615bcc879 100755 --- a/Snowflake.Data/Client/SnowflakeDbConnection.cs +++ b/Snowflake.Data/Client/SnowflakeDbConnection.cs @@ -153,7 +153,7 @@ public override void Close() { var transactionRollbackStatus = SnowflakeDbConnectionPool.GetPooling() ? TerminateTransactionForDirtyConnectionReturningToPool() : TransactionRollbackStatus.Undefined; - if (CanReuseSession(transactionRollbackStatus) && SnowflakeDbConnectionPool.addSession(SfSession)) + if (CanReuseSession(transactionRollbackStatus) && SnowflakeDbConnectionPool.AddSession(SfSession)) { logger.Debug($"Session pooled: {SfSession.sessionId}"); } @@ -191,7 +191,7 @@ public Task CloseAsync(CancellationToken cancellationToken) { var transactionRollbackStatus = SnowflakeDbConnectionPool.GetPooling() ? TerminateTransactionForDirtyConnectionReturningToPool() : TransactionRollbackStatus.Undefined; - if (CanReuseSession(transactionRollbackStatus) && SnowflakeDbConnectionPool.addSession(SfSession)) + if (CanReuseSession(transactionRollbackStatus) && SnowflakeDbConnectionPool.AddSession(SfSession)) { logger.Debug($"Session pooled: {SfSession.sessionId}"); _connectionState = ConnectionState.Closed; @@ -246,7 +246,7 @@ public override void Open() logger.Debug($"Open with a connection already opened: {_connectionState}"); return; } - SfSession = SnowflakeDbConnectionPool.getSession(this.ConnectionString); + SfSession = SnowflakeDbConnectionPool.GetSession(this.ConnectionString); if (SfSession != null) { logger.Debug($"Connection open with pooled session: {SfSession.sessionId}"); @@ -289,7 +289,7 @@ public override Task OpenAsync(CancellationToken cancellationToken) logger.Debug($"Open with a connection already opened: {_connectionState}"); return Task.CompletedTask; } - SfSession = SnowflakeDbConnectionPool.getSession(this.ConnectionString); + SfSession = SnowflakeDbConnectionPool.GetSession(this.ConnectionString); if (SfSession != null) { logger.Debug($"Connection open with pooled session: {SfSession.sessionId}"); diff --git a/Snowflake.Data/Client/SnowflakeDbConnectionPool.cs b/Snowflake.Data/Client/SnowflakeDbConnectionPool.cs index 4af48cb3b..8e0093262 100644 --- a/Snowflake.Data/Client/SnowflakeDbConnectionPool.cs +++ b/Snowflake.Data/Client/SnowflakeDbConnectionPool.cs @@ -1,209 +1,28 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Collections.Concurrent; -using System.Security; +using Snowflake.Data.Core; +using Snowflake.Data.Core.Session; using Snowflake.Data.Log; -using System.Linq; -using Snowflake.Data.Core; namespace Snowflake.Data.Client { - sealed class SessionPoolSingleton : IDisposable - { - private static SFLogger logger = SFLoggerFactory.GetLogger(); - private static SessionPoolSingleton instance = null; - private static readonly object _sessionPoolLock = new object(); - - private List sessionPool; - private int maxPoolSize; - private long timeout; - private int MAX_POOL_SIZE = 10; - private const long TIMEOUT = 3600; - private bool pooling = true; - - SessionPoolSingleton() - { - lock (_sessionPoolLock) - { - sessionPool = new List(); - maxPoolSize = MAX_POOL_SIZE; - timeout = TIMEOUT; - } - } - ~SessionPoolSingleton() - { - ClearAllPools(); - } - - public void Dispose() - { - ClearAllPools(); - } - - public static SessionPoolSingleton Instance - { - get - { - lock (_sessionPoolLock) - { - if(instance == null) - { - instance = new SessionPoolSingleton(); - } - return instance; - } - } - } - - private void cleanExpiredSessions() - { - logger.Debug("SessionPool::cleanExpiredSessions"); - lock (_sessionPoolLock) - { - long timeNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - - foreach (var item in sessionPool.ToList()) - { - if (item.IsExpired(timeout, timeNow)) - { - sessionPool.Remove(item); - item.close(); - } - } - } - } - - internal SFSession getSession(string connStr) - { - logger.Debug("SessionPool::getSession"); - if (!pooling) - return null; - lock (_sessionPoolLock) - { - for (int i = 0; i < sessionPool.Count; i++) - { - if (sessionPool[i].connStr.Equals(connStr)) - { - SFSession session = sessionPool[i]; - sessionPool.RemoveAt(i); - long timeNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - if (session.IsExpired(timeout, timeNow)) - { - session.close(); - i--; - } - else - { - logger.Debug($"reuse pooled session with sid {session.sessionId}"); - return session; - } - } - } - } - return null; - } - internal bool addSession(SFSession session) - { - logger.Debug("SessionPool::addSession"); - if (!pooling) - return false; - long timeNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); - if (session.IsNotOpen() || session.IsExpired(timeout, timeNow)) - return false; - - lock (_sessionPoolLock) - { - if (sessionPool.Count >= maxPoolSize) - { - cleanExpiredSessions(); - } - if (sessionPool.Count >= maxPoolSize) - { - // pool is full - return false; - } - - logger.Debug($"pool connection with sid {session.sessionId}"); - sessionPool.Add(session); - return true; - } - } - - internal void ClearAllPools() - { - logger.Debug("SessionPool::ClearAllPools"); - lock (_sessionPoolLock) - { - foreach (SFSession session in sessionPool) - { - session.close(); - } - sessionPool.Clear(); - } - } - - public void SetMaxPoolSize(int size) - { - maxPoolSize = size; - } - - public int GetMaxPoolSize() - { - return maxPoolSize; - } - - public void SetTimeout(long time) - { - timeout = time; - } - - public long GetTimeout() - { - return timeout; - } - - public int GetCurrentPoolSize() - { - return sessionPool.Count; - } - - public bool SetPooling(bool isEnable) - { - if (pooling == isEnable) - return false; - pooling = isEnable; - if (!pooling) - { - ClearAllPools(); - } - return true; - } - - public bool GetPooling() - { - return pooling; - } - } public class SnowflakeDbConnectionPool { - private static SFLogger logger = SFLoggerFactory.GetLogger(); + private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger(); - internal static SFSession getSession(string connStr) + internal static SFSession GetSession(string connStr) { - logger.Debug("SnowflakeDbConnectionPool::getSession"); - return SessionPoolSingleton.Instance.getSession(connStr); + s_logger.Debug("SnowflakeDbConnectionPool::GetSession"); + return SessionPoolSingleton.Instance.GetSession(connStr); } - internal static bool addSession(SFSession session) + internal static bool AddSession(SFSession session) { - logger.Debug("SnowflakeDbConnectionPool::addSession"); - return SessionPoolSingleton.Instance.addSession(session); + s_logger.Debug("SnowflakeDbConnectionPool::AddSession"); + return SessionPoolSingleton.Instance.AddSession(session); } public static void ClearAllPools() { - logger.Debug("SnowflakeDbConnectionPool::ClearAllPools"); + s_logger.Debug("SnowflakeDbConnectionPool::ClearAllPools"); SessionPoolSingleton.Instance.ClearAllPools(); } diff --git a/Snowflake.Data/Core/Session/SessionPool.cs b/Snowflake.Data/Core/Session/SessionPool.cs new file mode 100644 index 000000000..092135e47 --- /dev/null +++ b/Snowflake.Data/Core/Session/SessionPool.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Snowflake.Data.Log; + +namespace Snowflake.Data.Core.Session +{ + sealed class SessionPoolSingleton : IDisposable + { + private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger(); + private static SessionPoolSingleton s_instance = null; + private static readonly object s_sessionPoolLock = new object(); + + private readonly List _sessionPool; + private int _maxPoolSize; + private long _timeout; + private const int MaxPoolSize = 10; + private const long Timeout = 3600; + private bool _pooling = true; + + SessionPoolSingleton() + { + lock (s_sessionPoolLock) + { + _sessionPool = new List(); + _maxPoolSize = MaxPoolSize; + _timeout = Timeout; + } + } + ~SessionPoolSingleton() + { + ClearAllPools(); + } + + public void Dispose() + { + ClearAllPools(); + } + + public static SessionPoolSingleton Instance + { + get + { + lock (s_sessionPoolLock) + { + if(s_instance == null) + { + s_instance = new SessionPoolSingleton(); + } + return s_instance; + } + } + } + + private void CleanExpiredSessions() + { + s_logger.Debug("SessionPool::cleanExpiredSessions"); + lock (s_sessionPoolLock) + { + long timeNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + + foreach (var item in _sessionPool.ToList()) + { + if (item.IsExpired(_timeout, timeNow)) + { + _sessionPool.Remove(item); + item.close(); + } + } + } + } + + internal SFSession GetSession(string connStr) + { + s_logger.Debug("SessionPool::GetSession"); + if (!_pooling) + return null; + lock (s_sessionPoolLock) + { + for (int i = 0; i < _sessionPool.Count; i++) + { + if (_sessionPool[i].connStr.Equals(connStr)) + { + SFSession session = _sessionPool[i]; + _sessionPool.RemoveAt(i); + long timeNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + if (session.IsExpired(_timeout, timeNow)) + { + session.close(); + i--; + } + else + { + s_logger.Debug($"reuse pooled session with sid {session.sessionId}"); + return session; + } + } + } + } + return null; + } + internal bool AddSession(SFSession session) + { + s_logger.Debug("SessionPool::AddSession"); + if (!_pooling) + return false; + long timeNow = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + if (session.IsNotOpen() || session.IsExpired(_timeout, timeNow)) + return false; + + lock (s_sessionPoolLock) + { + if (_sessionPool.Count >= _maxPoolSize) + { + CleanExpiredSessions(); + } + if (_sessionPool.Count >= _maxPoolSize) + { + // pool is full + return false; + } + + s_logger.Debug($"pool connection with sid {session.sessionId}"); + _sessionPool.Add(session); + return true; + } + } + + internal void ClearAllPools() + { + s_logger.Debug("SessionPool::ClearAllPools"); + lock (s_sessionPoolLock) + { + foreach (SFSession session in _sessionPool) + { + session.close(); + } + _sessionPool.Clear(); + } + } + + public void SetMaxPoolSize(int size) + { + _maxPoolSize = size; + } + + public int GetMaxPoolSize() + { + return _maxPoolSize; + } + + public void SetTimeout(long time) + { + _timeout = time; + } + + public long GetTimeout() + { + return _timeout; + } + + public int GetCurrentPoolSize() + { + return _sessionPool.Count; + } + + public bool SetPooling(bool isEnable) + { + if (_pooling == isEnable) + return false; + _pooling = isEnable; + if (!_pooling) + { + ClearAllPools(); + } + return true; + } + + public bool GetPooling() + { + return _pooling; + } + } + +} \ No newline at end of file