@@ -106,7 +106,7 @@ public sealed partial class NpgsqlConnector : IDisposable
106106 /// </summary>
107107 public NpgsqlDatabaseInfo DatabaseInfo { get ; internal set ; } = default ! ;
108108
109- internal ConnectorTypeMapper TypeMapper { get ; set ; } = default ! ;
109+ internal TypeMapper TypeMapper { get ; set ; } = default ! ;
110110
111111 /// <summary>
112112 /// The current transaction status for this connector.
@@ -161,11 +161,6 @@ public sealed partial class NpgsqlConnector : IDisposable
161161 /// </summary>
162162 volatile Exception ? _breakReason ;
163163
164- /// <summary>
165- /// Semaphore, used to synchronize DatabaseInfo between multiple connections, so it wouldn't be loaded in parallel.
166- /// </summary>
167- static readonly SemaphoreSlim DatabaseInfoSemaphore = new ( 1 ) ;
168-
169164 /// <summary>
170165 /// <para>
171166 /// Used by the pool to indicate that I/O is currently in progress on this connector, so that another write
@@ -228,9 +223,9 @@ internal void FlagAsWritableForMultiplexing()
228223 /// Note that in multi-host scenarios, this references the host-specific <see cref="PoolingDataSource"/> rather than the
229224 /// <see cref="NpgsqlMultiHostDataSource"/>.
230225 /// </summary>
231- readonly NpgsqlDataSource _dataSource ;
226+ internal NpgsqlDataSource DataSource { get ; }
232227
233- internal string UserFacingConnectionString => _dataSource . ConnectionString ;
228+ internal string UserFacingConnectionString => DataSource . ConnectionString ;
234229
235230 /// <summary>
236231 /// Contains the UTC timestamp when this connector was opened, used to implement
@@ -315,7 +310,7 @@ internal NpgsqlConnector(NpgsqlDataSource dataSource, NpgsqlConnection conn)
315310 }
316311
317312 NpgsqlConnector ( NpgsqlConnector connector )
318- : this ( connector . _dataSource )
313+ : this ( connector . DataSource )
319314 {
320315 ProvideClientCertificatesCallback = connector . ProvideClientCertificatesCallback ;
321316 UserCertificateValidationCallback = connector . UserCertificateValidationCallback ;
@@ -326,7 +321,7 @@ internal NpgsqlConnector(NpgsqlDataSource dataSource, NpgsqlConnection conn)
326321 {
327322 Debug . Assert ( dataSource . OwnsConnectors ) ;
328323
329- _dataSource = dataSource ;
324+ DataSource = dataSource ;
330325
331326 LoggingConfiguration = dataSource . LoggingConfiguration ;
332327 ConnectionLogger = LoggingConfiguration . ConnectionLogger ;
@@ -464,7 +459,12 @@ internal async Task Open(NpgsqlTimeout timeout, bool async, CancellationToken ca
464459 {
465460 await OpenCore ( this , Settings . SslMode , timeout , async, cancellationToken ) ;
466461
467- await LoadDatabaseInfo ( forceReload : false , timeout , async, cancellationToken ) ;
462+ await DataSource . Bootstrap ( this , timeout , forceReload : false , async, cancellationToken ) ;
463+
464+ Debug . Assert ( DataSource . TypeMapper is not null ) ;
465+ Debug . Assert ( DataSource . DatabaseInfo is not null ) ;
466+ TypeMapper = DataSource . TypeMapper ;
467+ DatabaseInfo = DataSource . DatabaseInfo ;
468468
469469 if ( Settings . Pooling && ! Settings . Multiplexing && ! Settings . NoResetOnClose && DatabaseInfo . SupportsDiscard )
470470 {
@@ -500,18 +500,18 @@ internal async Task Open(NpgsqlTimeout timeout, bool async, CancellationToken ca
500500 }
501501 }
502502
503- if ( _dataSource . ConnectionInitializerAsync is not null )
503+ if ( DataSource . ConnectionInitializerAsync is not null )
504504 {
505- Debug . Assert ( _dataSource . ConnectionInitializer is not null ) ;
505+ Debug . Assert ( DataSource . ConnectionInitializer is not null ) ;
506506
507- var tempConnection = new NpgsqlConnection ( _dataSource , this ) ;
507+ var tempConnection = new NpgsqlConnection ( DataSource , this ) ;
508508
509509 try
510510 {
511511 if ( async)
512- await _dataSource . ConnectionInitializerAsync ( tempConnection ) ;
512+ await DataSource . ConnectionInitializerAsync ( tempConnection ) ;
513513 else if ( ! async )
514- _dataSource . ConnectionInitializer ( tempConnection ) ;
514+ DataSource . ConnectionInitializer ( tempConnection ) ;
515515 }
516516 finally
517517 {
@@ -595,47 +595,6 @@ await OpenCore(
595595 }
596596 }
597597
598- internal async ValueTask LoadDatabaseInfo ( bool forceReload , NpgsqlTimeout timeout , bool async ,
599- CancellationToken cancellationToken = default )
600- {
601- // The type loading below will need to send queries to the database, and that depends on a type mapper being set up (even if its
602- // empty). So we set up here, and then later inject the DatabaseInfo.
603- // For multiplexing connectors, the type mapper is the shared pool-wide one (since when validating/binding parameters on
604- // multiplexing there's no connector yet). However, in the very first multiplexing connection (bootstrap phase) we create
605- // a connector-specific mapper, which will later become shared pool-wide one.
606- TypeMapper =
607- Settings . Multiplexing && ( ( MultiplexingDataSource ) _dataSource ) . MultiplexingTypeMapper is { } multiplexingTypeMapper
608- ? multiplexingTypeMapper
609- : new ConnectorTypeMapper ( this ) ;
610-
611- var key = new NpgsqlDatabaseInfoCacheKey ( Settings ) ;
612- if ( forceReload || ! NpgsqlDatabaseInfo . Cache . TryGetValue ( key , out var database ) )
613- {
614- var hasSemaphore = async
615- ? await DatabaseInfoSemaphore . WaitAsync ( timeout . CheckAndGetTimeLeft ( ) , cancellationToken )
616- : DatabaseInfoSemaphore . Wait ( timeout . CheckAndGetTimeLeft ( ) , cancellationToken ) ;
617-
618- // We've timed out - calling Check, to throw the correct exception
619- if ( ! hasSemaphore )
620- timeout . Check ( ) ;
621-
622- try
623- {
624- if ( forceReload || ! NpgsqlDatabaseInfo . Cache . TryGetValue ( key , out database ) )
625- {
626- NpgsqlDatabaseInfo. Cache [ key ] = database = await NpgsqlDatabaseInfo . Load ( this , timeout , async) ;
627- }
628- }
629- finally
630- {
631- DatabaseInfoSemaphore . Release ( ) ;
632- }
633- }
634-
635- DatabaseInfo = database ;
636- TypeMapper. DatabaseInfo = database ;
637- }
638-
639598 internal async ValueTask < ClusterState > QueryClusterState (
640599 NpgsqlTimeout timeout , bool async , CancellationToken cancellationToken = default )
641600 {
@@ -1177,7 +1136,7 @@ async Task MultiplexingReadLoop()
11771136 SpinWait. SpinUntil ( ( ) => MultiplexAsyncWritingLock == 0 || IsBroken ) ;
11781137
11791138 ResetReadBuffer( ) ;
1180- _dataSource . Return ( this ) ;
1139+ DataSource . Return ( this ) ;
11811140 }
11821141 }
11831142
@@ -1214,7 +1173,7 @@ async Task MultiplexingReadLoop()
12141173 }
12151174
12161175 // "Return" the connector to the pool to for cleanup (e.g. update total connector count)
1217- _dataSource . Return ( this ) ;
1176+ DataSource . Return ( this ) ;
12181177
12191178 ConnectionLogger. LogError ( e , "Exception in multiplexing read loop" , Id ) ;
12201179 }
@@ -1930,9 +1889,9 @@ internal void Close()
19301889 }
19311890
19321891 internal bool TryRemovePendingEnlistedConnector ( Transaction transaction )
1933- => _dataSource . TryRemovePendingEnlistedConnector ( this , transaction ) ;
1892+ => DataSource . TryRemovePendingEnlistedConnector ( this , transaction ) ;
19341893
1935- internal void Return ( ) => _dataSource . Return ( this ) ;
1894+ internal void Return ( ) => DataSource . Return ( this ) ;
19361895
19371896 /// <inheritdoc />
19381897 public void Dispose ( ) => Close ( ) ;
@@ -1971,7 +1930,7 @@ internal Exception Break(Exception reason)
19711930 {
19721931 ClusterStateCache. UpdateClusterState ( Host , Port , ClusterState . Offline , DateTime . UtcNow ,
19731932 Settings . HostRecheckSecondsTranslated ) ;
1974- _dataSource . Clear ( ) ;
1933+ DataSource . Clear ( ) ;
19751934 }
19761935
19771936 LogMessages. BreakingConnection ( ConnectionLogger , Id , reason ) ;
@@ -2003,6 +1962,7 @@ internal Exception Break(Exception reason)
20031962 connection. Connector = null ;
20041963 connection. ConnectorBindingScope = ConnectorBindingScope . None ;
20051964 }
1965+
20061966 connection. FullState = ConnectionState . Broken ;
20071967 connection. ReleaseCloseLock ( ) ;
20081968 }
0 commit comments