Skip to content

Commit

Permalink
Merge to shared - TdsParserSessionPool (#1595)
Browse files Browse the repository at this point in the history
  • Loading branch information
lcheunglci authored Oct 5, 2022
1 parent 1cda345 commit c68dd0e
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 254 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,9 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\TdsRecordBufferSetter.cs">
<Link>Microsoft\Data\SqlClient\TdsRecordBufferSetter.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\TdsParserSessionPool.cs">
<Link>Microsoft\Data\SqlClient\TdsParserSessionPool.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\TdsValueSetter.cs">
<Link>Microsoft\Data\SqlClient\TdsValueSetter.cs</Link>
</Compile>
Expand Down Expand Up @@ -643,7 +646,6 @@
<Compile Include="Microsoft\Data\SqlClient\TdsParser.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParser.RegisterEncoding.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserHelperClasses.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserSessionPool.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserStateObject.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserStateObjectManaged.cs" />
<Compile Include="Microsoft\Data\SqlTypes\SqlTypeWorkarounds.netcore.cs" />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,9 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\TdsRecordBufferSetter.cs">
<Link>Microsoft\Data\SqlClient\TdsRecordBufferSetter.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\TdsParserSessionPool.cs">
<Link>Microsoft\Data\SqlClient\TdsParserSessionPool.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\TdsValueSetter.cs">
<Link>Microsoft\Data\SqlClient\TdsValueSetter.cs</Link>
</Compile>
Expand Down Expand Up @@ -653,7 +656,6 @@
<Compile Include="Microsoft\Data\SqlClient\SqlUtil.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParser.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserHelperClasses.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserSessionPool.cs" />
<Compile Include="Microsoft\Data\SqlClient\TdsParserStateObject.cs" />
<Compile Include="Microsoft\Data\SqlTypes\SqlFileStream.cs" />
<Compile Include="Microsoft\Data\SqlTypes\SqlStreamChars.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ internal class TdsParserSessionPool
// NOTE: This is a very simplistic, lightweight pooler. It wasn't
// intended to handle huge number of items, just to keep track
// of the session objects to ensure that they're cleaned up in
// a timely manner, to avoid holding on to an unacceptible
// a timely manner, to avoid holding on to an unacceptable
// amount of server-side resources in the event that consumers
// let their data readers be GC'd, instead of explicitly
// closing or disposing of them

private const int MaxInactiveCount = 10; // pick something, preferably small...

private static int _objectTypeCount; // EventSource Counter
private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
private static int s_objectTypeCount; // EventSource Counter
private readonly int _objectID = System.Threading.Interlocked.Increment(ref s_objectTypeCount);

private readonly TdsParser _parser; // parser that owns us
private readonly List<TdsParserStateObject> _cache; // collection of all known sessions
Expand Down Expand Up @@ -89,23 +89,6 @@ internal void Deactivate()
}
}

// This is called from a ThreadAbort - ensure that it can be run from a CER Catch
internal void BestEffortCleanup()
{
for (int i = 0; i < _cache.Count; i++)
{
TdsParserStateObject session = _cache[i];
if (null != session)
{
var sessionHandle = session.Handle;
if (sessionHandle != null)
{
sessionHandle.Dispose();
}
}
}
}

internal void Dispose()
{
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.TdsParserSessionPool.Dispose|ADV> {0} disposing cachedCount={1}", ObjectID, _cachedCount);
Expand Down Expand Up @@ -140,7 +123,6 @@ internal void Dispose()
}
_cache.Clear();
_cachedCount = 0;

// Any active sessions will take care of themselves
// (It's too dangerous to dispose them, as this can cause AVs)
}
Expand Down Expand Up @@ -175,6 +157,7 @@ internal TdsParserStateObject GetSession(object owner)

session.Activate(owner);
}

SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.TdsParserSessionPool.GetSession|ADV> {0} using session {1}", ObjectID, session.ObjectID);
return session;
}
Expand All @@ -190,16 +173,19 @@ internal void PutSession(TdsParserStateObject session)
{
if (IsDisposed)
{
// We're diposed - just clean out the session
// We're disposed - just clean out the session
Debug.Assert(_cachedCount == 0, "SessionPool is disposed, but there are still sessions in the cache?");
session.Dispose();
}
else if ((okToReuse) && (_freeStateObjectCount < MaxInactiveCount))
{
// Session is good to re-use and our cache has space
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.TdsParserSessionPool.PutSession|ADV> {0} keeping session {1} cachedCount={2}", ObjectID, session.ObjectID, _cachedCount);
#if NETFRAMEWORK
Debug.Assert(!session._pendingData, "pending data on a pooled session?");

#else
Debug.Assert(!session.HasPendingData, "pending data on a pooled session?");
#endif
_freeStateObjects[_freeStateObjectCount] = session;
_freeStateObjectCount++;
}
Expand All @@ -218,23 +204,37 @@ internal void PutSession(TdsParserStateObject session)
}
}


internal int ActiveSessionsCount => _cachedCount - _freeStateObjectCount;

internal string TraceString()
{
return String.Format(/*IFormatProvider*/ null,
return string.Format(/*IFormatProvider*/ null,
"(ObjID={0}, free={1}, cached={2}, total={3})",
_objectID,
null == _freeStateObjects ? "(null)" : _freeStateObjectCount.ToString((IFormatProvider)null),
_cachedCount,
_cache.Count);
}

internal int ActiveSessionsCount
#if NETFRAMEWORK
// This is called from a ThreadAbort - ensure that it can be run from a CER Catch
internal void BestEffortCleanup()
{
get
for (int i = 0; i < _cache.Count; i++)
{
return _cachedCount - _freeStateObjectCount;
TdsParserStateObject session = _cache[i];
if (null != session)
{
SNIHandle sessionHandle = session.Handle;
if (sessionHandle != null)
{
sessionHandle.Dispose();
}
}
}
}
#endif
}
}

Expand Down

0 comments on commit c68dd0e

Please sign in to comment.