21#define RESIPROCATE_SUBSYSTEM Subsystem::REPRO
37BerkeleyDb::init(
const Data& dbPath,
const Data& dbName )
39 Data filePath(dbPath);
42 if ( !filePath.empty() )
53 DebugLog( <<
"No BerkeleyDb prefix specified - using default" );
61 InfoLog( <<
"Using BerkeleyDb prefixed with " << filePath );
68 mEnv =
new DbEnv(DB_CXX_NO_EXCEPTIONS);
70 ret = mEnv->open(0, DB_CREATE |
80 ErrLog( <<
"Could not open environment: " << db_strerror(ret));
84 mEnv->txn_checkpoint(0, 0, 0);
90 bool enableTransactions =
false;
92 bool secondaryIndex =
false;
93 Data secondaryFileName;
97 enableTransactions =
false;
104 Data fileName( filePath );
108 fileName +=
"_user";
break;
110 fileName +=
"_tlspeeridentity";
break;
112 fileName +=
"_route";
break;
114 fileName +=
"_acl";
break;
116 fileName +=
"_config";
break;
118 fileName +=
"_staticreg";
break;
120 fileName +=
"_filter";
break;
124 enableTransactions =
true;
126 secondaryIndex =
true;
138 secondaryFileName = fileName;
140 secondaryFileName +=
"_idx1.db";
143 mTableInfo[i].mDb =
new Db(mEnv, DB_CXX_NO_EXCEPTIONS);
146 DebugLog( <<
"About to open Berkeley DB: " << fileName );
147 ret = mTableInfo[i].mDb->open(0,
152 DB_CREATE | DB_THREAD | (enableTransactions ? DB_AUTO_COMMIT : 0),
154 DB_CREATE | DB_THREAD,
159 ErrLog( <<
"Could not open database " << fileName <<
": " << db_strerror(ret));
165 ret = mTableInfo[i].mDb->cursor(0, &mTableInfo[i].mCursor, 0);
168 ErrLog( <<
"Could not cursor on database " << fileName <<
": " << db_strerror(ret));
174 DebugLog( <<
"Opened Berkeley DB: " << fileName );
179 mTableInfo[i].mSecondaryDb =
new Db(mEnv, DB_CXX_NO_EXCEPTIONS);
182 ret = mTableInfo[i].mSecondaryDb->set_flags(DB_DUP);
185 ErrLog( <<
"Could not set database " << secondaryFileName <<
" to allow duplicates: " << db_strerror(ret));
190 DebugLog( <<
"About to open secondary Berkeley DB: " << secondaryFileName );
191 ret = mTableInfo[i].mSecondaryDb->open(0,
192 secondaryFileName.
c_str(),
196 DB_CREATE | DB_THREAD | (enableTransactions ? DB_AUTO_COMMIT : 0),
198 DB_CREATE | DB_THREAD,
203 ErrLog( <<
"Could not open secondary database " << secondaryFileName <<
": " << db_strerror(ret));
209 mTableInfo[i].mSecondaryDb->set_app_private(
this);
210 ret = mTableInfo[i].mDb->associate(0, mTableInfo[i].mSecondaryDb, &getSecondaryKeyCallback, 0 );
213 ErrLog( <<
"Could not associate secondary database " << secondaryFileName <<
": " << db_strerror(ret));
217 DebugLog( <<
"Opened secondary Berkeley DB: " << secondaryFileName );
219 ret = mTableInfo[i].mSecondaryDb->cursor(0, &mTableInfo[i].mSecondaryCursor, 0);
222 ErrLog( <<
"Could not secondary cursor on database " << secondaryFileName <<
": " << db_strerror(ret));
236 if(mTableInfo[i].mSecondaryCursor)
238 mTableInfo[i].mSecondaryCursor->close();
239 mTableInfo[i].mSecondaryCursor = 0;
242 if(mTableInfo[i].mCursor)
244 mTableInfo[i].mCursor->close();
245 mTableInfo[i].mCursor = 0;
248 if(mTableInfo[i].mTransaction)
250 dbRollbackTransaction((
Table)i);
254 if(mTableInfo[i].mSecondaryDb)
256 mTableInfo[i].mSecondaryDb->close(0);
257 delete mTableInfo[i].mSecondaryDb;
258 mTableInfo[i].mSecondaryDb = 0;
261 if(mTableInfo[i].mDb)
263 mTableInfo[i].mDb->close(0);
264 delete mTableInfo[i].mDb;
265 mTableInfo[i].mDb = 0;
270 mEnv->txn_checkpoint(0, 0, 0);
277BerkeleyDb::getSecondaryKeyCallback(Db *db,
const Dbt *pkey,
const Dbt *pdata, Dbt *skey)
285 if(bdb->mTableInfo[i].mSecondaryDb == db)
293 Data primaryKey(
Data::Share,
reinterpret_cast<const char*
>(pkey->get_data()), pkey->get_size());
294 Data primaryData(
Data::Share,
reinterpret_cast<const char*
>(pdata->get_data()), pdata->get_size());
296 unsigned int secondaryKeyLen;
297 int rc = bdb->
getSecondaryKey(table, primaryKey, primaryData, &secondaryKey, &secondaryKeyLen);
298 skey->set_data(secondaryKey);
299 skey->set_size(secondaryKeyLen);
305BerkeleyDb::dbWriteRecord(
const Table table,
309 Dbt key((
void*)pKey.
data(), (::u_int32_t)pKey.
size());
310 Dbt data((
void*)pData.
data(), (::u_int32_t)pData.
size());
314 ret = mTableInfo[table].mDb->put(mTableInfo[table].mTransaction, &key, &data, 0);
316 if(ret == 0 && mTableInfo[table].mTransaction == 0)
319 mTableInfo[table].mDb->sync(0);
320 if(mTableInfo[table].mSecondaryDb)
322 mTableInfo[table].mSecondaryDb->sync(0);
330BerkeleyDb::dbReadRecord(
const Table table,
334 Dbt key((
void*)pKey.
data(), (::u_int32_t)pKey.
size());
336 data.set_flags(DB_DBT_MALLOC);
341 ret = mTableInfo[table].mDb->get(mTableInfo[table].mTransaction, &key, &data, 0);
343 if (ret == DB_NOTFOUND)
348 free(data.get_data());
354 pData.
copy(
reinterpret_cast<const char*
>(data.get_data()), data.get_size());
357 free(data.get_data());
370BerkeleyDb::dbEraseRecord(
const Table table,
374 Dbt key((
void*) pKey.
data(), (::u_int32_t)pKey.
size());
376 Db* db = mTableInfo[table].mDb;
377 if(isSecondaryKey && mTableInfo[table].mSecondaryDb)
379 db = mTableInfo[table].mSecondaryDb;
382 db->del(mTableInfo[table].mTransaction, &key, 0);
383 if(mTableInfo[table].mTransaction == 0)
386 mTableInfo[table].mDb->sync(0);
387 if(mTableInfo[table].mSecondaryDb)
389 mTableInfo[table].mSecondaryDb->sync(0);
396BerkeleyDb::dbNextKey(
const Table table,
403 ret = mTableInfo[table].mCursor->get(&key, &data, first ? DB_FIRST : DB_NEXT);
404 if (ret == DB_NOTFOUND)
410 Data d(
Data::Share,
reinterpret_cast<const char*
>(key.get_data()), key.get_size());
416BerkeleyDb::dbNextRecord(
const Table table,
422 Dbt dbkey((
void*) key.
data(), (::u_int32_t)key.
size());
427 if(mTableInfo[table].mSecondaryCursor == 0)
434 unsigned int flags = 0;
437 flags = first ? DB_FIRST : DB_NEXT;
441 flags = first ? DB_SET : DB_NEXT_DUP;
451 ret = mTableInfo[table].mSecondaryCursor->get(&dbkey, &dbdata,
flags);
452 if (ret == DB_NOTFOUND)
457 data.
copy(
reinterpret_cast<const char*
>(dbdata.get_data()), dbdata.get_size());
463BerkeleyDb::dbBeginTransaction(
const Table table)
469 int ret = mTableInfo[table].mDb->get_env()->txn_begin(0 , &mTableInfo[table].mTransaction, 0);
472 ErrLog( <<
"Could not begin transaction: " << db_strerror(ret));
477 if(mTableInfo[table].mCursor)
479 mTableInfo[table].mCursor->close();
480 mTableInfo[table].mCursor = 0;
483 ret = mTableInfo[table].mDb->cursor(mTableInfo[table].mTransaction, &mTableInfo[table].mCursor, 0);
486 ErrLog( <<
"Could not open cursor for transaction: " << db_strerror(ret));
494BerkeleyDb::dbCommitTransaction(
const Table table)
502 if(mTableInfo[table].mCursor)
504 mTableInfo[table].mCursor->close();
505 mTableInfo[table].mCursor = 0;
508 int ret = mTableInfo[table].mTransaction->commit(0);
509 mTableInfo[table].mTransaction = 0;
512 ErrLog( <<
"Could not commit transaction: " << db_strerror(ret));
517 mTableInfo[table].mDb->cursor(0, &mTableInfo[table].mCursor, 0);
524BerkeleyDb::dbRollbackTransaction(
const Table table)
532 if(mTableInfo[table].mCursor)
534 mTableInfo[table].mCursor->close();
535 mTableInfo[table].mCursor = 0;
538 int ret = mTableInfo[table].mTransaction->abort();
539 mTableInfo[table].mTransaction = 0;
546 mTableInfo[table].mDb->cursor(0, &mTableInfo[table].mCursor, 0);
#define resip_assert(x)
This file needs to work for both C and C++ code.
static const struct nv flags[]
virtual int getSecondaryKey(const Table table, const Key &key, const resip::Data &data, void **secondaryKey, unsigned int *secondaryKeyLen)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
static const Data Empty
Constant that represents a zero-length data.
const char * c_str() const
Returns a null-terminated string representing.
@ Share
The Data instance will use the buffer in a read-only mode.
bool empty() const noexcept
Checks whether the Data is empty.
size_type size() const noexcept
Returns the number of bytes in this Data.
Data & copy(const char *buf, size_type length)
Functional equivalent of: *this = Data(buf, length) but avoids the intermediate allocation and free.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
This Class is used to implement a primitive form of RPC using loose XML formatting.
dcm! – add UnusedChecking(_enum) below;