Transactional Cursors
Prev | Chapter 3. Transaction Basics | Next

## Transactional Cursors

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 <stdio.h>
    #include <stdlib.h>

    #include "db.h"

    int
    main(void)
    {
        DBT key, data;
        DBC *cursorp;
        DB_TXN *txn = NULL;
        int ret, c_ret;
        char *replacementString = "new string";

        ...
        /* environment and db handle creation omitted */
        ...

        /* Get the txn handle */
        txn = NULL;
        ret = envp->txn_begin(envp, NULL, &txn, 0);
        if (ret != 0) {
            envp->err(envp, ret, "Transaction begin failed.");
            goto err;
        }

        /* Get the cursor, supply the txn handle at that time */
        ret = dbp->cursor(dbp, txn, &cursorp, 0);
        if (ret != 0) {
            envp->err(envp, ret, "Cursor open failed.");
            txn->abort(txn);
            goto err;
        }

        /*
         * Now use the cursor. Note that we do not supply any txn handles to these
         * methods.
         */
        /* Prepare the DBTs */
        memset(&key, 0, sizeof(DBT));
        memset(&data, 0, sizeof(DBT));
        while (cursor->c_get(&key, &data, DB_NEXT) == 0) {
            data->data = (void *)replacementString;
            data->size = (strlen(replacementString) + 1) * sizeof(char);
            c_ret = cursor->c_put(cursor, &key, &data, DB_CURRENT);
            if (c_ret != 0) {
                /* abort the transaction and goto error */
                envp->err(envp, ret, "Cursor put failed.");
                cursorp->c_close(cursorp);
                cursorp = NULL;
                txn->abort(txn);
                goto err;
            }
        }

        /*
         * Commit the transaction. Note that the transaction handle
         * can no longer be used.
         */
        ret = cursorp->c_close(cursorp);
        if (ret != 0) {
            envp->err(envp, ret, "Cursor close failed.");
            txn->abort(txn);
            goto err;
        }
        ret = txn->commit(txn, 0);
        if (ret != 0) {
            envp->err(envp, ret, "Transaction commit failed.");
            goto err;
        }

    err:
        /* Close the cursor (if the handle is not NULL)
         * and perform whatever other cleanup is required */

        /* Close the database */

        /* Close the environment */

        ...

        if (c_ret != 0)
            ret = c_ret;

        return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
    }

Prev | Up | Next
Nested Transactions | Home | Secondary Indices with Transaction Applications