Skip to content

Commit 098bd5b

Browse files
committed
Merge master into ssl.
Conflicts: .ci/config/config.compression+ssl.json .ci/config/config.compression.json .ci/config/config.json .ci/config/config.ssl.json azure-pipelines.yml src/MySqlConnector/Core/ConnectionPool.cs src/MySqlConnector/Core/ServerSession.cs src/MySqlConnector/Logging/Log.cs src/MySqlConnector/MySqlConnection.cs src/MySqlConnector/Protocol/Payloads/OkPayload.cs tests/IntegrationTests/RedirectionTests.cs tests/IntegrationTests/ServerFeatures.cs Signed-off-by: Bradley Grainger <[email protected]>
2 parents 89beadf + 6e45dcd commit 098bd5b

File tree

12 files changed

+156
-124
lines changed

12 files changed

+156
-124
lines changed

.ci/config/config.compression+ssl.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"SocketPath": "./../../../../.ci/run/mysql/mysqld.sock",
55
"PasswordlessUser": "no_password",
66
"SecondaryDatabase": "testdb2",
7-
"UnsupportedFeatures": "RsaEncryption,CachingSha2Password,Tls12,Tls13,UuidToBin,TlsFingerprintValidation",
7+
"UnsupportedFeatures": "CachingSha2Password,Redirection,RsaEncryption,Tls12,Tls13,TlsFingerprintValidation,UuidToBin",
88
"MySqlBulkLoaderLocalCsvFile": "../../../TestData/LoadData_UTF8_BOM_Unix.CSV",
99
"MySqlBulkLoaderLocalTsvFile": "../../../TestData/LoadData_UTF8_BOM_Unix.TSV",
1010
"CertificatesPath": "../../../../.ci/server/certs"

.ci/config/config.compression.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"SocketPath": "./../../../../.ci/run/mysql/mysqld.sock",
55
"PasswordlessUser": "no_password",
66
"SecondaryDatabase": "testdb2",
7-
"UnsupportedFeatures": "Ed25519,QueryAttributes,StreamingResults,Tls11,UnixDomainSocket,ZeroDateTime,TlsFingerprintValidation",
7+
"UnsupportedFeatures": "Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket,ZeroDateTime",
88
"MySqlBulkLoaderLocalCsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.CSV",
99
"MySqlBulkLoaderLocalTsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.TSV"
1010
}

.ci/config/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"SocketPath": "./../../../../.ci/run/mysql/mysqld.sock",
55
"PasswordlessUser": "no_password",
66
"SecondaryDatabase": "testdb2",
7-
"UnsupportedFeatures": "Ed25519,QueryAttributes,StreamingResults,Tls11,UnixDomainSocket,ZeroDateTime,TlsFingerprintValidation",
7+
"UnsupportedFeatures": "Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,UnixDomainSocket,ZeroDateTime",
88
"MySqlBulkLoaderLocalCsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.CSV",
99
"MySqlBulkLoaderLocalTsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.TSV"
1010
}

.ci/config/config.ssl.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"SocketPath": "./../../../../.ci/run/mysql/mysqld.sock",
55
"PasswordlessUser": "no_password",
66
"SecondaryDatabase": "testdb2",
7-
"UnsupportedFeatures": "RsaEncryption,CachingSha2Password,Tls12,Tls13,UuidToBin,TlsFingerprintValidation",
7+
"UnsupportedFeatures": "CachingSha2Password,Redirection,RsaEncryption,Tls12,Tls13,TlsFingerprintValidation,UuidToBin",
88
"MySqlBulkLoaderLocalCsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.CSV",
99
"MySqlBulkLoaderLocalTsvFile": "../../../../tests/TestData/LoadData_UTF8_BOM_Unix.TSV",
1010
"CertificatesPath": "../../../../.ci/server/certs"

azure-pipelines.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ jobs:
136136
arguments: '-c Release --no-restore'
137137
testRunTitle: ${{ format('{0}, $(Agent.OS), {1}, {2}', 'mysql:8.0', 'net472/net8.0', 'No SSL') }}
138138
env:
139-
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,StreamingResults,Tls11,UnixDomainSocket'
139+
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,UnixDomainSocket'
140140
DATA__CONNECTIONSTRING: 'server=localhost;port=3306;user id=mysqltest;password=test;database=mysqltest;ssl mode=none;DefaultCommandTimeout=3600;AllowPublicKeyRetrieval=True;UseCompression=True'
141141

142142
- job: windows_integration_tests_2
@@ -174,7 +174,7 @@ jobs:
174174
arguments: '-c Release --no-restore'
175175
testRunTitle: ${{ format('{0}, $(Agent.OS), {1}, {2}', 'mysql:8.0', 'net6.0', 'No SSL') }}
176176
env:
177-
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,StreamingResults,Tls11,UnixDomainSocket'
177+
DATA__UNSUPPORTEDFEATURES: 'Ed25519,QueryAttributes,Redirection,StreamingResults,Tls11,UnixDomainSocket'
178178
DATA__CONNECTIONSTRING: 'server=localhost;port=3306;user id=mysqltest;password=test;database=mysqltest;ssl mode=none;DefaultCommandTimeout=3600;AllowPublicKeyRetrieval=True'
179179

180180
- job: linux_integration_tests
@@ -187,23 +187,23 @@ jobs:
187187
'MySQL 8.0':
188188
image: 'mysql:8.0'
189189
connectionStringExtra: 'AllowPublicKeyRetrieval=True'
190-
unsupportedFeatures: 'Ed25519,StreamingResults,Tls11,ZeroDateTime,Redirection,TlsFingerprintValidation'
190+
unsupportedFeatures: 'Ed25519,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
191191
'MySQL 8.4':
192192
image: 'mysql:8.4'
193193
connectionStringExtra: 'AllowPublicKeyRetrieval=True'
194-
unsupportedFeatures: 'Ed25519,StreamingResults,Tls11,ZeroDateTime,Redirection,TlsFingerprintValidation'
194+
unsupportedFeatures: 'Ed25519,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
195195
'MySQL 9.0':
196196
image: 'mysql:9.0'
197197
connectionStringExtra: 'AllowPublicKeyRetrieval=True'
198-
unsupportedFeatures: 'Ed25519,StreamingResults,Tls11,ZeroDateTime,Redirection,TlsFingerprintValidation'
198+
unsupportedFeatures: 'Ed25519,Redirection,StreamingResults,Tls11,TlsFingerprintValidation,ZeroDateTime'
199199
'MariaDB 10.6':
200200
image: 'mariadb:10.6'
201201
connectionStringExtra: ''
202-
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,Sha256Password,Tls11,UuidToBin,Redirection,TlsFingerprintValidation'
202+
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,Redirection,Sha256Password,Tls11,TlsFingerprintValidation,UuidToBin'
203203
'MariaDB 10.11':
204204
image: 'mariadb:10.11'
205205
connectionStringExtra: ''
206-
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,Sha256Password,Tls11,UuidToBin,Redirection,TlsFingerprintValidation'
206+
unsupportedFeatures: 'CachingSha2Password,CancelSleepSuccessfully,Json,RoundDateTime,QueryAttributes,Redirection,Sha256Password,Tls11,TlsFingerprintValidation,UuidToBin'
207207
'MariaDB 11.4':
208208
image: 'mariadb:11.4'
209209
connectionStringExtra: ''

src/MySqlConnector/Core/ConnectionPool.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,16 @@
88

99
namespace MySqlConnector.Core;
1010

11-
internal sealed class ConnectionPool : IDisposable
11+
internal sealed class ConnectionPool : IConnectionPoolMetadata, IDisposable
1212
{
1313
public int Id { get; }
1414

15+
ConnectionPool? IConnectionPoolMetadata.ConnectionPool => this;
16+
17+
int IConnectionPoolMetadata.Generation => m_generation;
18+
19+
int IConnectionPoolMetadata.GetNewSessionId() => Interlocked.Increment(ref m_lastSessionId);
20+
1521
public string? Name { get; }
1622

1723
public ConnectionSettings ConnectionSettings { get; }
@@ -111,11 +117,8 @@ public async ValueTask<ServerSession> GetSessionAsync(MySqlConnection connection
111117
}
112118

113119
// create a new session
114-
session = await ServerSession.ConnectAndRedirectAsync(
115-
() => new ServerSession(m_connectionLogger, this, m_generation,
116-
Interlocked.Increment(ref m_lastSessionId)), m_logger, Id, ConnectionSettings, m_loadBalancer,
117-
connection, s_createdNewSession, startingTimestamp, activity, ioBehavior, cancellationToken)
118-
.ConfigureAwait(false);
120+
session = await ServerSession.ConnectAndRedirectAsync(m_connectionLogger, m_logger, this, ConnectionSettings, m_loadBalancer,
121+
connection, s_createdNewSession, startingTimestamp, activity, ioBehavior, cancellationToken).ConfigureAwait(false);
119122
AdjustHostConnectionCount(session, 1);
120123
session.OwningConnection = new(connection);
121124
int leasedSessionsCountNew;
@@ -411,11 +414,8 @@ private async Task CreateMinimumPooledSessions(MySqlConnection connection, IOBeh
411414

412415
try
413416
{
414-
var session = await ServerSession.ConnectAndRedirectAsync(
415-
() => new ServerSession(m_connectionLogger, this, m_generation,
416-
Interlocked.Increment(ref m_lastSessionId)), m_logger, Id, ConnectionSettings, m_loadBalancer,
417-
connection, s_createdToReachMinimumPoolSize, Stopwatch.GetTimestamp(), null, ioBehavior,
418-
cancellationToken).ConfigureAwait(false);
417+
var session = await ServerSession.ConnectAndRedirectAsync(m_connectionLogger, m_logger, this, ConnectionSettings, m_loadBalancer,
418+
connection, s_createdToReachMinimumPoolSize, Stopwatch.GetTimestamp(), null, ioBehavior, cancellationToken).ConfigureAwait(false);
419419
AdjustHostConnectionCount(session, 1);
420420
lock (m_sessions)
421421
_ = m_sessions.AddFirst(session);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace MySqlConnector.Core;
2+
3+
internal interface IConnectionPoolMetadata
4+
{
5+
/// <summary>
6+
/// Returns the <see cref="ConnectionPool"/> this <see cref="IConnectionPoolMetadata"/> is associated with,
7+
/// or <c>null</c> if it represents a non-pooled connection.
8+
/// </summary>
9+
ConnectionPool? ConnectionPool { get; }
10+
11+
/// <summary>
12+
/// Returns the ID of the connection pool, or 0 if this is a non-pooled connection.
13+
/// </summary>
14+
int Id { get; }
15+
16+
/// <summary>
17+
/// Returns the generation of the connection pool, or 0 if this is a non-pooled connection.
18+
/// </summary>
19+
int Generation { get; }
20+
21+
/// <summary>
22+
/// Returns a new session ID.
23+
/// </summary>
24+
/// <returns>A new session ID.</returns>
25+
int GetNewSessionId();
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace MySqlConnector.Core;
2+
3+
internal sealed class NonPooledConnectionPoolMetadata : IConnectionPoolMetadata
4+
{
5+
public static IConnectionPoolMetadata Instance { get; } = new NonPooledConnectionPoolMetadata();
6+
7+
public ConnectionPool? ConnectionPool => null;
8+
public int Id => 0;
9+
public int Generation => 0;
10+
public int GetNewSessionId() => Interlocked.Increment(ref m_lastId);
11+
12+
private int m_lastId;
13+
}

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,16 @@ namespace MySqlConnector.Core;
2828

2929
internal sealed partial class ServerSession : IServerCapabilities
3030
{
31-
public ServerSession(ILogger logger)
32-
: this(logger, null, 0, Interlocked.Increment(ref s_lastId))
33-
{
34-
}
35-
36-
public ServerSession(ILogger logger, ConnectionPool? pool, int poolGeneration, int id)
31+
public ServerSession(ILogger logger, IConnectionPoolMetadata pool)
3732
{
3833
m_logger = logger;
3934
m_lock = new();
4035
m_payloadCache = new();
41-
Id = (pool?.Id ?? 0) + "." + id;
36+
Id = pool.Id + "." + pool.GetNewSessionId();
4237
ServerVersion = ServerVersion.Empty;
4338
CreatedTimestamp = Stopwatch.GetTimestamp();
44-
Pool = pool;
45-
PoolGeneration = poolGeneration;
39+
Pool = pool.ConnectionPool;
40+
PoolGeneration = pool.Generation;
4641
HostName = "";
4742
m_activityTags = [];
4843
DataReader = new();
@@ -665,10 +660,11 @@ private bool ValidateFingerPrint(byte[]? validationHash, ReadOnlySpan<byte> chal
665660
return string.Equals(clientGeneratedHash, serverGeneratedHash, StringComparison.Ordinal);
666661
}
667662

668-
public static async ValueTask<ServerSession> ConnectAndRedirectAsync(Func<ServerSession> createSession, ILogger logger, int? poolId, ConnectionSettings cs, ILoadBalancer? loadBalancer, MySqlConnection connection, Action<ILogger, int, string, Exception?>? logMessage, long startingTimestamp, Activity? activity, IOBehavior ioBehavior, CancellationToken cancellationToken)
663+
public static async ValueTask<ServerSession> ConnectAndRedirectAsync(ILogger connectionLogger, ILogger poolLogger, IConnectionPoolMetadata pool, ConnectionSettings cs, ILoadBalancer? loadBalancer, MySqlConnection connection, Action<ILogger, int, string, Exception?>? logMessage, long startingTimestamp, Activity? activity, IOBehavior ioBehavior, CancellationToken cancellationToken)
669664
{
670-
var session = createSession();
671-
if (poolId is not null && logger.IsEnabled(LogLevel.Debug)) logMessage!(logger, poolId.Value, session.Id, null);
665+
var session = new ServerSession(connectionLogger, pool);
666+
if (logMessage is not null && poolLogger.IsEnabled(LogLevel.Debug))
667+
logMessage(poolLogger, pool.Id, session.Id, null);
672668

673669
string? redirectionUrl;
674670
try
@@ -684,10 +680,10 @@ public static async ValueTask<ServerSession> ConnectAndRedirectAsync(Func<Server
684680
Exception? redirectionException = null;
685681
if (redirectionUrl is not null)
686682
{
687-
Log.HasServerRedirectionHeader(logger, session.Id, redirectionUrl);
683+
Log.HasServerRedirectionHeader(connectionLogger, session.Id, redirectionUrl);
688684
if (cs.ServerRedirectionMode == MySqlServerRedirectionMode.Disabled)
689685
{
690-
Log.ServerRedirectionIsDisabled(logger, session.Id);
686+
Log.ServerRedirectionIsDisabled(connectionLogger, session.Id);
691687
return session;
692688
}
693689

@@ -696,19 +692,19 @@ public static async ValueTask<ServerSession> ConnectAndRedirectAsync(Func<Server
696692
if (host != cs.HostNames![0] || port != cs.Port || user != cs.UserID)
697693
{
698694
var redirectedSettings = cs.CloneWith(host, port, user);
699-
Log.OpeningNewConnection(logger, host, port, user);
700-
var redirectedSession = createSession();
695+
Log.OpeningNewConnection(connectionLogger, session.Id, host, port, user);
696+
var redirectedSession = new ServerSession(connectionLogger, pool);
701697
try
702698
{
703699
await redirectedSession.ConnectAsync(redirectedSettings, connection, startingTimestamp, loadBalancer, activity, ioBehavior, cancellationToken).ConfigureAwait(false);
704-
Log.ClosingSessionToUseRedirectedSession(logger, session.Id, redirectedSession.Id);
700+
Log.ClosingSessionToUseRedirectedSession(connectionLogger, session.Id, redirectedSession.Id);
705701
await session.DisposeAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
706702
return redirectedSession;
707703
}
708704
catch (Exception ex)
709705
{
710706
redirectionException = ex;
711-
Log.FailedToConnectRedirectedSession(logger, ex, redirectedSession.Id);
707+
Log.FailedToConnectRedirectedSession(connectionLogger, ex, session.Id, redirectedSession.Id);
712708
try
713709
{
714710
await redirectedSession.DisposeAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
@@ -720,14 +716,14 @@ public static async ValueTask<ServerSession> ConnectAndRedirectAsync(Func<Server
720716
}
721717
else
722718
{
723-
Log.SessionAlreadyConnectedToServer(logger, session.Id);
719+
Log.SessionAlreadyConnectedToServer(connectionLogger, session.Id);
724720
}
725721
}
726722
}
727723

728724
if (cs.ServerRedirectionMode == MySqlServerRedirectionMode.Required)
729725
{
730-
Log.RequiresServerRedirection(logger, session.Id);
726+
Log.RequiresServerRedirection(connectionLogger, session.Id);
731727
throw new MySqlException(MySqlErrorCode.UnableToConnectToHost, "Server does not support redirection", redirectionException);
732728
}
733729
return session;
@@ -2099,7 +2095,6 @@ protected override void OnStatementBegin(int index)
20992095
private static readonly PayloadData s_sleepWithAttributesPayload = QueryPayload.Create(true, "SELECT SLEEP(0) INTO @\uE001MySqlConnector\uE001Sleep;"u8);
21002096
private static readonly PayloadData s_selectConnectionIdVersionNoAttributesPayload = QueryPayload.Create(false, "SELECT CONNECTION_ID(), VERSION();"u8);
21012097
private static readonly PayloadData s_selectConnectionIdVersionWithAttributesPayload = QueryPayload.Create(true, "SELECT CONNECTION_ID(), VERSION();"u8);
2102-
private static int s_lastId;
21032098

21042099
private readonly ILogger m_logger;
21052100
private readonly object m_lock;

src/MySqlConnector/Logging/Log.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -405,23 +405,23 @@ internal static partial class Log
405405
[LoggerMessage(EventIds.HasServerRedirectionHeader, LogLevel.Trace, "Session {SessionId} has server redirection header {Header}")]
406406
public static partial void HasServerRedirectionHeader(ILogger logger, string sessionId, string header);
407407

408-
[LoggerMessage(EventIds.ServerRedirectionIsDisabled, LogLevel.Trace, "Session {SessionId}, server redirection is disabled; ignoring redirection")]
408+
[LoggerMessage(EventIds.ServerRedirectionIsDisabled, LogLevel.Trace, "Session {SessionId} server redirection is disabled; ignoring redirection")]
409409
public static partial void ServerRedirectionIsDisabled(ILogger logger, string sessionId);
410410

411-
[LoggerMessage(EventIds.OpeningNewConnection, LogLevel.Debug, "opening new connection to {Host}:{Port} as {User}")]
412-
public static partial void OpeningNewConnection(ILogger logger, string host, int port, string user);
411+
[LoggerMessage(EventIds.OpeningNewConnection, LogLevel.Debug, "Session {SessionId} opening new connection to {Host}:{Port} as {User}")]
412+
public static partial void OpeningNewConnection(ILogger logger, string sessionId, string host, int port, string user);
413413

414-
[LoggerMessage(EventIds.FailedToConnectRedirectedSession, LogLevel.Information, "failed to connect redirected session {SessionId}")]
415-
public static partial void FailedToConnectRedirectedSession(ILogger logger, Exception ex, string sessionId);
414+
[LoggerMessage(EventIds.FailedToConnectRedirectedSession, LogLevel.Information, "Session {SessionId} failed to connect redirected session {RedirectedSessionId}")]
415+
public static partial void FailedToConnectRedirectedSession(ILogger logger, Exception ex, string sessionId, string redirectedSessionId);
416416

417-
[LoggerMessage(EventIds.ClosingSessionToUseRedirectedSession, LogLevel.Trace, "closing session {SessionId} to use redirected session {RedirectedSessionId} instead")]
417+
[LoggerMessage(EventIds.ClosingSessionToUseRedirectedSession, LogLevel.Trace, "Closing session {SessionId} to use redirected session {RedirectedSessionId} instead")]
418418
public static partial void ClosingSessionToUseRedirectedSession(ILogger logger, string sessionId, string redirectedSessionId);
419419

420420
[LoggerMessage(EventIds.SessionAlreadyConnectedToServer, LogLevel.Trace, "Session {SessionId} is already connected to this server; ignoring redirection")]
421421
public static partial void SessionAlreadyConnectedToServer(ILogger logger, string sessionId);
422422

423-
[LoggerMessage(EventIds.RequiresServerRedirection, LogLevel.Error, "Session {SessionId}, new connection requires server redirection but server doesn't support it")]
424-
public static partial void RequiresServerRedirection(ILogger logger, string SessionId);
423+
[LoggerMessage(EventIds.RequiresServerRedirection, LogLevel.Error, "Session {SessionId} requires server redirection but server doesn't support it")]
424+
public static partial void RequiresServerRedirection(ILogger logger, string sessionId);
425425

426426
[LoggerMessage(EventIds.CreatedPoolWillNotBeUsed, LogLevel.Debug, "Pool {PoolId} was created but will not be used (due to race)")]
427427
public static partial void CreatedPoolWillNotBeUsed(ILogger logger, int poolId);

0 commit comments

Comments
 (0)