To enable transactions for your environment, you must initialize the transactional subsystem. Note that doing this also initializes the logging subsystem. In addition, you must initialize the memory pool (in-memory cache). Frequently, but not always, you will also initialize the locking subsystem. For example:
Notice in the following example that you first create the environment handle, and then you provide the handle to the XmlManager constructor. You do this because you cannot use transactions with the XmlManager instance's default internal environment.
#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 std::string envHome("/export1/testEnv"); DbEnv myEnv(0); XmlManager *myManager = NULL; try { myEnv.open(envHome.c_str(), env_flags, 0); myManager = new XmlManager(&myEnv, 0); } catch(DbException &e) { std::cerr << "Error opening environment: " << envHome << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } catch(std::exception &e) { std::cerr << "Error opening environment: " << envHome << " or opening XmlManager." << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } try { if (myManager != NULL) { delete myManager; } myEnv.close(0); } catch(DbException &e) { std::cerr << "Error closing environment: " << envHome << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } catch(std::exception &e) { std::cerr << "Error closing environment: " << envHome << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } return (EXIT_SUCCESS); }
You then create and/or open your containers as normal. The only difference is that you must pass the DBXML_TRANSACTIONAL flag to the openContainer() or createContainer() method. For example:
#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 std::string envHome("/export1/testEnv"); DbEnv myEnv(0); XmlManager *myManager = NULL; try { myEnv.open(envHome.c_str(), env_flags, 0); myManager = new XmlManager(&myEnv, 0); u_int32_t containerFlags = DB_CREATE | // If the container does not exist, // create it. DBXML_TRANSACTIONAL; // Enable transactions. std::string containerName = "myContainer.dbxml"; XmlContainer myContainer = myManager->openContainer(containerName, containerFlags); } catch(DbException &e) { std::cerr << "Error opening environment: " << envHome << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } catch(std::exception &e) { std::cerr << "Error opening environment: " << envHome << " or opening XmlManager or XmlContainer." << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } try { if (myManager != NULL) { delete myManager; } myEnv.close(0); } catch(DbException &e) { std::cerr << "Error closing environment: " << envHome << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } catch(std::exception &e) { std::cerr << "Error closing environment: " << envHome << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } return (EXIT_SUCCESS); }
It is possible to use Berkeley DB databases along side of BDB XML containers. When you do this, you will typically use both the databases and the containers from within the same environment so that you can combine operations to both using transactions.
There is no difference between opening a Berkeley DB database in an environment that uses containers and opening a database in an environment that does not use containers (see the Berkeley DB Getting Started with Transaction Processing guide for details on how to do this). You simply share the same environment handle between the two when you open the database(s) and container(s). For example:
#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 u_int32_t db_flags = DB_CREATE | DB_AUTO_COMMIT; Db *dbp = NULL; const char *file_name = "mydb.db"; std::string envHome("/export1/testEnv"); DbEnv myEnv(0); XmlManager *myManager = NULL; try { myEnv.open(envHome.c_str(), env_flags, 0); dbp = new Db(&myEnv, 0); dbp->open(NULL, // Txn pointer file_name, // File name NULL, // Logical db name DB_BTREE, // Database type (using btree) db_flags, // Open flags 0); // File mode. Using defaults myManager = new XmlManager(&myEnv, 0); u_int32_t containerFlags = DB_CREATE | // If the container does not exist, // create it. DBXML_TRANSACTIONAL; // Enable transactions. std::string containerName = "myContainer.dbxml"; XmlContainer myContainer = myManager->openContainer(containerName, containerFlags); } catch(DbException &e) { std::cerr << "Error opening database environment: " << envHome << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } catch(std::exception &e) { std::cerr << "Error opening database environment: " << envHome << " or opening XmlManager or XmlContainer." << std::endl; std::cerr << e.what() << std::endl; return (EXIT_FAILURE); } try { if (dbp != NULL) { dbp->close(dbp, 0); } if (myManager != NULL) { delete myManager; } myEnv.close(0); } catch(DbException &e) { std::cerr << "Error closing database and 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); }
Never close a database that has active transactions. Make sure all transactions are resolved (either committed or aborted) before closing the database.