From bebf28c752b5c759006c9d7542ab0f972a1d0eb9 Mon Sep 17 00:00:00 2001 From: panoskj Date: Sun, 24 Sep 2023 03:21:11 +0300 Subject: [PATCH] 2. Merging "Buffer read" methods of TdsParserStateObject, port #667 to netfx. --- .../SqlClient/TdsParserStateObject.netcore.cs | 21 +++++++ .../SqlClient/TdsParserStateObject.netfx.cs | 59 +++++++++---------- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs index 893bbcd463..89b9321cff 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs @@ -313,6 +313,9 @@ internal bool TryReadInt16(out short value) internal bool TryReadInt32(out int value) { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to ReadInt32"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); Span buffer = stackalloc byte[4]; if (((_inBytesUsed + 4) > _inBytesRead) || (_inBytesPacket < 4)) @@ -342,6 +345,9 @@ internal bool TryReadInt32(out int value) // This method is safe to call when doing async without snapshot internal bool TryReadInt64(out long value) { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to ReadInt64"); // you need to setup for a thread abort somewhere before you call this method +#endif if ((_inBytesPacket == 0) || (_inBytesUsed == _inBytesRead)) { if (!TryPrepareBuffer()) @@ -420,6 +426,9 @@ internal bool TryReadUInt16(out ushort value) // This method is safe to call when doing async without replay internal bool TryReadUInt32(out uint value) { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to ReadUInt32"); // you need to setup for a thread abort somewhere before you call this method +#endif if ((_inBytesPacket == 0) || (_inBytesUsed == _inBytesRead)) { if (!TryPrepareBuffer()) @@ -468,6 +477,9 @@ internal bool TryReadUInt32(out uint value) internal bool TryReadSingle(out float value) { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to ReadSingle"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); if (((_inBytesUsed + 4) > _inBytesRead) || (_inBytesPacket < 4)) { @@ -501,6 +513,9 @@ internal bool TryReadSingle(out float value) internal bool TryReadDouble(out double value) { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to ReadDouble"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); if (((_inBytesUsed + 8) > _inBytesRead) || (_inBytesPacket < 8)) { @@ -534,6 +549,9 @@ internal bool TryReadDouble(out double value) internal bool TryReadString(int length, out string value) { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to ReadString"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); int cBytes = length << 1; byte[] buf; @@ -574,6 +592,9 @@ internal bool TryReadString(int length, out string value) internal bool TryReadStringWithEncoding(int length, System.Text.Encoding encoding, bool isPlp, out string value) { +#if NETFRAMEWORK + TdsParser.ReliabilitySection.Assert("unreliable call to ReadStringWithEncoding"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); if (null == encoding) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs index e03d64e84d..eafa6b1c50 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs @@ -380,75 +380,68 @@ internal bool TryReadInt16(out short value) { Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); - byte[] buffer; - int offset; + Span buffer = stackalloc byte[2]; if (((_inBytesUsed + 2) > _inBytesRead) || (_inBytesPacket < 2)) { // If the int16 isn't fully in the buffer, or if it isn't fully in the packet, // then use ReadByteArray since the logic is there to take care of that. - if (!TryReadByteArray(_bTmp, 2)) + if (!TryReadByteArray(buffer, 2)) { value = default; return false; } - - buffer = _bTmp; - offset = 0; } else { // The entire int16 is in the packet and in the buffer, so just return it // and take care of the counters. - - buffer = _inBuff; - offset = _inBytesUsed; - + buffer = _inBuff.AsSpan(_inBytesUsed, 2); _inBytesUsed += 2; _inBytesPacket -= 2; } AssertValidState(); - value = (short)((buffer[offset + 1] << 8) + buffer[offset]); + value = (short)((buffer[1] << 8) + buffer[0]); return true; } internal bool TryReadInt32(out int value) { +#if NETFRAMEWORK TdsParser.ReliabilitySection.Assert("unreliable call to ReadInt32"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); + Span buffer = stackalloc byte[4]; if (((_inBytesUsed + 4) > _inBytesRead) || (_inBytesPacket < 4)) { // If the int isn't fully in the buffer, or if it isn't fully in the packet, // then use ReadByteArray since the logic is there to take care of that. - if (!TryReadByteArray(_bTmp, 4)) + if (!TryReadByteArray(buffer, 4)) { value = 0; return false; } - - AssertValidState(); - value = BitConverter.ToInt32(_bTmp, 0); - return true; } else { // The entire int is in the packet and in the buffer, so just return it // and take care of the counters. - - value = BitConverter.ToInt32(_inBuff, _inBytesUsed); - + buffer = _inBuff.AsSpan(_inBytesUsed, 4); _inBytesUsed += 4; _inBytesPacket -= 4; + } AssertValidState(); + value = (buffer[3] << 24) + (buffer[2] << 16) + (buffer[1] << 8) + buffer[0]; return true; } - } // This method is safe to call when doing async without snapshot internal bool TryReadInt64(out long value) { +#if NETFRAMEWORK TdsParser.ReliabilitySection.Assert("unreliable call to ReadInt64"); // you need to setup for a thread abort somewhere before you call this method +#endif if ((_inBytesPacket == 0) || (_inBytesUsed == _inBytesRead)) { if (!TryPrepareBuffer()) @@ -499,43 +492,37 @@ internal bool TryReadUInt16(out ushort value) { Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); - byte[] buffer; - int offset; + Span buffer = stackalloc byte[2]; if (((_inBytesUsed + 2) > _inBytesRead) || (_inBytesPacket < 2)) { // If the uint16 isn't fully in the buffer, or if it isn't fully in the packet, // then use ReadByteArray since the logic is there to take care of that. - - if (!TryReadByteArray(_bTmp, 2)) + if (!TryReadByteArray(buffer, 2)) { value = default; return false; } - - buffer = _bTmp; - offset = 0; } else { // The entire uint16 is in the packet and in the buffer, so just return it // and take care of the counters. - - buffer = _inBuff; - offset = _inBytesUsed; - + buffer = _inBuff.AsSpan(_inBytesUsed, 2); _inBytesUsed += 2; _inBytesPacket -= 2; } AssertValidState(); - value = (ushort)((buffer[offset + 1] << 8) + buffer[offset]); + value = (ushort)((buffer[1] << 8) + buffer[0]); return true; } // This method is safe to call when doing async without replay internal bool TryReadUInt32(out uint value) { +#if NETFRAMEWORK TdsParser.ReliabilitySection.Assert("unreliable call to ReadUInt32"); // you need to setup for a thread abort somewhere before you call this method +#endif if ((_inBytesPacket == 0) || (_inBytesUsed == _inBytesRead)) { if (!TryPrepareBuffer()) @@ -584,7 +571,9 @@ internal bool TryReadUInt32(out uint value) internal bool TryReadSingle(out float value) { +#if NETFRAMEWORK TdsParser.ReliabilitySection.Assert("unreliable call to ReadSingle"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); if (((_inBytesUsed + 4) > _inBytesRead) || (_inBytesPacket < 4)) { @@ -618,7 +607,9 @@ internal bool TryReadSingle(out float value) internal bool TryReadDouble(out double value) { +#if NETFRAMEWORK TdsParser.ReliabilitySection.Assert("unreliable call to ReadDouble"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); if (((_inBytesUsed + 8) > _inBytesRead) || (_inBytesPacket < 8)) { @@ -652,7 +643,9 @@ internal bool TryReadDouble(out double value) internal bool TryReadString(int length, out string value) { +#if NETFRAMEWORK TdsParser.ReliabilitySection.Assert("unreliable call to ReadString"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); int cBytes = length << 1; byte[] buf; @@ -693,7 +686,9 @@ internal bool TryReadString(int length, out string value) internal bool TryReadStringWithEncoding(int length, System.Text.Encoding encoding, bool isPlp, out string value) { +#if NETFRAMEWORK TdsParser.ReliabilitySection.Assert("unreliable call to ReadStringWithEncoding"); // you need to setup for a thread abort somewhere before you call this method +#endif Debug.Assert(_syncOverAsync || !_asyncReadWithoutSnapshot, "This method is not safe to call when doing sync over async"); if (null == encoding)