Transaction Processing Process
The transaction processing process is divided into several steps: 1. transaction assembly; 2. lock the corresponding data set; 3. notification data collection backup; 4. perform each atomic operation in sequence. mark the successful bits of each atomic operation; 6 store the results returned to the result pool
The transaction assembly on the client needs to be completed by itself, because the tasks submitted by each client are different, and the server performs unified processing. The code for transaction assembly is as follows:
Boolean success = false; # region assembles a transaction and returns the result transactionentity = new transactionentity (); // prepare the submitted parameter hashtable resulthashtable = new hashtable (); // prepare the returned parameter transactionentity. transactionid. add ("14"); // number 21: reserve a hotel transactionentity. transactionparam. add (new object [] {locationstring, deleremoteservice}); // The transactionentity parameter. transactionid. add ("19"); // 19: Add Reservation Information transactionentity. tra Nsactionparam. add (new object [] {custnamestring, 2, reservationremoteservice}); // parameter queuetransactionservice. inttransactionid + = 1; // transaction No. Int inttransactionid = queuetransactionservice. inttransactionid; queuetransactionservice. globalcontrolservice = globalcontrolservice; // assign the new transaction number queuetransactionservice. addentity (inttransactionid. tostring (), transactionentity); // stores the transaction to be processed in the hashtable queue, waiting for the program to automatically process W Hile (true) // check the result queue cyclically and find the transaction result {If (queuetransactionservice. transactionresult. containskey (inttransactionid. tostring () // you can find the data you need in the result list and jump out of the infinite waiting for break;} resulthashtable = (hashtable) queuetransactionservice. transactionresult [inttransactionid. tostring ()]; // accept the result success = (Boolean) resulthashtable ["14"]; If (success = true) {MessageBox. show ("Hotel Reservation successful, Location:" + locationstring);} else {messageb Ox. Show ("hotel reservation failed! ") ;}# Endregion
The transaction Assembly first needs to instantiate the transaction entity class (transactionentiy) and result acceptance class (hashtable ). In the next step, you need to fill in transactionentiy. The whole transactionentiy has only three parameters, and the two parameters need to be filled here. Only whether each operation is successful must be filled in the client and processed for detection. After adding the transaction sequence number, what the client needs to do is to throw the transaction into the transaction pool and wait for the program to run. At this time, the client needs to wait in the result pool and find its own results. The following figure shows an example:
Transaction pool and result pool
Before executing this transaction, You need to lock all the data sets involved in it, that is, to modify the value of its hascontrol flag. When locking the data set, the data set is also notified to be backed up so that the transaction cannot be restored to the original state when the transaction is canceled. The code snippet is as follows:
/// <Summary> /// execute a transaction and store the result in hashtable. This process is automatically locked, back up the data set /// </Summary> /// <Param name = "tansactionhashtable"> the transaction to be executed, including the number of each operation and the required parameters </param> /// <returns> returned results, store the results obtained by each operation in hashtable </returns> Public hashtable processtransaction () {for (INT I = 0; I <transactionentity. transactionid. count; I ++) {// lock the required data set lockbyid (transactionentity. transactionid [I]); // starts the transaction and notifies the relevant data collection server to handle beginbyid (transactionentity. transactionid [I], Xid );}
Cyclically traverses each operation in the transaction, finds its number, executes the corresponding operation according to the number, and places the result in the corresponding collection.
Hashtable transactionresult = new hashtable (); For (INT I = 0; I <transactionentity. transactionid. count; I ++) {try {// store the method number and result returned by the method in hashtable and return it to the client object objresulttmp = getdatabyid (transactionentity. transactionid [I], transactionentity. transactionparam [I]); If (objresulttmp = NULL) // If the returned value is null, it indicates that no data is obtained or the operation fails, and transactionentity is executed. success. add (false); else transactionentity. success. add (true); transactionresult. add (transactionentity. transactionid [I], objresulttmp);} catch (exception e) {transactionentity. success. add (false );}}
The execution of a transaction may not be successful. If an operation fails, it means that the entire transaction must be rolled back to the initial state. Therefore, after each operation is completed, the flag is assigned a value. The failure is marked as follows: 1. If the returned result is null, the execution fails; 2. If an error occurs during the execution, it is in the catch area. Both cases are considered as operation failures.
Int flag = 1; // mark as, 1 as all succeeded, 0 as failed // check whether the execution is not successful through the loop (INT I = 0; I <transactionentity. success. count; I ++) {If (transactionentity. success [I]. equals (false) // If an operation fails, the entire transaction is rolled back. The specific operation is to restore the corresponding data set {flag = 0; // failed break ;}}
Whether the transaction is successful or fails, you must provide an explanation for the dataset. At the end of the transaction execution, you need to determine whether the transaction needs to be committed or rolled back.
// Determine whether to perform rollback if (flag = 0) // to this point, failed, rollback for (INT I = 0; I <transactionentity. transactionid. count; I ++) {rollbackbyid (transactionentity. transactionid [I], Xid);} else for (INT I = 0; I <transactionentity. transactionid. count; I ++) {// This indicates that the entire transaction is successfully executed commitebyid (transactionentity. transactionid [I], Xid);} // The execution is complete. Unlock for (INT I = 0; I <transactionentity. transactionid. count; I ++) {unlockbyid (transactionentity. transactionid [I]);}
In the end, you need to release the resources used for rollback and execution to ensure that other transactions can run normally.