1 // Author: Bruce Allen 2 // Created: 2/25/2013 3 // 4 // The software provided here is released by the Naval Postgraduate 5 // School, an agency of the U.S. Department of Navy. The software 6 // bears no warranty, either expressed or implied. NPS does not assume 7 // legal liability nor responsibility for a User's use of the software 8 // or the results of such use. 9 // 10 // Please note that within the United States, copyright protection, 11 // under Section 105 of the United States Code, Title 17, is not 12 // available for any work of the United States Government and/or for 13 // any works created by United States Government employees. User 14 // acknowledges that this software contains work which was created by 15 // NPS government employees and is therefore in the public domain and 16 // not subject to copyright. 17 // 18 // Released into the public domain on February 25, 2013 by Bruce Allen. 19 20 /** 21 * \file 22 * Provides a working context for accessing a LMDB DB. 23 * 24 * A context must be opened then closed exactly once. 25 */ 26 27 #ifndef LMDB_CONTEXT_HPP 28 #define LMDB_CONTEXT_HPP 29 #include "lmdb.h" 30 31 namespace hashdb { 32 class lmdb_context_t { 33 private: 34 MDB_env* env; 35 unsigned int txn_flags; // example MDB_RDONLY 36 unsigned int dbi_flags; // example MDB_DUPSORT 37 int state; 38 39 // do not allow copy or assignment 40 lmdb_context_t(const lmdb_context_t&); 41 lmdb_context_t& operator=(const lmdb_context_t&); 42 43 public: 44 MDB_txn* txn; 45 MDB_dbi dbi; 46 MDB_cursor* cursor; 47 MDB_val key; 48 MDB_val data; 49 lmdb_context_t(MDB_env * p_env,bool is_writable,bool is_duplicates)50 lmdb_context_t(MDB_env* p_env, bool is_writable, bool is_duplicates) : 51 env(p_env), txn_flags(0), dbi_flags(0), 52 state(0), txn(0), dbi(0), cursor(0), key(), data() { 53 54 // set flags based on bool inputs 55 if (is_writable) { 56 dbi_flags |= MDB_CREATE; // DBI 57 } else { 58 txn_flags |= MDB_RDONLY; // TXN 59 } 60 if (is_duplicates) { 61 dbi_flags |= MDB_DUPSORT; // DBI 62 } 63 } 64 ~lmdb_context_t()65 ~lmdb_context_t() { 66 if (state != 2) { 67 std::cerr << "Error: LMDB context not 2: state " << state << "\n"; 68 assert(0); 69 } 70 } 71 open()72 void open() { 73 if (state++ != 0) { 74 std::cerr << "Error: LMDB context not 0: state " << state << "\n"; 75 assert(0); 76 } 77 78 // create txn object 79 int rc = mdb_txn_begin(env, NULL, txn_flags, &txn); 80 if (rc != 0) { 81 std::cerr << "LMDB txn error: " << mdb_strerror(rc) << "\n"; 82 assert(0); 83 } 84 85 // create the database handle integer 86 rc = mdb_dbi_open(txn, NULL, dbi_flags, &dbi); 87 if (rc != 0) { 88 std::cerr << "LMDB dbi error: " << mdb_strerror(rc) << "\n"; 89 assert(0); 90 } 91 92 // create a cursor object to use with this txn 93 rc = mdb_cursor_open(txn, dbi, &cursor); 94 if (rc != 0) { 95 std::cerr << "LMDB cursor error: " << mdb_strerror(rc) << "\n"; 96 assert(0); 97 } 98 } 99 close()100 void close() { 101 if (state++ != 1) { 102 assert(0); 103 } 104 105 // free cursor 106 mdb_cursor_close(cursor); 107 108 // do not close dbi handle, why not close it? 109 110 // free txn object 111 if ((txn_flags & MDB_RDONLY) != MDB_RDONLY) { 112 113 // RW 114 int rc = mdb_txn_commit(txn); 115 if (rc != 0) { 116 std::cerr << "LMDB txn commit error: " << mdb_strerror(rc) << "\n"; 117 assert(0); 118 } 119 120 } else { 121 // RO 122 mdb_txn_abort(txn); 123 } 124 } 125 }; 126 } 127 128 #endif 129 130