Auto Commit

While transactions are frequently used to provide atomicity to multiple container operations, it is sometimes necessary to perform a single container operation under the control of a transaction. Rather than force you to obtain a transaction, perform the single write operation, and then either commit or abort the transaction, you can automatically group this sequence of events using auto commit.

To use auto commit:

  1. Open your environment and your containers so that they support transactions. See Enabling Transactions for details.

    Note that frequently auto commit is used for the environment or container open. To use auto commit for either your environment or container open, specify DB_AUTO_COMMIT to the or method. If you specify auto commit for the environment open, then you do not need to also specify auto commit for the container open.

  2. Do not provide a transactional handle to the method that is performing the container write operation.

Note

Never have more than one active transaction in your thread at a time. This is especially a problem if you mix an explicit transaction with another operation that uses auto commit. Doing so can result in undetectable deadlocks.

For example, the following uses auto commit to perform the container write operation:

#include "DbXml.hpp"
...

using namespace DbXml;
int main(void)
{
    u_int32_t env_flags = DB_CREATE     |  // If the environment does not
                                           // exist, create it.
                          DB_INIT_LOCK  |  // Initialize locking
                          DB_INIT_LOG   |  // Initialize logging
                          DB_INIT_MPOOL |  // Initialize the cache
                          DB_INIT_TXN;     // Initialize transactions

    DB_ENV *myEnv = 0;
    XmlManager *myManager = NULL;
    char *envHome = "/export1/testEnv";
    int dberr;

    dberr = db_env_create(&myEnv, 0);
    if (dberr) {
        std::cout << "Unable to create environment: " <<
            db_strerror(dberr) << std::endl;
        if (myEnv)
            myEnv->close(myEnv, 0);
        return (EXIT_FAILURE);
    }

    myEnv->open(myEnv, envHome, env_flags, 0);
    myManager = new XmlManager(myEnv, 0);

    try {
        XmlContainerConfig cconfig;
        cconfig.setAllowCreate(true);    // If the container does not
                                         // exist, create it.
        cconfig.setTransactional(true);  // Enable transactions.

        std::string containerName = "myContainer.dbxml";
        XmlContainer myContainer =
            myManager->openContainer(containerName, cconfig);

    } catch(DbException &e) {
        std::cerr << "Error opening container: "
                  << e.what() << std::endl;
        return (EXIT_FAILURE);
    } catch(std::exception &e) {
        std::cerr << "Error opening container: "
                  << e.what() << std::endl;
        return (EXIT_FAILURE);
    }

    // File to open
    std::string file1 = "doc1.xml";

    try {
        // Need an update context for the put.
        XmlUpdateContext theContext = myManager.createUpdateContext();

        // Get the input stream.
        XmlInputStream *theStream =
            myManager.createLocalFileInputStream(file1);

        // Put the document. Because the container was opened to 
        // support transactions, this write is performed using 
        // auto commit.
        myContainer.putDocument(file1,       // The document's name
                                theStream,   // The actual document.
                                theContext,  // The update context
                                             // (required).
                                0);          // Put flags.

    } catch(XmlException &e) {
        std::cerr << "Error in write: "
                  << e.what() << std::endl;
    }

    try {
        if (myManager != NULL) {
            delete myManager;
        }
        myEnv.close(0);
    } catch(DbException &e) {
        std::cerr << "Error closing database environment: "
                << envHome << std::endl;
        std::cerr << e.what() << std::endl;
        return (EXIT_FAILURE);
    } catch(std::exception &e) {
        std::cerr << "Error closing database environment: "
                << envHome << std::endl;
        std::cerr << e.what() << std::endl;
        return (EXIT_FAILURE);
    }
    return (EXIT_SUCCESS);
}