Transaction Processing with c-treeDB C and C++
Our last newsletter outlined the advanced rollback and savepoint tranasaction processing features available with c-tree Plus. What if you're working with the c-treeDB programming interface? Does c-treeDB provide you with the same advanced data integrity that c-tree Plus is valued for?
YES! Transaction processing in c-treeDB is even easier to use than the c-tree ISAM and low-level features. Previous developers may easily overlook the power available to them with this powerful programming API. This c-tree How-To will point you in the right direction for putting transaction processing to work for you in your c-treeDB C and C++ applications.
You use c-treeDB to create tables under transaction control by specifying the create mode CTCREATE_TRNLOG or CTCREATE_PREIMG.
CTCREATE_TRNLOG creates files with full transaction processing capabilities. This allows you to take advantage of the automatic recovery feature. Transaction log files are generated to ensure the full data integrity should a system crash or other application failure occur. This gains your application both atomicity and recovery of operations.
CTCREATE_PREIMG allows operations to participate in transactions thereby acquiring atomicity. Applications can gain a performance boost over full transaction processing as no transaction log files are generated. However, this performance gain is at the expense of recoverability.
Note: You can not use both CTCREATE_TRNLOG and CTCREATE_PREIMG at the same time.
Using the c-treeDB C API, you can use the following code to create a table with TRNLOG enabled:
if (ctdbCreateTable(hTable, "mytable", CTCREATE_TRNLOG) != CTDBRET_OK
printf("ctdbCreateTable failed with error %d
", ctdbGetError(hTable));
You may use the same call, with CTCREATE_PREIMG mode to create a table with PreImage.
Using the c-treeDB C++ API, the example above looks like:
try
{
hTable.CreateTable("mytable", CTCREATE_TRNLOG);
}
catch (CTException &err)
{
printf("Error %d: %s
", err.GetErrorCode(), err.GetErrorMsg());
}
catch (...)
{
printf("Some other error
");
}
When a table is created with CTCREATE_TRNLOG or CTCREATE_PREIMG, all modifications to the table definition or table data must be done inside a transaction. Using the c-treeDB C API you start a transaction by calling the ctdbBegin() function. If there are no c-tree or c-treeDB errors since the transaction was started, you commit the transaction by calling the ctdbCommit() function. When there are errors, or if you wish to abort the transaction, you call the ctdbAbort() function to abort the current transaction.
Example using the c-treeDB C API:
CTDBRET AddNewRecord(CTHANDLE hRecord, pTEXT str)
{
CTDBRET eRet;
/* start a new transaction */
if ((eRet = ctdbBegin(hRecord)) != CTDBRET_OK)
{
printf("ctdbBegin failed with error %d
", eRet);
goto Exit;
}
/* clear the record buffer */
if ((eRet = ctdbClearRecord(hRecord)) != CTDBRET_OK)
{
printf("ctdbClearRecord failed with error %d
", eRet);
goto Exit;
}
/* set the string field */
if ((eRet = ctdbSetFieldAsString(hRecord, 0, "This is the first record")) != CTDBRET_OK)
{
printf("ctdbSetFieldAsString failed with error %d
", eRet);
goto Exit;
}
/* add the new record */
if ((eRet = ctdbWriteRecord(hRecord)) != CTDBRET_OK)
{
printf("ctdbWriteRecord failed with error %d
", eRet);
goto Exit;
}
/* if you get here, you can commit the transaction */
if ((eRet = ctdbCommit(hRecord)) != CTDBRET_OK)
{
printf("ctdbCommit failed with error %d
", eRet);
}
Exit:
/* check if we need to abort a transaciton */
if (eRet != CTDBRET_OK && ctdbIsTransActive(hRecord))
ctdbAbort(hRecord);
return eRet;
}
The functions ctdbBegin(), ctdbAbort(), ctdbCommit() and ctdbIsTransActive() receive a session handle as a parameter. This means you can pass any c-treeDB handle (database, table, record, index, field, segment, etc) to these functions and they will know how to extract the session handle associated with any other c-treeDB handle. Transactions are session wide.
The same example using the c-treeDB C++ API:
void AddNewRecord(CTRecord& hRecord, const CTString& str)
{
try
{
hRecord.Begin();
hRecord.ClearRecord();
hRecord.SetFieldAsString(0, str);
hRecord.Write();
hRecord.Commit();
}
catch (CTException &err)
{
if (hRecord.IsTransActive())
hRecord.Abort();
printf("Error %d: %s
", err.GetErrorCode(), err.GetErrorMsg());
}
catch (...)
{
if (hRecord.IsTransActive())
hRecord.Abort();
printf("Some other error
");
}
}
Again, methods Begin() , Commit() , Abort() and IsTransActive() are declared in the CTBase class, and this class is the base class for all c-treeDB C++ handle classes.
|