void NormalRepNode::masterOperations() { XmlManager& mgr = getManager(); XmlContainer& cont = getContainer(); XmlUpdateContext uc = mgr.createUpdateContext(); int num = documentNum; XmlTransaction txn = mgr.createTransaction(); try { ostringstream o; printMsg("is putting document."); for (int i = 0; i < num && (docNum_+i) < maxDocumentNum; i++) { ostringstream o; o << "<node>" << "<name>" << getEnvHome() << "</name>" << "<doc_id>" << i << "</doc_id>" << "</node>"; // Put documents cont.putDocument(txn, "", o.str(), uc, DBXML_GEN_NAME); } docNum_ = cont.getNumDocuments(txn); txn.commit(); printMsg("put document done."); } catch (XmlException &xe) { txn.abort(); // Deal with permission denied exception if (xe.getExceptionCode() == XmlException::DATABASE_ERROR && xe.getDbErrno() == EACCES) { yield(); } else throwIfUnExpected(xe); } }
void NormalRepNode::clientOperations() { XmlTransaction txn = getManager().createTransaction(); try { // Save the new node state. docNum_ = getContainer().getNumDocuments(txn); txn.commit(); } catch (XmlException &xe) { txn.abort(); throwIfUnExpected(xe); } }
void RepNode::openContainer() { // reopening a container is forbidden. if (!cont_.isNull()) throwException("Attempt to re-open a container."); XmlContainerConfig conf; // wait for being elected as a Master or start up done(as a client). while (!(isMaster() || appData_.isStartupDone())) yield(); if (isMaster()) conf.setAllowCreate(true); XmlTransaction txn; while (true) { try { txn = mgr_->createTransaction(); cont_ = mgr_->openContainer(txn, containerName_, conf); txn.commit(); return; /* * One thing to watch out for is a case where the databases * you are trying to open do not yet exist. This can happen * for replicas where the databases are being opened * read-only. If this happens, ENOENT is returned by the * open() call. */ } catch (XmlException &xe) { ostringstream o; XmlException::ExceptionCode ec = xe.getExceptionCode(); if (ec == XmlException::DATABASE_ERROR) { int dbErr = xe.getDbErrno(); if (dbErr != ENOENT && dbErr != DB_REP_LOCKOUT) { o << envHome_ << ":" << xe.what() << endl << "DB_ERRNO:" << dbErr << endl; throwException(o.str()); } } else if (ec != XmlException::CONTAINER_NOT_FOUND) { o << envHome_ << ":" << xe.what() << endl << "ExceptionCode :" << ec << endl; throwException(o.str()); } yield(); } } }
void DeleteDocumentCommand::execute(Args &args, Environment &env) { if(args.size() != 2) { throw CommandException("Wrong number of arguments"); } env.testContainer(); if(env.txn()) { XmlTransaction myTxn = env.childTransaction(); env.container()->deleteDocument(myTxn, args[1], env.uc()); myTxn.commit(); } else { env.container()->deleteDocument(args[1], env.uc()); } if(env.verbose()) cout << "Document deleted, name = " << args[1] << endl; }
void DeleteIndexCommand::execute(Args &args, Environment &env) { if(args.size() != 2 && args.size() != 4) { throw CommandException("Wrong number of arguments"); } env.testContainer(); if(env.verbose()) { if(args.size() == 2) cout << "Deleting default index type: " << args[1] << endl; else cout << "Deleting index type: " << args[3] << " from node: {" << args[1] << "}:" << args[2] << endl; } if(env.txn()) { XmlTransaction myTxn = env.childTransaction(); if(args.size() == 2) env.container()->deleteDefaultIndex(myTxn, args[1], env.uc()); else env.container()->deleteIndex(myTxn, args[1], args[2], args[3], env.uc()); myTxn.commit(); } else { if(args.size() == 2) env.container()->deleteDefaultIndex(args[1], env.uc()); else env.container()->deleteIndex(args[1], args[2], args[3], env.uc()); } }
int main(int argc, char **argv) { std::string path2DbEnv; std::string theContainer = "namespaceExampleData.dbxml"; for ( int i=1; i<argc; i++ ) { if ( argv[i][0] == '-' ) { switch(argv[i][1]) { case 'h': path2DbEnv = argv[++i]; break; default: usage(); } } } if (! path2DbEnv.length() ) usage(); // Berkeley DB environment flags u_int32_t envFlags = DB_RECOVER|DB_CREATE|DB_INIT_MPOOL| DB_INIT_LOCK|DB_INIT_TXN|DB_INIT_LOG; // Berkeley DB cache size (64 MB). The default is quite small u_int32_t envCacheSize = 64*1024*1024; // Create and open a Berkeley DB Transactional Environment. int dberr; DB_ENV *dbEnv = 0; dberr = db_env_create(&dbEnv, 0); if (dberr == 0) { dbEnv->set_cachesize(dbEnv, 0, envCacheSize, 1); dberr = dbEnv->open(dbEnv, path2DbEnv.c_str(), envFlags, 0); } if (dberr) { std::cout << "Unable to create environment handle due to the following error: " << db_strerror(dberr) << std::endl; if (dbEnv) dbEnv->close(dbEnv, 0); return -1; } //Have the XmlManager adopt the db environment XmlManager mgr(dbEnv, DBXML_ADOPT_DBENV); //Configure the container to use transactions XmlContainerConfig config; config.setTransactional(true); //Open a container in the db environment XmlContainer container = mgr.openContainer(theContainer, config); //create a transaction XmlTransaction txn = mgr.createTransaction(); //create a context and declare the namespaces XmlQueryContext context = mgr.createQueryContext(); context.setNamespace( "fruits", "http://groceryItem.dbxml/fruits"); context.setNamespace( "vegetables", "http://groceryItem.dbxml/vegetables"); context.setNamespace( "desserts", "http://groceryItem.dbxml/desserts"); //Query for documents by their document names. doContextQuery( txn, mgr, container.getName(), "/*[dbxml:metadata('dbxml:name')='ZuluNut.xml']", context ); doContextQuery( txn, mgr, container.getName(), "/*[dbxml:metadata('dbxml:name')='TrifleOrange.xml']", context ); doContextQuery( txn, mgr, container.getName(), "/*[dbxml:metadata('dbxml:name')='TriCountyProduce.xml']", context ); //Get the document from the container using the document name doGetDocument(txn, container, "ZuluNut.xml"); doGetDocument(txn, container, "TrifleOrange.xml"); doGetDocument(txn, container, "TriCountyProduce.xml"); //commit the transaction txn.commit(); return 0; }
int main(int argc, char **argv) { // This program uses a named container, which will apear // on disk std::string containerName = "people.dbxml"; std::string content = "<people><person><name>joe</name></person><person><name>mary</name></person></people>"; std::string docName = "people"; // Note that the query uses a variable, which must be set // in the query context std::string queryString = "collection('people.dbxml')/people/person[name=$name]"; std::string environmentDir = "."; // Berkeley DB environment flags u_int32_t envFlags = DB_RECOVER|DB_CREATE|DB_INIT_MPOOL| DB_INIT_LOCK|DB_INIT_TXN|DB_INIT_LOG; // Berkeley DB cache size (25 MB). The default is quite small u_int32_t envCacheSize = 25*1024*1024; // argument parsing should really use getopt(), but // avoid it for platform-independence if (argc == 3) { if (std::string(argv[1]) != std::string("-h")) usage(argv[0]); environmentDir = argv[2]; } else if (argc != 1) usage(argv[0]); // Create and open a Berkeley DB Transactional Environment. int dberr; DB_ENV *dbEnv = 0; dberr = db_env_create(&dbEnv, 0); if (dberr == 0) { dbEnv->set_cachesize(dbEnv, 0, envCacheSize, 1); dbEnv->set_errcall(dbEnv, errcall); // set error callback dbEnv->set_lk_detect(dbEnv, DB_LOCK_DEFAULT); // handle deadlocks dberr = dbEnv->open(dbEnv, environmentDir.c_str(), envFlags, 0); } if (dberr) { std::cout << "Unable to create environment handle due to the following error: " << db_strerror(dberr) << std::endl; if (dbEnv) dbEnv->close(dbEnv, 0); return -1; } try { // All BDB XML programs require an XmlManager instance. // Create it from the DbEnv XmlManager mgr(dbEnv, DBXML_ADOPT_DBENV); // Because the container will exist on disk, remove it // first if it exists if (mgr.existsContainer(containerName)) mgr.removeContainer(containerName); /* Create a container that is transactional. The container * type is NodeContainer, which is the default container type, * and the index is on nodes, which is the default for a * NodeContainer container. XmlContainerConfig can be used * to set the container type and index type. */ XmlContainerConfig config; config.setTransactional(true); XmlContainer cont = mgr.createContainer( containerName, config); // All Container modification operations need XmlUpdateContext XmlUpdateContext uc = mgr.createUpdateContext(); // The following putDocument call will auto-transact // and will abort/cleanup if the operation deadlocks or // otherwise fails cont.putDocument(docName, content, uc); // Querying requires an XmlQueryContext XmlQueryContext qc = mgr.createQueryContext(); // Add a variable to the query context, used by the query qc.setVariableValue("name", "mary"); // Use try/catch and while to handle deadlock/retry int retry = 0; while (retry < 5) { // hard-code 5 retries // Create a new transaction for the query XmlTransaction txn = mgr.createTransaction(); try { // o Note the passing of txn to both methods // o Often the XmlQueryExpression object will be created and // saved for reuse in order to amortize the cost of parsing a query XmlQueryExpression expr = mgr.prepare(txn, queryString, qc); XmlResults res = expr.execute(txn, qc); // Note use of XmlQueryExpression::getQuery() and // XmlResults::size() std::cout << "The query, '" << expr.getQuery() << "' returned " << (unsigned int)res.size() << " result(s)" << std::endl; // Process results -- just print them XmlValue value; std::cout << "Result: " << std::endl; while (res.next(value)) { std::cout << "\t" << value.asString() << std::endl; } // done with the transaction txn.commit(); break; } catch (XmlException &x) { txn.abort(); // unconditional if ((x.getExceptionCode() == XmlException::DATABASE_ERROR) && (x.getDbErrno() == DB_LOCK_DEADLOCK)) { ++retry; continue; // try again } throw; // re-throw -- not deadlock } } // In C++, resources are released as objects go out // of scope. } catch (XmlException &xe) { std::cout << "XmlException: " << xe.what() << std::endl; } return 0; }
void AddDocumentCommand::execute(Args &args, Environment &env) { if ((args.size() < 3) || (args.size() > 4)){ throw CommandException("Wrong number of arguments"); } env.testContainer(); env.deleteResults(); if ((args.size() == 4) && (args[3] == "q")) { if(env.txn()) { XmlTransaction myTxn = env.childTransaction(); env.results() = new XmlResults( env.db().query(myTxn, args[2], env.context())); XmlValue value; while(env.results()->next(value)) { string v = value.asString(); string name = env.container()-> putDocument(myTxn, args[1], v, env.uc(), DBXML_GEN_NAME); if(env.verbose()) cout << "Document added, name = " << name << endl; } myTxn.commit(); } else { env.results() = new XmlResults(env.db().query(args[2], env.context())); XmlValue value; while(env.results()->next(value)) { string v = value.asString(); string name = env.container()-> putDocument(args[1], v, env.uc(), DBXML_GEN_NAME); if(env.verbose()) cout << "Document added, name = " << name << endl; } } } else { // by string or by file bool byString = true; if (args.size() == 4 && args[3] == "f") byString = false; XmlDocument doc = env.db().createDocument(); doc.setName(args[1]); if (byString) doc.setContent(args[2]); else { XmlInputStream *is = env.db().createLocalFileInputStream(args[2]); doc.setContentAsXmlInputStream(is); } if(env.txn()) { XmlTransaction myTxn = env.childTransaction(); env.container()->putDocument(myTxn, doc, env.uc()); myTxn.commit(); } else { env.container()->putDocument(doc, env.uc()); } // put doc content in last results XmlResults res = env.db().createResults(); res.add(XmlValue(doc)); env.results() = new XmlResults(res); if(env.verbose()) cout << "Document added, name = " << args[1] << endl; } }
int main(int argc, char **argv) { std::string path2DbEnv; std::string theContainer = "simpleExampleData.dbxml"; for ( int i=1; i<argc; i++ ) { if ( argv[i][0] == '-' ) { switch(argv[i][1]) { case 'h': path2DbEnv = argv[++i]; break; default: usage(); } } } if (! path2DbEnv.length() ) usage(); // Berkeley DB environment flags u_int32_t envFlags = DB_RECOVER|DB_CREATE|DB_INIT_MPOOL| DB_INIT_LOCK|DB_INIT_TXN|DB_INIT_LOG; // Berkeley DB cache size (64 MB). The default is quite small u_int32_t envCacheSize = 64*1024*1024; // Create and open a Berkeley DB Transactional Environment. int dberr; DB_ENV *dbEnv = 0; dberr = db_env_create(&dbEnv, 0); if (dberr == 0) { dbEnv->set_cachesize(dbEnv, 0, envCacheSize, 1); dberr = dbEnv->open(dbEnv, path2DbEnv.c_str(), envFlags, 0); } if (dberr) { std::cout << "Unable to create environment handle due to the following error: " << db_strerror(dberr) << std::endl; if (dbEnv) dbEnv->close(dbEnv, 0); return -1; } //Have the XmlManager adopt the db environment XmlManager db(dbEnv, DBXML_ADOPT_DBENV); //Configure the container to use transactions XmlContainerConfig config; config.setTransactional(true); //Open a container in the db environment XmlContainer container = db.openContainer(theContainer, config); // Get an XmlUpdateContext. Useful from a performance perspective. XmlUpdateContext updateContext = db.createUpdateContext(); //Get a transaction XmlTransaction txn = db.createTransaction(); std::string document1 = "<aDoc><title>doc1</title><color>green</color></aDoc>"; std::string document2 = "<aDoc><title>doc2</title><color>yellow</color></aDoc>"; //Add the documents XmlDocument myXMLDoc = db.createDocument(); /* Set the XmlDocument to the relevant string and then put it into the container. * Using the flag DBXML_GEN_NAME means that a generated name will be assigned * to the document if it does not have one. An exception will be thrown if * a document is inserted without a name or the DBXML_GEN_NAME flag. */ myXMLDoc.setContent( document1 ); container.putDocument(txn, myXMLDoc, updateContext, DBXML_GEN_NAME); //do it again for the second document myXMLDoc.setContent( document2 ); container.putDocument(txn, myXMLDoc, updateContext, DBXML_GEN_NAME); //Normally we would use a try/catch block to trap any exceptions. // In the catch, we should call txn->abort() to avoid leaving the // database in an indeterminate state in the event of an error. // However, this simple example avoids error handling so as to // highlite basic concepts, so that step if omitted here as well. //Commit the writes. This causes the container write operations // to be saved to the container. txn.commit(); return 0; }
int main(int argc, char **argv) { std::string path2DbEnv; std::string theContainer = "namespaceExampleData.dbxml"; for ( int i=1; i<argc; i++ ) { if ( argv[i][0] == '-' ) { switch(argv[i][1]) { case 'h': path2DbEnv = argv[++i]; break; default: usage(); } } } if (! path2DbEnv.length() ) usage(); // Berkeley DB environment flags u_int32_t envFlags = DB_RECOVER|DB_CREATE|DB_INIT_MPOOL| DB_INIT_LOCK|DB_INIT_TXN|DB_INIT_LOG; // Berkeley DB cache size (64 MB). The default is quite small u_int32_t envCacheSize = 64*1024*1024; // Create and open a Berkeley DB Transactional Environment. int dberr; DB_ENV *dbEnv = 0; dberr = db_env_create(&dbEnv, 0); if (dberr == 0) { dbEnv->set_cachesize(dbEnv, 0, envCacheSize, 1); dberr = dbEnv->open(dbEnv, path2DbEnv.c_str(), envFlags, 0); } if (dberr) { std::cout << "Unable to create environment handle due to the following error: " << db_strerror(dberr) << std::endl; if (dbEnv) dbEnv->close(dbEnv, 0); return -1; } //Have the XmlManager adopt the db environment XmlManager db(dbEnv, DBXML_ADOPT_DBENV); //Configure the container to use transactions XmlContainerConfig config; config.setTransactional(true); XmlContainer container = db.openContainer(theContainer, config); //Get a transaction XmlTransaction txn = db.createTransaction(); XmlUpdateContext uc = db.createUpdateContext(); //Add an string equality index for the "product" element node. addIndex( container, "", "product", "node-element-equality-string", txn, uc ); //Add an edge presence index for the product node addIndex( container, "", "product", "edge-element-presence", txn, uc ); //commit the index adds txn.commit(); return 0; }
int main(int argc, char **argv) { std::string path2DbEnv; std::string theContainer = "simpleExampleData.dbxml"; for ( int i=1; i<argc; i++ ) { if ( argv[i][0] == '-' ) { switch(argv[i][1]) { case 'h': path2DbEnv = argv[++i]; break; default: usage(); } } } if (! path2DbEnv.length() ) usage(); // Berkeley DB environment flags u_int32_t envFlags = DB_RECOVER|DB_CREATE|DB_INIT_MPOOL| DB_INIT_LOCK|DB_INIT_TXN|DB_INIT_LOG; // Berkeley DB cache size (64 MB). The default is quite small u_int32_t envCacheSize = 64*1024*1024; // Create and open a Berkeley DB Transactional Environment. int dberr; DB_ENV *dbEnv = 0; dberr = db_env_create(&dbEnv, 0); if (dberr == 0) { dbEnv->set_cachesize(dbEnv, 0, envCacheSize, 1); dberr = dbEnv->open(dbEnv, path2DbEnv.c_str(), envFlags, 0); } if (dberr) { std::cout << "Unable to create environment handle due to the following error: " << db_strerror(dberr) << std::endl; if (dbEnv) dbEnv->close(dbEnv, 0); return -1; } //Have the XmlManager adopt the db environment XmlManager db(dbEnv, DBXML_ADOPT_DBENV); //Configure the container to use transactions XmlContainerConfig config; config.setTransactional(true); //Open a container in the db environment XmlContainer container = db.openContainer(theContainer, config); //Create a transaction XmlTransaction txn = db.createTransaction(); //perform the queries //find all the Vendor documents in the database doQuery( txn, db, container, "/vendor" ); //find all the vendors that are wholesale shops doQuery( txn, db, container, "/vendor[@type=\"wholesale\"]"); //find the product document for "Lemon Grass" doQuery( txn, db, container, "/product/item[.=\"Lemon Grass\"]"); //find all the products where the price is less than or equal to 0.11 doQuery( txn, db, container, "/product/inventory[price<=0.11]"); //find all the vegetables where the price is less than or equal to 0.11 doQuery( txn, db, container, "/product[inventory/price<=0.11 and category=\"vegetables\"]"); //commit the transaction txn.commit(); return 0; }