Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to Shared for SqlDependencyUtils.cs #1370

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlDependencyListener.cs">
<Link>Microsoft\Data\SqlClient\SqlDependencyListener.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlDependencyUtils.cs">
<Link>Microsoft\Data\SqlClient\SqlDependencyUtils.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlDependencyUtils.AppDomain.cs">
<Link>Microsoft\Data\SqlClient\SqlDependencyUtils.AppDomain.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlEnums.cs">
<Link>Microsoft\Data\SqlClient\SqlEnums.cs</Link>
</Compile>
Expand Down Expand Up @@ -497,14 +503,16 @@
<Compile Include="Microsoft\Data\SqlClient\SqlClientEventSource.NetCoreApp.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetGroup)' == 'netcoreapp'">
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlDependencyUtils.AssemblyLoadContext.cs">
<Link>Microsoft\Data\SqlClient\SqlDependencyUtils.AssemblyLoadContext.cs</Link>
</Compile>
<Compile Include="Microsoft\Data\ProviderBase\DbConnectionPool.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlAuthenticationProviderManager.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDiagnosticListener.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDelegatedTransaction.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParser.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SNI\SslOverTdsStream.NetCoreApp.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlConnectionFactory.AssemblyLoadContext.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDependencyUtils.AssemblyLoadContext.cs" />
<Compile Include="Microsoft\Data\SqlClient\SNI\SNIStreams.ValueTask.cs" />
</ItemGroup>
<ItemGroup Condition="'$(OSGroup)' != 'AnyOS' AND '$(TargetFramework)' != 'netstandard2.0' AND '$(BuildSimulator)' == 'true'">
Expand Down Expand Up @@ -573,8 +581,6 @@
<Link>Microsoft\Data\SqlClient\SqlConnectionTimeoutErrorInternal.cs</Link>
</Compile>
<Compile Include="Microsoft\Data\SqlClient\SqlDataReader.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDependencyUtils.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDependencyUtils.AppDomain.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDelegatedTransaction.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlError.cs" />
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlEnclaveSession.cs">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlDependencyListener.cs">
<Link>Microsoft\Data\SqlClient\SqlDependencyListener.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlDependencyUtils.cs">
<Link>Microsoft\Data\SqlClient\SqlDependencyUtils.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs">
<Link>Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs</Link>
</Compile>
Expand Down Expand Up @@ -569,7 +572,6 @@
<Compile Include="Microsoft\Data\SqlClient\SqlDataReader.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDataReaderSmi.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDelegatedTransaction.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlDependencyUtils.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlError.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlInternalConnection.cs" />
<Compile Include="Microsoft\Data\SqlClient\SqlInternalConnectionSmi.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ internal partial class SqlDependencyPerAppDomainDispatcher : MarshalByRefObject
{
// Instance members

internal static readonly SqlDependencyPerAppDomainDispatcher
SingletonInstance = new SqlDependencyPerAppDomainDispatcher(); // singleton object
internal static readonly SqlDependencyPerAppDomainDispatcher SingletonInstance = new(); // singleton object

internal object _instanceLock = new object();
internal object _instanceLock = new();

// Dependency ID -> Dependency hashtable. 1 -> 1 mapping.
// 1) Used for ASP.NET to map from ID to dependency.
// 2) Used to enumerate dependencies to invalidate based on server.
private Dictionary<string, SqlDependency> _dependencyIdToDependencyHash;
private readonly Dictionary<string, SqlDependency> _dependencyIdToDependencyHash;

// holds dependencies list per notification and the command hash from which this notification was generated
// command hash is needed to remove its entry from _commandHashToNotificationId when the notification is removed
Expand All @@ -46,12 +45,12 @@ internal DependencyList(string commandHash)
// resource effect on SQL Server. The Guid identifier is sent to the server during notification enlistment,
// and returned during the notification event. Dependencies look up existing Guids, if one exists, to ensure
// they are re-using notification ids.
private Dictionary<string, DependencyList> _notificationIdToDependenciesHash;
private readonly Dictionary<string, DependencyList> _notificationIdToDependenciesHash;

// CommandHash value -> notificationId associated with it: 1->1 mapping. This map is used to quickly find if we need to create
// new notification or hookup into existing one.
// CommandHash is built from connection string, command text and parameters
private Dictionary<string, string> _commandHashToNotificationId;
private readonly Dictionary<string, string> _commandHashToNotificationId;

// TIMEOUT LOGIC DESCRIPTION
//
Expand All @@ -73,10 +72,10 @@ internal DependencyList(string commandHash)
private DateTime _nextTimeout;
// Timer to periodically check the dependencies in the table and see if anyone needs
// a timeout. We'll enable this only on demand.
private Timer _timeoutTimer;
private readonly Timer _timeoutTimer;

private static int _objectTypeCount; // EventSource counter
internal int ObjectID { get; } = Interlocked.Increment(ref _objectTypeCount);
private static int s_objectTypeCount; // EventSource counter
internal int ObjectID { get; } = Interlocked.Increment(ref s_objectTypeCount);

private SqlDependencyPerAppDomainDispatcher()
{
Expand All @@ -86,7 +85,12 @@ private SqlDependencyPerAppDomainDispatcher()
_dependencyIdToDependencyHash = new Dictionary<string, SqlDependency>();
_notificationIdToDependenciesHash = new Dictionary<string, DependencyList>();
_commandHashToNotificationId = new Dictionary<string, string>();
#if NETFRAMEWORK
_timeoutTimer = new Timer(new TimerCallback(TimeoutTimerCallback), null, Timeout.Infinite, Timeout.Infinite);

// If rude abort - we'll leak. This is acceptable for now.
AppDomain.CurrentDomain.DomainUnload += new EventHandler(UnloadEventHandler);
#else
_timeoutTimer = ADP.UnsafeCreateTimer(
new TimerCallback(TimeoutTimerCallback),
null,
Expand All @@ -95,17 +99,19 @@ private SqlDependencyPerAppDomainDispatcher()

SubscribeToAppDomainUnload();
SubscribeToAssemblyLoadContextUnload();
#endif // NETFRAMEWORK
}
finally
{
SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID);
}
}

#if NETCOREAPP || NETSTANDARD
partial void SubscribeToAppDomainUnload();

partial void SubscribeToAssemblyLoadContextUnload();

#endif
private void UnloadEventHandler(object sender, EventArgs e)
{
long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent("SqlDependencyPerAppDomainDispatcher.UnloadEventHandler | DEP | Object Id {0}", ObjectID);
Expand All @@ -115,7 +121,7 @@ private void UnloadEventHandler(object sender, EventArgs e)
// stopping of all start calls in this AppDomain. For containers shared among various AppDomains,
// this will just be a ref-count subtract. For non-shared containers, we will close the container
// and clean-up.
var dispatcher = SqlDependency.ProcessDispatcher;
SqlDependencyProcessDispatcher dispatcher = SqlDependency.ProcessDispatcher;
dispatcher?.QueueAppDomainUnloading(SqlDependency.AppDomainKey);
}
finally
Expand Down Expand Up @@ -171,8 +177,7 @@ internal string AddCommandEntry(string commandHash, SqlDependency dep)
{
// we have one or more SqlDependency instances with same command hash

DependencyList dependencyList = null;
if (!_notificationIdToDependenciesHash.TryGetValue(notificationId, out dependencyList))
if (!_notificationIdToDependenciesHash.TryGetValue(notificationId, out DependencyList dependencyList))
{
// this should not happen since _commandHashToNotificationId and _notificationIdToDependenciesHash are always
// updated together
Expand Down Expand Up @@ -203,7 +208,7 @@ internal string AddCommandEntry(string commandHash, SqlDependency dep)
Guid.NewGuid().ToString("D", System.Globalization.CultureInfo.InvariantCulture)
);
SqlClientEventSource.Log.TryNotificationTraceEvent("<sc.SqlDependencyPerAppDomainDispatcher.AddCommandEntry|DEP> Creating new Dependencies list for commandHash.");
DependencyList dependencyList = new DependencyList(commandHash);
DependencyList dependencyList = new(commandHash);
dependencyList.Add(dep);

// map command hash to notification we just created to reuse it for the next client
Expand Down Expand Up @@ -289,7 +294,7 @@ internal void InvalidateServer(string server, SqlNotification sqlNotification)
long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent("<sc.SqlDependencyPerAppDomainDispatcher.Invalidate|DEP> {0}, server: '{1}'", ObjectID, server);
try
{
List<SqlDependency> dependencies = new List<SqlDependency>();
List<SqlDependency> dependencies = new();

lock (_instanceLock)
{ // Copy inside of lock, but invalidate outside of lock.
Expand Down Expand Up @@ -449,8 +454,8 @@ private void RemoveDependencyFromCommandToDependenciesHash(SqlDependency depende
{
lock (_instanceLock)
{
List<string> notificationIdsToRemove = new List<string>();
List<string> commandHashesToRemove = new List<string>();
List<string> notificationIdsToRemove = new();
List<string> commandHashesToRemove = new();

foreach (KeyValuePair<string, DependencyList> entry in _notificationIdToDependenciesHash)
{
Expand Down