You can transaction-protect your cursor operations by specifying a transaction handle at the time that you create your cursor. Beyond that, you do not ever provide a transaction handle directly to a cursor method.
Note that if you transaction-protect a cursor, then you must make sure that the cursor is closed before you either commit or abort the transaction. For example:
#include "db_cxx.h"
...
int main(void)
{
// Environment and database opens omitted
...
DbTxn *txn = NULL;
Dbc *cursorp = NULL;
try {
Dbt key, data;
key.set_data(keystr);
key.set_size((strlen(keystr) + 1) * sizeof(char));
key.set_data(datastr);
key.set_size((strlen(datastr) + 1) * sizeof(char));
DbTxn *txn = NULL;
myEnv.txn_begin(NULL, &txn, 0);
try {
// Get our cursor. Note that we pass the transaction handle here.
db.cursor(txn, &cursorp, 0);
// Perform our operations. Note that we do not pass a transaction
// handle here.
char *replacementString = "new string";
while (cursor->get(&key, &data, DB_NEXT) == 0) {
data.set_data(void *)replacementString);
data.set_size((strlen(replacementString) + 1) * sizeof(char));
cursor->put(&key, &data, DB_CURRENT);
}
// We're done. Commit the transaction.
cursor->close();
txn->commit(0);
} catch (DbException &e) {
std::cerr << "Error in transaction: "
<< e.what() << std::endl;
cursor->close();
txn->abort();
}
} catch(DbException &e) {
std::cerr << "Error opening database and environment: "
<< file_name << ", "
<< envHome << std::endl;
std::cerr << e.what() << std::endl;
}
return (EXIT_SUCCESS);
}