Skip to content

Commit

Permalink
SNOW-937188 introduction of full API for new pool
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-mhofman committed Apr 29, 2024
1 parent 0429a48 commit f74bc2c
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 25 deletions.
30 changes: 15 additions & 15 deletions Snowflake.Data/Client/SnowflakeDbConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ public class SnowflakeDbConnection : DbConnection
{
private SFLogger logger = SFLoggerFactory.GetLogger<SnowflakeDbConnection>();

internal SFSession SfSession { get; set; }
internal SFSession SfSession { get; set; }

internal ConnectionState _connectionState;

protected override DbProviderFactory DbProviderFactory => new SnowflakeDbFactory();

internal int _connectionTimeout;

private bool _disposed = false;
Expand All @@ -47,7 +47,7 @@ protected enum TransactionRollbackStatus
public SnowflakeDbConnection()
{
_connectionState = ConnectionState.Closed;
_connectionTimeout =
_connectionTimeout =
int.Parse(SFSessionProperty.CONNECTION_TIMEOUT.GetAttribute<SFSessionPropertyAttr>().
defaultValue);
_isArrayBindStageCreated = false;
Expand Down Expand Up @@ -84,12 +84,12 @@ private bool IsNonClosedWithSession()
public override int ConnectionTimeout => this._connectionTimeout;

/// <summary>
/// If the connection to the database is closed, the DataSource returns whatever is contained
/// in the ConnectionString for the DataSource keyword. If the connection is open and the
/// ConnectionString data source keyword's value starts with "|datadirectory|", the property
/// returns whatever is contained in the ConnectionString for the DataSource keyword only. If
/// the connection to the database is open, the property returns what the native provider
/// returns for the DBPROP_INIT_DATASOURCE, and if that is empty, the native provider's
/// If the connection to the database is closed, the DataSource returns whatever is contained
/// in the ConnectionString for the DataSource keyword. If the connection is open and the
/// ConnectionString data source keyword's value starts with "|datadirectory|", the property
/// returns whatever is contained in the ConnectionString for the DataSource keyword only. If
/// the connection to the database is open, the property returns what the native provider
/// returns for the DBPROP_INIT_DATASOURCE, and if that is empty, the native provider's
/// DBPROP_DATASOURCENAME is returned.
/// Note: not yet implemented
/// </summary>
Expand All @@ -115,7 +115,7 @@ public void PreventPooling()
SfSession.SetPooling(false);
logger.Debug($"Session {SfSession.sessionId} marked not to be pooled any more");
}

internal bool HasActiveExplicitTransaction() => ExplicitTransaction != null && ExplicitTransaction.IsActive;

private bool TryToReturnSessionToPool()
Expand Down Expand Up @@ -150,12 +150,12 @@ private TransactionRollbackStatus TerminateTransactionForDirtyConnectionReturnin
// error to indicate a problem within application code that a connection was closed while still having a pending transaction
logger.Error("Closing dirty connection: rollback transaction in session " + SfSession.sessionId + " succeeded.");
ExplicitTransaction = null;
return TransactionRollbackStatus.Success;
return TransactionRollbackStatus.Success;
}
}
catch (Exception exception)
{
// error to indicate a problem with rollback of an active transaction and inability to return dirty connection to the pool
// error to indicate a problem with rollback of an active transaction and inability to return dirty connection to the pool
logger.Error("Closing dirty connection: rollback transaction in session: " + SfSession.sessionId + " failed, exception: " + exception.Message);
return TransactionRollbackStatus.Failure; // connection won't be pooled
}
Expand Down Expand Up @@ -254,10 +254,10 @@ await SfSession.CloseAsync(cancellationToken).ContinueWith(

protected virtual bool CanReuseSession(TransactionRollbackStatus transactionRollbackStatus)
{
return SnowflakeDbConnectionPool.GetPooling() &&
return SnowflakeDbConnectionPool.GetPooling() &&
transactionRollbackStatus == TransactionRollbackStatus.Success;
}

public override void Open()
{
logger.Debug("Open Connection.");
Expand Down Expand Up @@ -401,7 +401,7 @@ protected override void Dispose(bool disposing)
SfSession = null;
_connectionState = ConnectionState.Closed;
}

_disposed = true;
}

Expand Down
16 changes: 14 additions & 2 deletions Snowflake.Data/Client/SnowflakeDbSessionPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,24 @@ internal SnowflakeDbSessionPool(SessionPool sessionPool)
public void SetMaxPoolSize(int size) => _sessionPool.SetMaxPoolSize(size);
public int GetMaxPoolSize() => _sessionPool.GetMaxPoolSize();

public void SetTimeout(long seconds) => _sessionPool.SetTimeout(seconds);
public long GetTimeout() => _sessionPool.GetTimeout();
public void SetMinPoolSize(int size) => _sessionPool.SetMinPoolSize(size);
public int GetMinPoolSize() => _sessionPool.GetMinPoolSize();

public void SetExpirationTimeout(long seconds) => _sessionPool.SetTimeout(seconds);
public long GetExpirationTimeout() => _sessionPool.GetTimeout();

public void SetConnectionTimeout(long seconds) => _sessionPool.SetTimeout(seconds);
public long GetConnectionTimeout() => _sessionPool.GetTimeout();

public int GetCurrentPoolSize() => _sessionPool.GetCurrentPoolSize();

public bool SetPooling(bool isEnable) => _sessionPool.SetPooling(isEnable);
public bool GetPooling() => _sessionPool.GetPooling();

public void SetChangedSession(ChangedSessionBehavior newChangedSession) => _sessionPool.SetChangedSession(newChangedSession);
public ChangedSessionBehavior GetChangedSession() => _sessionPool.GetChangedSession();

public void SetWaitForIdleSessionTimeout(double seconds) => _sessionPool.SetWaitForIdleSessionTimeout(seconds);
public double GetWaitForIdleSessionTimeout() => _sessionPool.GetWaitForIdleSessionTimeout();
}
}
6 changes: 3 additions & 3 deletions Snowflake.Data/Core/Session/ChangedSessionBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace Snowflake.Data.Core.Session
{
/**
* It describes what should happen to a session with a changed state (e. g. schema/role/etc.) when it is being returned to the pool.
* ChangedSessionBehavior describes what should happen to a session with a changed state (schema/role/database/warehouse) when it is being returned to the pool.
*/
internal enum ChangedSessionBehavior
public enum ChangedSessionBehavior
{
OriginalPool,
ChangePool,
Expand All @@ -24,7 +24,7 @@ public static List<string> StringValues()
.Select(b => b.ToString())
.ToList();
}

public static ChangedSessionBehavior From(string changedSession)
{
return (ChangedSessionBehavior) Enum.Parse(typeof(ChangedSessionBehavior), changedSession, true);
Expand Down
4 changes: 3 additions & 1 deletion Snowflake.Data/Core/Session/ConnectionPoolManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ public SessionPool GetPool(string connectionString, SecureString password)
public SessionPool GetPool(string connectionString)
{
s_logger.Debug($"ConnectionPoolManager::GetPool");
if (!connectionString.ToLower().Contains("password="))
// unless it is an external browser then those two must be passed along
var connStr = $";{connectionString.ToLower()};";
if (!connStr.Contains(";password=") && connStr.Contains(";user="))
{
s_logger.Error($"To obtain a pool a password must to be given with a connection string or SecureString parameter");
throw new SnowflakeDbException(SFError.MISSING_CONNECTION_PROPERTY, "Could not provide the pool without the password");
Expand Down
51 changes: 47 additions & 4 deletions Snowflake.Data/Core/Session/SessionPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -521,15 +521,58 @@ internal async void ClearAllPoolsAsync()
}
}

public void SetMaxPoolSize(int size)
public void SetMaxPoolSize(int newMaxPoolSize)
{
_poolConfig.MaxPoolSize = size;
s_logger.Info($"SessionPool::SetMaxPoolSize({newMaxPoolSize})");
_poolConfig.MaxPoolSize = newMaxPoolSize;
_configOverriden = true;
}

public int GetMaxPoolSize()
public int GetMaxPoolSize() => _poolConfig.MaxPoolSize;

public void SetMinPoolSize(int newMinPoolSize)
{
s_logger.Info($"SessionPool::SetMinPoolSize({newMinPoolSize})");
_poolConfig.MinPoolSize = newMinPoolSize;
_configOverriden = true;
}

public int GetMinPoolSize() => _poolConfig.MinPoolSize;

public ChangedSessionBehavior GetChangedSession() => _poolConfig.ChangedSession;

public void SetChangedSession(ChangedSessionBehavior newChangedSession)
{
if (IsMultiplePoolsVersion())
{
s_logger.Info($"SessionPool::SetChangedSession({newChangedSession})");
_poolConfig.ChangedSession = newChangedSession;
_configOverriden = true;
}
}

public double GetWaitForIdleSessionTimeout() => _poolConfig.WaitingForIdleSessionTimeout.TotalSeconds;

public void SetWaitForIdleSessionTimeout(double waitForIdleSession)
{
if (IsMultiplePoolsVersion())
{
s_logger.Info($"SessionPool::SetWaitForIdleSessionTimeout({waitForIdleSession})");
_poolConfig.WaitingForIdleSessionTimeout = TimeSpan.FromSeconds(waitForIdleSession);
_configOverriden = true;
}
}

public void SetConnectionTimeout(long seconds)
{
var timeout = seconds < 0 ? TimeoutHelper.Infinity() : TimeSpan.FromSeconds(seconds);
_poolConfig.ConnectionTimeout = timeout;
_configOverriden = true;
}

public long GetConnectionTimeout()
{
return _poolConfig.MaxPoolSize;
return TimeoutHelper.IsInfinite(_poolConfig.ConnectionTimeout) ? -1 : (long)_poolConfig.ConnectionTimeout.TotalSeconds;
}

public void SetTimeout(long seconds)
Expand Down

0 comments on commit f74bc2c

Please sign in to comment.