private static void WriteSessionRecoveryFeatureRequest(TdsPackageWriter writer, SessionData reconnectData) { var(_, initialLength, currentLength, writeState) = SessionRecoveryFeatureRequestLengths(reconnectData); writer.WriteByte(TdsEnums.FEATUREEXT_SRECOVERY); if (reconnectData == null) { writer.WriteInt32(0); } else { writer.WriteInt32(8 + initialLength + currentLength); // length of data w/o total length (initial + current + 2 * sizeof(DWORD)) writer.WriteInt32(initialLength); writer.WriteByteLenString(reconnectData.InitialDatabase); writer.WriteCollation(reconnectData.InitialCollation); writer.WriteByteLenString(reconnectData.InitialLanguage); for (var i = 0; i < SessionData.MaxNumberOfSessionStates; i++) { if (reconnectData.InitialState[i] != null) { writer.WriteByte((byte)i); if (reconnectData.InitialState[i].Length < 0xFF) { writer.WriteByte((byte)reconnectData.InitialState[i].Length); } else { writer.WriteByte(0xFF); writer.WriteInt32(reconnectData.InitialState[i].Length); } writer.WriteByteArray(reconnectData.InitialState[i]); } } writer.WriteInt32(currentLength); writer.WriteByteLenString(reconnectData.Database != reconnectData.InitialDatabase ? reconnectData.Database : null); writer.WriteCollation(SqlCollations.AreSame(reconnectData.InitialCollation, reconnectData.Collation) ? null : reconnectData.Collation); writer.WriteByteLenString(reconnectData.Language != reconnectData.InitialLanguage ? reconnectData.Language : null); for (var i = 0; i < SessionData.MaxNumberOfSessionStates; i++) { if (writeState[i]) { writer.WriteByte((byte)i); if (reconnectData.Delta[i].DataLength < 0xFF) { writer.WriteByte((byte)reconnectData.Delta[i].DataLength); } else { writer.WriteByte(0xFF); writer.WriteInt32(reconnectData.Delta[i].DataLength); } writer.WriteByteArray(reconnectData.Delta[i].Data); } } } }
private static (int totalLength, int initialLength, int currentLength, bool[] writeState) SessionRecoveryFeatureRequestLengths(SessionData reconnectData) { var totalLength = 1; var initialLength = 0; // sizeof(DWORD) - length itself var currentLength = 0; // sizeof(DWORD) - length itself var writeState = new bool[SessionData.MaxNumberOfSessionStates]; if (reconnectData == null) { totalLength += 4; } else { Debug.Assert(reconnectData.UnrecoverableStatesCount == 0, "Unrecoverable state count should be 0"); initialLength += 1 + 2 * NullAwareStringLength(reconnectData.InitialDatabase); initialLength += 1 + 2 * NullAwareStringLength(reconnectData.InitialLanguage); initialLength += reconnectData.InitialCollation == null ? 1 : 6; for (var i = 0; i < SessionData.MaxNumberOfSessionStates; i++) { if (reconnectData.InitialState[i] != null) { initialLength += 1 /* StateId*/ + StateValueLength(reconnectData.InitialState[i].Length); } } currentLength += 1 + 2 * (reconnectData.InitialDatabase == reconnectData.Database ? 0 : NullAwareStringLength(reconnectData.Database)); currentLength += 1 + 2 * (reconnectData.InitialLanguage == reconnectData.Language ? 0 : NullAwareStringLength(reconnectData.Language)); currentLength += reconnectData.Collation != null && !SqlCollations.AreSame(reconnectData.Collation, reconnectData.InitialCollation) ? 6 : 1; for (var i = 0; i < SessionData.MaxNumberOfSessionStates; i++) { if (reconnectData.Delta[i] != null) { Debug.Assert(reconnectData.Delta[i].Recoverable, "State should be recoverable"); writeState[i] = true; if (reconnectData.InitialState[i] != null && reconnectData.InitialState[i].Length == reconnectData.Delta[i].DataLength) { writeState[i] = false; for (var j = 0; j < reconnectData.Delta[i].DataLength; j++) { if (reconnectData.InitialState[i][j] != reconnectData.Delta[i].Data[j]) { writeState[i] = true; break; } } } if (writeState[i]) { currentLength += 1 /* StateId*/ + StateValueLength(reconnectData.Delta[i].DataLength); } } } totalLength += initialLength + currentLength + 12 /* length fields (initial, current, total) */; } return(totalLength, initialLength, currentLength, writeState); }