@@ -2037,22 +2037,23 @@ internal int ReadPlpBytesChunk(byte[] buff, int offset, int len)
2037
2037
2038
2038
internal TdsOperationStatus TryReadPlpBytes ( ref byte [ ] buff , int offset , int len , out int totalBytesRead )
2039
2039
{
2040
+ bool canContinue = false ;
2040
2041
bool isStarting = false ;
2041
2042
bool isContinuing = false ;
2042
2043
bool compatibilityMode = LocalAppContextSwitches . UseCompatibilityAsyncBehaviour ;
2043
2044
if ( ! compatibilityMode )
2044
2045
{
2045
- ( _ , isStarting , isContinuing ) = GetSnapshotStatuses ( ) ;
2046
+ ( canContinue , isStarting , isContinuing ) = GetSnapshotStatuses ( ) ;
2046
2047
}
2047
- return TryReadPlpBytes ( ref buff , offset , len , out totalBytesRead , isStarting || isContinuing , compatibilityMode ) ;
2048
+ return TryReadPlpBytes ( ref buff , offset , len , out totalBytesRead , canContinue , canContinue , compatibilityMode ) ;
2048
2049
}
2049
2050
// Reads the requested number of bytes from a plp data stream, or the entire data if
2050
2051
// requested length is -1 or larger than the actual length of data. First call to this method
2051
2052
// should be preceeded by a call to ReadPlpLength or ReadDataLength.
2052
2053
// Returns the actual bytes read.
2053
2054
// NOTE: This method must be retriable WITHOUT replaying a snapshot
2054
2055
// Every time you call this method increment the offset and decrease len by the value of totalBytesRead
2055
- internal TdsOperationStatus TryReadPlpBytes ( ref byte [ ] buff , int offset , int len , out int totalBytesRead , bool writeDataSizeToSnapshot , bool compatibilityMode )
2056
+ internal TdsOperationStatus TryReadPlpBytes ( ref byte [ ] buff , int offset , int len , out int totalBytesRead , bool canContinue , bool writeDataSizeToSnapshot , bool compatibilityMode )
2056
2057
{
2057
2058
totalBytesRead = 0 ;
2058
2059
@@ -2077,9 +2078,16 @@ internal TdsOperationStatus TryReadPlpBytes(ref byte[] buff, int offset, int len
2077
2078
// If total length is known up front, allocate the whole buffer in one shot instead of realloc'ing and copying over each time
2078
2079
if ( buff == null && _longlen != TdsEnums . SQL_PLP_UNKNOWNLEN )
2079
2080
{
2080
- if ( writeDataSizeToSnapshot )
2081
+ if ( compatibilityMode && _snapshot != null && _snapshotStatus != SnapshotStatus . NotActive )
2082
+ {
2083
+ // legacy replay path perf optimization
2084
+ // if there is a snapshot which contains a stored plp buffer take it
2085
+ // and try to use it if it is the right length
2086
+ buff = TryTakeSnapshotStorage ( ) as byte [ ] ;
2087
+ }
2088
+ else if ( writeDataSizeToSnapshot && canContinue && _snapshot != null )
2081
2089
{
2082
- // if there is a snapshot and it contains a stored plp buffer take it
2090
+ // if there is a snapshot which it contains a stored plp buffer take it
2083
2091
// and try to use it if it is the right length
2084
2092
buff = TryTakeSnapshotStorage ( ) as byte [ ] ;
2085
2093
if ( buff != null )
@@ -2088,13 +2096,7 @@ internal TdsOperationStatus TryReadPlpBytes(ref byte[] buff, int offset, int len
2088
2096
totalBytesRead = offset ;
2089
2097
}
2090
2098
}
2091
- else if ( compatibilityMode && _snapshot != null && _snapshotStatus != SnapshotStatus . NotActive )
2092
- {
2093
- // legacy replay path perf optimization
2094
- // if there is a snapshot and it contains a stored plp buffer take it
2095
- // and try to use it if it is the right length
2096
- buff = TryTakeSnapshotStorage ( ) as byte [ ] ;
2097
- }
2099
+
2098
2100
2099
2101
if ( ( ulong ) ( buff ? . Length ?? 0 ) != _longlen )
2100
2102
{
@@ -2146,44 +2148,50 @@ internal TdsOperationStatus TryReadPlpBytes(ref byte[] buff, int offset, int len
2146
2148
_longlenleft -= ( ulong ) bytesRead ;
2147
2149
if ( result != TdsOperationStatus . Done )
2148
2150
{
2149
- if ( writeDataSizeToSnapshot )
2151
+ if ( compatibilityMode && _snapshot != null )
2150
2152
{
2153
+ // legacy replay path perf optimization
2151
2154
// a partial read has happened so store the target buffer in the snapshot
2152
2155
// so it can be re-used when another packet arrives and we read again
2153
2156
SetSnapshotStorage ( buff ) ;
2154
- SetSnapshotDataSize ( bytesRead ) ;
2155
-
2156
2157
}
2157
- else if ( compatibilityMode && _snapshot != null )
2158
+ else if ( canContinue )
2158
2159
{
2159
- // legacy replay path perf optimization
2160
2160
// a partial read has happened so store the target buffer in the snapshot
2161
2161
// so it can be re-used when another packet arrives and we read again
2162
2162
SetSnapshotStorage ( buff ) ;
2163
+ if ( writeDataSizeToSnapshot )
2164
+ {
2165
+ SetSnapshotDataSize ( bytesRead ) ;
2166
+ }
2163
2167
}
2164
2168
return result ;
2165
2169
}
2170
+ if ( writeDataSizeToSnapshot && canContinue )
2171
+ {
2172
+ SetSnapshotDataSize ( bytesRead ) ;
2173
+ }
2166
2174
2167
2175
if ( _longlenleft == 0 )
2168
2176
{
2169
2177
// Read the next chunk or cleanup state if hit the end
2170
2178
result = TryReadPlpLength ( false , out _ ) ;
2171
2179
if ( result != TdsOperationStatus . Done )
2172
2180
{
2173
- if ( writeDataSizeToSnapshot )
2174
- {
2175
- if ( result == TdsOperationStatus . NeedMoreData )
2176
- {
2177
- SetSnapshotStorage ( buff ) ;
2178
- SetSnapshotDataSize ( bytesRead ) ;
2179
- }
2180
- }
2181
- else if ( compatibilityMode && _snapshot != null )
2181
+ if ( compatibilityMode && _snapshot != null )
2182
2182
{
2183
2183
// a partial read has happened so store the target buffer in the snapshot
2184
2184
// so it can be re-used when another packet arrives and we read again
2185
2185
SetSnapshotStorage ( buff ) ;
2186
2186
}
2187
+ else if ( canContinue && result == TdsOperationStatus . NeedMoreData )
2188
+ {
2189
+ SetSnapshotStorage ( buff ) ;
2190
+ if ( writeDataSizeToSnapshot )
2191
+ {
2192
+ SetSnapshotDataSize ( bytesRead ) ;
2193
+ }
2194
+ }
2187
2195
return result ;
2188
2196
}
2189
2197
}
@@ -3455,9 +3463,9 @@ internal bool IsSnapshotContinuing()
3455
3463
_snapshotStatus == TdsParserStateObject . SnapshotStatus . ContinueRunning ;
3456
3464
}
3457
3465
3458
- internal ( bool IsAvailable , bool IsStarting , bool IsContinuing ) GetSnapshotStatuses ( )
3466
+ internal ( bool CanContinue , bool IsStarting , bool IsContinuing ) GetSnapshotStatuses ( )
3459
3467
{
3460
- bool isAvailable = _snapshot != null && _snapshot . ContinueEnabled ;
3468
+ bool isAvailable = _snapshot != null && _snapshot . ContinueEnabled && _snapshotStatus != SnapshotStatus . NotActive ;
3461
3469
bool isStarting = false ;
3462
3470
bool isContinuing = false ;
3463
3471
if ( isAvailable )
@@ -4020,6 +4028,28 @@ internal void CheckStack(string trace)
4020
4028
Debug . Assert ( _stateObj . _permitReplayStackTraceToDiffer || prev . Stack == trace , "The stack trace on subsequent replays should be the same" ) ;
4021
4029
}
4022
4030
}
4031
+
4032
+ public int CurrentPacketIndex
4033
+ {
4034
+ get
4035
+ {
4036
+ int value = - 1 ;
4037
+ if ( _current != null )
4038
+ {
4039
+ PacketData current = _firstPacket ;
4040
+ while ( current != null )
4041
+ {
4042
+ value += 1 ;
4043
+ if ( current == _current )
4044
+ {
4045
+ break ;
4046
+ }
4047
+ current = current . NextPacket ;
4048
+ }
4049
+ }
4050
+ return value ;
4051
+ }
4052
+ }
4023
4053
#endif
4024
4054
public bool ContinueEnabled => ! LocalAppContextSwitches . UseCompatibilityAsyncBehaviour ;
4025
4055
0 commit comments