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

Merge TDSParserStateObject.StateSnapshot packet list mangement and reimplment #2164

Merged
merged 1 commit into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal abstract partial class TdsParserStateObject
// Timeout variables
private readonly WeakReference _cancellationOwner = new WeakReference(null);

// Async
// Async

//////////////////
// Constructors //
Expand Down Expand Up @@ -1072,12 +1072,18 @@ internal bool TryReadNetworkPacket()
{
if (_snapshotReplay)
{
if (_snapshot.Replay())
#if DEBUG
// in debug builds stack traces contain line numbers so if we want to be
// able to compare the stack traces they must all be created in the same
// location in the code
string stackTrace = Environment.StackTrace;
#endif
if (_snapshot.MoveNext())
{
#if DEBUG
if (s_checkNetworkPacketRetryStacks)
{
_snapshot.CheckStack(Environment.StackTrace);
_snapshot.CheckStack(stackTrace);
}
#endif
return true;
Expand All @@ -1087,7 +1093,7 @@ internal bool TryReadNetworkPacket()
{
if (s_checkNetworkPacketRetryStacks)
{
_lastStack = Environment.StackTrace;
_lastStack = stackTrace;
}
}
#endif
Expand Down Expand Up @@ -1123,7 +1129,7 @@ internal bool TryReadNetworkPacket()
internal void PrepareReplaySnapshot()
{
_networkPacketTaskSource = null;
_snapshot.PrepareReplay();
_snapshot.MoveToStart();
}

internal void ReadSniSyncOverAsync()
Expand Down Expand Up @@ -1434,7 +1440,7 @@ internal void ReadSni(TaskCompletionSource<object> completion)
Timeout.Infinite,
Timeout.Infinite
);


// -1 == Infinite
// 0 == Already timed out (NOTE: To simulate the same behavior as sync we will only timeout on 0 if we receive an IO Pending from SNI)
Expand Down Expand Up @@ -1740,10 +1746,10 @@ public void ProcessSniPacket(PacketHandle packet, uint error)

if (_snapshot != null)
{
_snapshot.PushBuffer(_inBuff, _inBytesRead);
_snapshot.AppendPacketData(_inBuff, _inBytesRead);
if (_snapshotReplay)
{
_snapshot.Replay();
_snapshot.MoveNext();
#if DEBUG
_snapshot.AssertCurrent();
#endif
Expand Down Expand Up @@ -3024,137 +3030,7 @@ internal void CloneCleanupAltMetaDataSetArray()

sealed partial class StateSnapshot
{
private sealed partial class PacketData
{
public byte[] Buffer;
public int Read;
public PacketData Prev;

public void SetStack(string value)
{
SetStackInternal(value);
}
partial void SetStackInternal(string value);

public void Clear()
{
Buffer = null;
Read = 0;
Prev = null;
SetStackInternal(null);
}
}

#if DEBUG
private sealed partial class PacketData
{
public string Stack;

partial void SetStackInternal(string value)
{
Stack = value;
}
}


#endif
private PacketData _snapshotInBuffList;
private PacketData _sparePacket;

internal byte[] _plpBuffer;

private int _snapshotInBuffCount;

#if DEBUG
internal void AssertCurrent()
{
Debug.Assert(_snapshotInBuffCurrent == _snapshotInBuffCount, "Should not be reading new packets when not replaying last packet");
}

internal void CheckStack(string trace)
{
PacketData prev = _snapshotInBuffList?.Prev;
if (prev.Stack == null)
{
prev.Stack = trace;
}
else
{
Debug.Assert(_stateObj._permitReplayStackTraceToDiffer || prev.Stack.ToString() == trace.ToString(), "The stack trace on subsequent replays should be the same");
}
}
#endif
internal void PushBuffer(byte[] buffer, int read)
{
#if DEBUG
for (PacketData current = _snapshotInBuffList; current != null; current = current.Prev)
{
Debug.Assert(!object.ReferenceEquals(current.Buffer, buffer));
}
#endif

PacketData packetData = _sparePacket;
if (packetData is null)
{
packetData = new PacketData();
}
else
{
_sparePacket = null;
}
packetData.Buffer = buffer;
packetData.Read = read;
packetData.Prev = _snapshotInBuffList;
#if DEBUG
packetData.SetStack(_stateObj._lastStack);
#endif
_snapshotInBuffList = packetData;
_snapshotInBuffCount++;
}

internal bool Replay()
{
if (_snapshotInBuffCurrent < _snapshotInBuffCount)
{
PacketData next = _snapshotInBuffList;
for (
int position = (_snapshotInBuffCount - 1);
position != _snapshotInBuffCurrent;
position -= 1
)
{
next = next.Prev;
}
_stateObj._inBuff = next.Buffer;
_stateObj._inBytesUsed = 0;
_stateObj._inBytesRead = next.Read;
_snapshotInBuffCurrent++;
return true;
}

return false;
}

internal void Snap(TdsParserStateObject state)
{
_snapshotInBuffList = null;
_snapshotInBuffCount = 0;
_snapshotInBuffCurrent = 0;

CaptureAsStart(state);
}

internal void Clear()
{
PacketData packet = _snapshotInBuffList;
_snapshotInBuffList = null;
_snapshotInBuffCount = 0;

packet.Clear();
_sparePacket = packet;

ClearCore();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1164,7 +1164,7 @@ internal bool TrySkipBytes(int num)
/////////////////////////////////////////

#if DEBUG
StackTrace _lastStack;
string _lastStack;
#endif

internal bool TryReadNetworkPacket()
Expand All @@ -1179,12 +1179,18 @@ internal bool TryReadNetworkPacket()
{
if (_snapshotReplay)
{
if (_snapshot.Replay())
#if DEBUG
// in debug builds stack traces contain line numbers so if we want to be
// able to compare the stack traces they must all be created in the same
// location in the code
string stackTrace = Environment.StackTrace;
#endif
if (_snapshot.MoveNext())
{
#if DEBUG
if (s_checkNetworkPacketRetryStacks)
{
_snapshot.CheckStack(new StackTrace());
_snapshot.CheckStack(stackTrace);
}
#endif
return true;
Expand All @@ -1194,7 +1200,7 @@ internal bool TryReadNetworkPacket()
{
if (s_checkNetworkPacketRetryStacks)
{
_lastStack = new StackTrace();
_lastStack = stackTrace;
}
}
#endif
Expand Down Expand Up @@ -1230,7 +1236,7 @@ internal bool TryReadNetworkPacket()
internal void PrepareReplaySnapshot()
{
_networkPacketTaskSource = null;
_snapshot.PrepareReplay();
_snapshot.MoveToStart();
}

internal void ReadSniSyncOverAsync()
Expand Down Expand Up @@ -1884,10 +1890,10 @@ public void ProcessSniPacket(IntPtr packet, uint error)

if (_snapshot != null)
{
_snapshot.PushBuffer(_inBuff, _inBytesRead);
_snapshot.AppendPacketData(_inBuff, _inBytesRead);
if (_snapshotReplay)
{
_snapshot.Replay();
_snapshot.MoveNext();
#if DEBUG
_snapshot.AssertCurrent();
#endif
Expand Down Expand Up @@ -3189,98 +3195,10 @@ internal void CloneCleanupAltMetaDataSetArray()
}
}

class PacketData
{
public byte[] Buffer;
public int Read;
#if DEBUG
public StackTrace Stack;
#endif
}

sealed partial class StateSnapshot
{
private List<PacketData> _snapshotInBuffs;

public StateSnapshot()
{
_snapshotInBuffs = new List<PacketData>();
}

#if DEBUG
internal void AssertCurrent()
{
Debug.Assert(_snapshotInBuffCurrent == _snapshotInBuffs.Count, "Should not be reading new packets when not replaying last packet");
}

internal void CheckStack(StackTrace trace)
{
PacketData prev = _snapshotInBuffs[_snapshotInBuffCurrent - 1];
if (prev.Stack == null)
{
prev.Stack = trace;
}
else
{
Debug.Assert(_stateObj._permitReplayStackTraceToDiffer || prev.Stack.ToString() == trace.ToString(), "The stack trace on subsequent replays should be the same");
}
}
#endif

internal void PushBuffer(byte[] buffer, int read)
{
#if DEBUG
if (_snapshotInBuffs != null && _snapshotInBuffs.Count > 0)
{
foreach (PacketData packet in _snapshotInBuffs)
{
if (object.ReferenceEquals(packet.Buffer, buffer))
{
Debug.Assert(false,"buffer is already present in packet list");
}
}
}
#endif

PacketData packetData = new PacketData();
packetData.Buffer = buffer;
packetData.Read = read;
#if DEBUG
packetData.Stack = _stateObj._lastStack;
#endif

_snapshotInBuffs.Add(packetData);
}

internal bool Replay()
{
if (_snapshotInBuffCurrent < _snapshotInBuffs.Count)
{
PacketData next = _snapshotInBuffs[_snapshotInBuffCurrent];
_stateObj._inBuff = next.Buffer;
_stateObj._inBytesUsed = 0;
_stateObj._inBytesRead = next.Read;
_snapshotInBuffCurrent++;
return true;
}

return false;
}

internal void Snap(TdsParserStateObject state)
{
_snapshotInBuffs.Clear();
_snapshotInBuffCurrent = 0;

CaptureAsStart(state);
}

internal void Clear()
{
_snapshotInBuffs.Clear();

ClearCore();
}
}
}
}