internal int WriteSessionRecoveryFeatureRequest(SessionData reconnectData, bool write /* if false just calculates the length */)
{
int len = 1;
if (write)
{
_physicalStateObj.WriteByte(TdsEnums.FEATUREEXT_SRECOVERY);
}
if (reconnectData == null)
{
if (write)
{
WriteInt(0, _physicalStateObj);
}
len += 4;
}
else
{
Debug.Assert(reconnectData._unrecoverableStatesCount == 0, "Unrecoverable state count should be 0");
int initialLength = 0; // sizeof(DWORD) - length itself
initialLength += 1 + 2 * TdsParserStaticMethods.NullAwareStringLength(reconnectData._initialDatabase);
initialLength += 1 + 2 * TdsParserStaticMethods.NullAwareStringLength(reconnectData._initialLanguage);
initialLength += (reconnectData._initialCollation == null) ? 1 : 6;
for (int i = 0; i < SessionData._maxNumberOfSessionStates; i++)
{
if (reconnectData._initialState[i] != null)
{
initialLength += 1 /* StateId*/ + StateValueLength(reconnectData._initialState[i].Length);
}
}
int currentLength = 0; // sizeof(DWORD) - length itself
currentLength += 1 + 2 * (reconnectData._initialDatabase == reconnectData._database ? 0 : TdsParserStaticMethods.NullAwareStringLength(reconnectData._database));
currentLength += 1 + 2 * (reconnectData._initialLanguage == reconnectData._language ? 0 : TdsParserStaticMethods.NullAwareStringLength(reconnectData._language));
currentLength += (reconnectData._collation != null && !SqlCollation.AreSame(reconnectData._collation, reconnectData._initialCollation)) ? 6 : 1;
bool[] writeState = new bool[SessionData._maxNumberOfSessionStates];
for (int 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 (int 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);
}
}
}
if (write)
{
WriteInt(8 + initialLength + currentLength, _physicalStateObj); // length of data w/o total length (initial + current + 2 * sizeof(DWORD))
WriteInt(initialLength, _physicalStateObj);
WriteIdentifier(reconnectData._initialDatabase, _physicalStateObj);
WriteCollation(reconnectData._initialCollation, _physicalStateObj);
WriteIdentifier(reconnectData._initialLanguage, _physicalStateObj);
for (int i = 0; i < SessionData._maxNumberOfSessionStates; i++)
{
if (reconnectData._initialState[i] != null)
{
_physicalStateObj.WriteByte((byte)i);
if (reconnectData._initialState[i].Length < 0xFF)
{
_physicalStateObj.WriteByte((byte)reconnectData._initialState[i].Length);
}
else
{
_physicalStateObj.WriteByte(0xFF);
WriteInt(reconnectData._initialState[i].Length, _physicalStateObj);
}
_physicalStateObj.WriteByteArray(reconnectData._initialState[i], reconnectData._initialState[i].Length, 0);
}
}
WriteInt(currentLength, _physicalStateObj);
WriteIdentifier(reconnectData._database != reconnectData._initialDatabase ? reconnectData._database : null, _physicalStateObj);
WriteCollation(SqlCollation.AreSame(reconnectData._initialCollation, reconnectData._collation) ? null : reconnectData._collation, _physicalStateObj);
WriteIdentifier(reconnectData._language != reconnectData._initialLanguage ? reconnectData._language : null, _physicalStateObj);
for (int i = 0; i < SessionData._maxNumberOfSessionStates; i++)
{
if (writeState[i])
{
_physicalStateObj.WriteByte((byte)i);
if (reconnectData._delta[i]._dataLength < 0xFF)
{
_physicalStateObj.WriteByte((byte)reconnectData._delta[i]._dataLength);
}
else
{
_physicalStateObj.WriteByte(0xFF);
WriteInt(reconnectData._delta[i]._dataLength, _physicalStateObj);
}
_physicalStateObj.WriteByteArray(reconnectData._delta[i]._data, reconnectData._delta[i]._dataLength, 0);
}
}
}
len += initialLength + currentLength + 12 /* length fields (initial, current, total) */;
}
return len;
}