// Serialize a key and OutstandingTransactionsValue value to an encoded string // The forceWrite parameter indicates whether to serialize to a string anyway even if there are no NACK RMs in the // OutstandingTransactionsValue. This is needed sometimes (such as in recovery) to indicate a transaction has // committed/aborted successfully and there are no remaining NACK RMs. private string SerializeToString(string key, OutstandingTransactionsValue value, bool forceWrite = false) { // Only serialize if forceWrite is specified or if the list of NACK RMs is not empty if (forceWrite || (value != null && value.nackRMList.Count > 0)) { // Write the key to the string System.Text.StringBuilder sb = new System.Text.StringBuilder(key); if (value != null && value.nackRMList != null) { // Write the transaction type to the string sb.Append("," + ((value.transactionType == OutstandingTransactionsValue.TransactionType.Commit) ? "0" : "1")); // Write the list of NACK RMs to the string foreach (string item in value.nackRMList) { sb.Append("," + item); } } return(sb.ToString()); } else { return(null); } }
// Serialize the key and CommittedTransactionValue value from an encoded string private bool SerializeFromString(string s, out string key, out OutstandingTransactionsValue value) { key = null; value = null; string[] tokens = s.Split(','); // Split the string into tokens using a delimiter if (tokens.Length == 0) { return(false); } key = tokens[0]; // The key is always the first token value = new OutstandingTransactionsValue(); // The transaction type is the 2nd token (if it exists) if (tokens.Length >= 2) { value.transactionType = (int.Parse(tokens[1]) == 0) ? OutstandingTransactionsValue.TransactionType.Commit : OutstandingTransactionsValue.TransactionType.Abort; } // The rest of the tokens (if they exist) is the list of RMs that have not acknowledge the commit/abort value.nackRMList = tokens.Skip(2).ToList <string>(); return(true); }
// Write a outstanding transaction entry to the file immediately public void UpdateAndFlush(string transactionId, OutstandingTransactionsValue value) { // If the list of NACK RMs is empty, the transaction has committed/aborted successfully // so remove it from the list of outstanding transactions if (value == null || value.nackRMList == null || value.nackRMList.Count == 0) { transactionList.Remove(transactionId); } // Otherwise, add/update the outstanding transaction list. else { transactionList[transactionId] = value; } // Append transaction information to file. If this is an existing transaction, it may // cause the file to have multiple occurrences of the same transaction ID. We will take // care of this in ReadFromFile() to make sure the last entry wins, this will avoid the need // to rewrite the whole file every time an existing transaction is updated. using (System.IO.StreamWriter sw = new StreamWriter(GetFilename(), true)) { sw.WriteLine(SerializeToString(transactionId, value, true)); } }