Compensator Class
.NET Framework 3.0
Represents the base class for all Compensating Resource Manager (CRM) Compensators.
Namespace: System.EnterpriseServices.CompensatingResourceManager
Assembly: System.EnterpriseServices (in system.enterpriseservices.dll)
Assembly: System.EnterpriseServices (in system.enterpriseservices.dll)
The user should extend from this object in order to write a custom transaction Compensator.
A Compensator must always have a public constructor; otherwise, the recovery engine cannot create it.
For more information, see How to: Create a Compensating Resource Manager (CRM).
The following code example demonstrates the use of this class.
// A CRM Compensator public class AccountCompensator : Compensator { private bool receivedPrepareRecord = false; public override void BeginPrepare () { // nothing to do } public override bool PrepareRecord (LogRecord log) { // Check the validity of the record. if (log == null) return(true); Object[] record = log.Record as Object[]; if (record == null) return(true); if (record.Length != 2) return(true); // The record is valid. receivedPrepareRecord = true; return(false); } public override bool EndPrepare () { // Allow the transaction to proceed onlyif we have received a prepare record. if (receivedPrepareRecord) { return(true); } else { return(false); } } public override void BeginCommit (bool commit) { // nothing to do } public override bool CommitRecord (LogRecord log) { // nothing to do return(false); } public override void EndCommit () { // nothing to do } public override void BeginAbort (bool abort) { // nothing to do } public override bool AbortRecord (LogRecord log) { // Check the validity of the record. if (log == null) return(true); Object[] record = log.Record as Object[]; if (record == null) return(true); if (record.Length != 2) return(true); // Extract old account data from the record. string filename = (string) record[0]; int balance = (int) record[1]; // Restore the old state of the account. AccountManager.WriteAccountBalance(filename, balance); return(false); } public override void EndAbort () { // nothing to do } }
// A CRM Compensator
public class AccountCompensator extends Compensator
{
private boolean receivedPrepareRecord = false;
public void BeginPrepare()
{
// nothing to do
} //BeginPrepare
public boolean PrepareRecord(LogRecord log)
{
// Check the validity of the record.
if (log == null) {
return true;
}
Object record[] = new Object[] { log.get_Record() };
if (record == null) {
return true;
}
if (record.get_Length() != 2) {
return true;
}
// The record is valid.
receivedPrepareRecord = true;
return false;
} //PrepareRecord
public boolean EndPrepare()
{
// Allow the transaction to proceed onlyif we have received
// a prepare record.
if (receivedPrepareRecord) {
return true;
}
else {
return false;
}
} //EndPrepare
public void BeginCommit(boolean commit)
{
// nothing to do
} //BeginCommit
public boolean CommitRecord(LogRecord log)
{
// nothing to do
return false;
} //CommitRecord
public void EndCommit()
{
// nothing to do
} //EndCommit
public void BeginAbort(boolean abort)
{
// nothing to do
} //BeginAbort
public boolean AbortRecord(LogRecord log)
{
// Check the validity of the record.
if (log == null) {
return true;
}
Object record[] = new Object[] { log.get_Record() };
if (record == null) {
return true;
}
if (record.get_Length() != 2) {
return true;
}
// Extract old account data from the record.
String fileName = (String)(record.get_Item(0));
int balance = System.Convert.ToInt32(record[1]);
// Restore the old state of the account.
AccountManager.WriteAccountBalance(fileName, balance);
return false;
} //AbortRecord
public void EndAbort()
{
// nothing to do
} //EndAbort
} //AccountCompensator
This compensator is used by the following worker class.
// A CRM Worker [Transaction] public class Account : ServicedComponent { // A data member for the account file name. private string filename; public string Filename { get { return(filename); } set { filename = value; } } // A boolean data member that determines whether to commit or abort the transaction. private bool commit; public bool AllowCommit { get { return(commit); } set { commit = value; } } // Debit the account, public void DebitAccount (int ammount) { // Create a new clerk using the AccountCompensator class. Clerk clerk = new Clerk(typeof(AccountCompensator), "An account transaction compensator", CompensatorOptions.AllPhases); // Create a record of previous account status, and deliver it to the clerk. int balance = AccountManager.ReadAccountBalance(filename); Object[] record = new Object[2]; record[0] = filename; record[1] = balance; clerk.WriteLogRecord(record); clerk.ForceLog(); // Perform the transaction balance -= ammount; AccountManager.WriteAccountBalance(filename, balance); // Commit or abort the transaction if (commit) { ContextUtil.SetComplete(); } else { ContextUtil.SetAbort(); } } }
// A CRM Worker
/** @attribute Transaction()
*/
public class Account extends ServicedComponent
{
// A data member for the account file name.
/** @property
*/
private String fileName;
public String get_fileName()
{
return fileName;
} //get_fileName
public void set_fileName(String value)
{
fileName = value;
} //set_fileName
// A boolean data member that determines whether to commit or
// abort the transaction.
private boolean commit;
/** @property
*/
public boolean get_AllowCommit()
{
return commit;
} //get_AllowCommit
/** @property
*/
public void set_AllowCommit(boolean value)
{
commit = value;
} //set_AllowCommit
// Debit the account,
public void DebitAccount(int ammount)
{
// Create a new clerk using the AccountCompensator class.
Clerk clerk = new Clerk(AccountCompensator.class.ToType(),
"An account transaction compensator",
CompensatorOptions.AllPhases);
// Create a record of previous account status, and deliver
// it to the clerk.
Console.WriteLine("filename = " + fileName);
int balance = AccountManager.ReadAccountBalance(fileName);
Object record[] = new Object[2];
record.set_Item(0, fileName);
record.set_Item(1,(Int32)balance);
clerk.WriteLogRecord(record);
clerk.ForceLog();
// Perform the transaction
balance -= ammount;
AccountManager.WriteAccountBalance(fileName, balance);
// Commit or abort the transaction
if (commit) {
ContextUtil.SetComplete();
}
else {
ContextUtil.SetAbort();
}
} //DebitAccount
} //Account
The following code example demonstrates a client that exercises this compensator and worker.
using System; public class CrmClient { public static void Main () { // Create a new account object. The object is created in a COM+ server application. Account account = new Account(); // Transactionally debit the account. try { account.Filename = System.IO.Path.GetFullPath("JohnDoe"); account.AllowCommit = true; account.DebitAccount(3); } finally { account.Dispose(); } } }
import System.*;
public class CrmClient
{
public static void main(String[] args)
{
// Create a new account object. The object is created in a COM+
// server application.
Account account = new Account();
// Transactionally debit the account.
try {
account.set_fileName(System.IO.Path.GetFullPath("JohnDoe"));
account.set_AllowCommit(true);
account.DebitAccount(3);
}
finally {
account.Dispose();
}
} //main
} //CrmClient
System.Object
System.MarshalByRefObject
System.ContextBoundObject
System.EnterpriseServices.ServicedComponent
System.EnterpriseServices.CompensatingResourceManager.Compensator
System.MarshalByRefObject
System.ContextBoundObject
System.EnterpriseServices.ServicedComponent
System.EnterpriseServices.CompensatingResourceManager.Compensator
Community Additions
ADD
Show: