|
reSIProcate/repro
9694
|
#include <BerkeleyDb.hxx>


Classes | |
| class | TableInfo |
Public Member Functions | |
| BerkeleyDb () | |
| BerkeleyDb (const resip::Data &dbPath, const resip::Data &dbName=resip::Data::Empty) | |
| virtual | ~BerkeleyDb () |
| virtual bool | isSane () |
Private Member Functions | |
| void | init (const resip::Data &dbPath, const resip::Data &dbName) |
| virtual bool | dbWriteRecord (const Table table, const resip::Data &key, const resip::Data &data) |
| virtual bool | dbReadRecord (const Table table, const resip::Data &key, resip::Data &data) const |
| return false if not found | |
| virtual void | dbEraseRecord (const Table table, const resip::Data &key, bool isSecondaryKey=false) |
| virtual resip::Data | dbNextKey (const Table table, bool first=true) |
| virtual bool | dbNextRecord (const Table table, const resip::Data &key, resip::Data &data, bool forUpdate, bool first=false) |
| virtual bool | dbBeginTransaction (const Table table) |
| virtual bool | dbCommitTransaction (const Table table) |
| virtual bool | dbRollbackTransaction (const Table table) |
Static Private Member Functions | |
| static int | getSecondaryKeyCallback (Db *db, const Dbt *pkey, const Dbt *pdata, Dbt *skey) |
Private Attributes | |
| DbEnv * | mEnv |
| TableInfo | mTableInfo [MaxTable] |
| bool | mSane |
Definition at line 26 of file BerkeleyDb.hxx.
| BerkeleyDb::BerkeleyDb | ( | ) |
Definition at line 24 of file BerkeleyDb.cxx.
{
init(Data::Empty, Data::Empty);
}
| BerkeleyDb::BerkeleyDb | ( | const resip::Data & | dbPath, |
| const resip::Data & | dbName = resip::Data::Empty |
||
| ) |
Definition at line 30 of file BerkeleyDb.cxx.
{
init(dbPath, dbName);
}
| BerkeleyDb::~BerkeleyDb | ( | ) | [virtual] |
Definition at line 224 of file BerkeleyDb.cxx.
{
for (int i=0;i<MaxTable;i++)
{
if(mTableInfo[i].mSecondaryCursor)
{
mTableInfo[i].mSecondaryCursor->close();
mTableInfo[i].mSecondaryCursor = 0;
}
if(mTableInfo[i].mCursor)
{
mTableInfo[i].mCursor->close();
mTableInfo[i].mCursor = 0;
}
if(mTableInfo[i].mTransaction)
{
dbRollbackTransaction((Table)i);
}
// Secondary DB should be closed before primary
if(mTableInfo[i].mSecondaryDb)
{
mTableInfo[i].mSecondaryDb->close(0);
delete mTableInfo[i].mSecondaryDb;
mTableInfo[i].mSecondaryDb = 0;
}
if(mTableInfo[i].mDb)
{
mTableInfo[i].mDb->close(0);
delete mTableInfo[i].mDb;
mTableInfo[i].mDb = 0;
}
}
if(mEnv)
{
mEnv->txn_checkpoint(0, 0, 0); // Note: a checkpoint is run when this last is created and when it is destroyed
delete mEnv;
}
}
| bool BerkeleyDb::dbBeginTransaction | ( | const Table | table | ) | [private, virtual] |
Implements repro::AbstractDb.
Definition at line 455 of file BerkeleyDb.cxx.
{
#ifdef USE_DBENV
// For now - we support transactions on the primary table only
assert(mDb);
assert(mTableInfo[table].mTransaction == 0);
int ret = mTableInfo[table].mDb->get_env()->txn_begin(0 /* parent trans*/, &mTableInfo[table].mTransaction, 0);
if(ret != 0)
{
ErrLog( <<"Could not begin transaction: " << db_strerror(ret));
return false;
}
// Open new Cursors - since cursors used in a transaction must be opened and closed within the transation
if(mTableInfo[table].mCursor)
{
mTableInfo[table].mCursor->close();
mTableInfo[table].mCursor = 0;
}
ret = mTableInfo[table].mDb->cursor(mTableInfo[table].mTransaction, &mTableInfo[table].mCursor, 0);
if(ret != 0)
{
ErrLog( <<"Could not open cursor for transaction: " << db_strerror(ret));
}
#endif
return true;
}
| bool BerkeleyDb::dbCommitTransaction | ( | const Table | table | ) | [private, virtual] |
Implements repro::AbstractDb.
Definition at line 486 of file BerkeleyDb.cxx.
{
bool success = true;
#ifdef USE_DBENV
assert(mDb);
assert(mTableInfo[table].mTransaction);
// Close the cursor - since cursors used in a transaction must be opened and closed within the transation
if(mTableInfo[table].mCursor)
{
mTableInfo[table].mCursor->close();
mTableInfo[table].mCursor = 0;
}
int ret = mTableInfo[table].mTransaction->commit(0);
mTableInfo[table].mTransaction = 0;
if(ret != 0)
{
ErrLog( <<"Could not commit transaction: " << db_strerror(ret));
success = false;
}
// Reopen a cursor for general use
mTableInfo[table].mDb->cursor(0, &mTableInfo[table].mCursor, 0);
#endif
return success;
}
| void BerkeleyDb::dbEraseRecord | ( | const Table | table, |
| const resip::Data & | key, | ||
| bool | isSecondaryKey = false |
||
| ) | [private, virtual] |
Implements repro::AbstractDb.
Definition at line 362 of file BerkeleyDb.cxx.
{
Dbt key((void*) pKey.data(), (::u_int32_t)pKey.size());
Db* db = mTableInfo[table].mDb;
if(isSecondaryKey && mTableInfo[table].mSecondaryDb)
{
db = mTableInfo[table].mSecondaryDb;
}
assert(db);
db->del(mTableInfo[table].mTransaction, &key, 0);
if(mTableInfo[table].mTransaction == 0)
{
// If we are in a transaction, then it will sync on commit
mTableInfo[table].mDb->sync(0);
if(mTableInfo[table].mSecondaryDb)
{
mTableInfo[table].mSecondaryDb->sync(0);
}
}
}
| resip::Data BerkeleyDb::dbNextKey | ( | const Table | table, |
| bool | first = true |
||
| ) | [private, virtual] |
Implements repro::AbstractDb.
Definition at line 388 of file BerkeleyDb.cxx.
{
Dbt key, data;
int ret;
assert(mTableInfo[table].mDb);
ret = mTableInfo[table].mCursor->get(&key, &data, first ? DB_FIRST : DB_NEXT);
if (ret == DB_NOTFOUND)
{
return Data::Empty;
}
assert(ret == 0);
Data d(Data::Share, reinterpret_cast<const char*>(key.get_data()), key.get_size());
return d;
}
| bool BerkeleyDb::dbNextRecord | ( | const Table | table, |
| const resip::Data & | key, | ||
| resip::Data & | data, | ||
| bool | forUpdate, | ||
| bool | first = false |
||
| ) | [private, virtual] |
Implements repro::AbstractDb.
Definition at line 408 of file BerkeleyDb.cxx.
{
Dbt dbkey((void*) key.data(), (::u_int32_t)key.size());
Dbt dbdata;
int ret;
assert(mTableInfo[table].mSecondaryCursor);
if(mTableInfo[table].mSecondaryCursor == 0)
{
// Iterating across multiple records with a common key is only
// supported on Seconday databases where duplicate keys exist
return false;
}
unsigned int flags = 0;
if(key.empty())
{
flags = first ? DB_FIRST : DB_NEXT;
}
else
{
flags = first ? DB_SET : DB_NEXT_DUP;
}
#ifdef USE_DBENV
if(forUpdate)
{
flags |= DB_RMW;
}
#endif
ret = mTableInfo[table].mSecondaryCursor->get(&dbkey, &dbdata, flags);
if (ret == DB_NOTFOUND)
{
return false;
}
assert(ret == 0);
data.copy(reinterpret_cast<const char*>(dbdata.get_data()), dbdata.get_size());
return true;
}
| bool BerkeleyDb::dbReadRecord | ( | const Table | table, |
| const resip::Data & | key, | ||
| resip::Data & | data | ||
| ) | const [private, virtual] |
return false if not found
Implements repro::AbstractDb.
Definition at line 322 of file BerkeleyDb.cxx.
{
Dbt key((void*)pKey.data(), (::u_int32_t)pKey.size());
Dbt data;
data.set_flags(DB_DBT_MALLOC); // required for DB_THREAD flag use
int ret;
assert(mTableInfo[table].mDb);
ret = mTableInfo[table].mDb->get(mTableInfo[table].mTransaction, &key, &data, 0);
if (ret == DB_NOTFOUND)
{
// key not found
if (data.get_data())
{
free(data.get_data());
}
return false;
}
assert(ret != DB_KEYEMPTY);
assert(ret == 0);
pData.copy(reinterpret_cast<const char*>(data.get_data()), data.get_size());
if (data.get_data())
{
free(data.get_data());
}
if(pData.empty())
{
// this should never happen
return false;
}
return true;
}
| bool BerkeleyDb::dbRollbackTransaction | ( | const Table | table | ) | [private, virtual] |
Implements repro::AbstractDb.
Definition at line 516 of file BerkeleyDb.cxx.
{
bool success = true;
#ifdef USE_DBENV
assert(mDb);
assert(mTableInfo[table].mTransaction);
// Close the cursor - since cursors used in a transaction must be opened and closed within the transation
if(mTableInfo[table].mCursor)
{
mTableInfo[table].mCursor->close();
mTableInfo[table].mCursor = 0;
}
int ret = mTableInfo[table].mTransaction->abort();
mTableInfo[table].mTransaction = 0;
if(ret != 0)
{
success = false;
}
// Reopen a cursor for general use
mTableInfo[table].mDb->cursor(0, &mTableInfo[table].mCursor, 0);
#endif
return success;
}
| bool BerkeleyDb::dbWriteRecord | ( | const Table | table, |
| const resip::Data & | key, | ||
| const resip::Data & | data | ||
| ) | [private, virtual] |
Implements repro::AbstractDb.
Definition at line 297 of file BerkeleyDb.cxx.
{
Dbt key((void*)pKey.data(), (::u_int32_t)pKey.size());
Dbt data((void*)pData.data(), (::u_int32_t)pData.size());
int ret;
assert(mTableInfo[table].mDb);
ret = mTableInfo[table].mDb->put(mTableInfo[table].mTransaction, &key, &data, 0);
if(ret == 0 && mTableInfo[table].mTransaction == 0)
{
// If we are in a transaction, then it will sync on commit
mTableInfo[table].mDb->sync(0);
if(mTableInfo[table].mSecondaryDb)
{
mTableInfo[table].mSecondaryDb->sync(0);
}
}
return ret == 0;
}
| int BerkeleyDb::getSecondaryKeyCallback | ( | Db * | db, |
| const Dbt * | pkey, | ||
| const Dbt * | pdata, | ||
| Dbt * | skey | ||
| ) | [static, private] |
Definition at line 269 of file BerkeleyDb.cxx.
{
BerkeleyDb* bdb = (BerkeleyDb*)db->get_app_private();
// Find associated table using db pointer
Table table = MaxTable;
for (int i=MaxTable-1; i >= 0; i--) // search backwards, since tables at the end have the secondary indexes
{
if(bdb->mTableInfo[i].mSecondaryDb == db)
{
table = (Table)i;
break;
}
}
assert(table != MaxTable);
Data primaryKey(Data::Share, reinterpret_cast<const char*>(pkey->get_data()), pkey->get_size());
Data primaryData(Data::Share, reinterpret_cast<const char*>(pdata->get_data()), pdata->get_size());
void* secondaryKey;
unsigned int secondaryKeyLen;
int rc = bdb->getSecondaryKey(table, primaryKey, primaryData, &secondaryKey, &secondaryKeyLen);
skey->set_data(secondaryKey);
skey->set_size(secondaryKeyLen);
return rc;
}
| void BerkeleyDb::init | ( | const resip::Data & | dbPath, |
| const resip::Data & | dbName | ||
| ) | [private] |
Definition at line 37 of file BerkeleyDb.cxx.
{
Data filePath(dbPath);
// An empty path is how you specify the current working directory as a path
if ( !filePath.empty() )
{
#ifdef WIN32
filePath += '\\';
#else
filePath += '/';
#endif
}
if ( dbName.empty() )
{
DebugLog( << "No BerkeleyDb prefix specified - using default" );
filePath += "repro";
}
else
{
filePath += dbName;
}
InfoLog( << "Using BerkeleyDb prefixed with " << filePath );
mSane = true;
// Create Environment
int ret;
#ifdef USE_DBENV
mEnv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
assert(mEnv);
ret = mEnv->open(0, DB_CREATE | // If the env does not exist, then create it
DB_INIT_LOCK | // Initialize Locking (needed for transactions)
DB_INIT_LOG | // Initialize Logging (needed for transactions)
DB_INIT_MPOOL | // Initialize the cache (needed for transactions)
DB_INIT_TXN | // Initialize transactions
DB_RECOVER | // Run normal recovery
DB_THREAD, // Free-thread the env handle
0 /* mode */);
if(ret != 0)
{
ErrLog( <<"Could not open environment: " << db_strerror(ret));
mSane = false;
return;
}
mEnv->txn_checkpoint(0, 0, 0); // Note: a checkpoint is run when this last is created and when it is destroyed
#else
mEnv = 0;
#endif
bool enableTransactions = false;
bool secondaryIndex = false;
Data secondaryFileName;
for (int i=0;i<MaxTable;i++)
{
enableTransactions = false;
// if the line bellow seems wrong, you need to check which version
// of db you have - it is likely an very out of date version
// still trying to figure this out so email fluffy if you have
// problems and include your version the DB_VERSION_STRING found
// in your db4/db.h file.
Data fileName( filePath );
switch (i)
{
case UserTable:
fileName += "_user"; break;
case RouteTable:
fileName += "_route"; break;
case AclTable:
fileName += "_acl"; break;
case ConfigTable:
fileName += "_config"; break;
case StaticRegTable:
fileName += "_staticreg"; break;
case FilterTable:
fileName += "_filter"; break;
case SiloTable:
fileName += "_silo";
enableTransactions = true;
secondaryIndex = true;
break;
default:
assert(0);
}
if(!secondaryIndex)
{
fileName += ".db";
}
else
{
secondaryFileName = fileName;
fileName += ".db";
secondaryFileName += "_idx1.db";
}
mTableInfo[i].mDb = new Db(mEnv, DB_CXX_NO_EXCEPTIONS);
assert(mTableInfo[i].mDb);
DebugLog( << "About to open Berkeley DB: " << fileName );
ret = mTableInfo[i].mDb->open(0,
fileName.c_str(),
0,
DB_BTREE,
#ifdef USE_DBENV
DB_CREATE | DB_THREAD | (enableTransactions ? DB_AUTO_COMMIT : 0),
#else
DB_CREATE | DB_THREAD,
#endif
0);
if(ret != 0)
{
ErrLog( <<"Could not open database " << fileName << ": " << db_strerror(ret));
mSane = false;
return;
}
// Open a cursor on the database
ret = mTableInfo[i].mDb->cursor(0, &mTableInfo[i].mCursor, 0);
if(ret != 0)
{
ErrLog( <<"Could not cursor on database " << fileName << ": " << db_strerror(ret));
mSane = false;
return;
}
assert(mTableInfo[i].mCursor);
DebugLog( << "Opened Berkeley DB: " << fileName );
if(secondaryIndex)
{
mTableInfo[i].mSecondaryDb = new Db(mEnv, DB_CXX_NO_EXCEPTIONS);
assert(mTableInfo[i].mSecondaryDb);
ret = mTableInfo[i].mSecondaryDb->set_flags(DB_DUP);
if(ret!=0)
{
ErrLog( <<"Could not set database " << secondaryFileName << " to allow duplicates: " << db_strerror(ret));
mSane = false;
return;
}
DebugLog( << "About to open secondary Berkeley DB: " << secondaryFileName );
ret = mTableInfo[i].mSecondaryDb->open(0,
secondaryFileName.c_str(),
0,
DB_BTREE,
#ifdef USE_DBENV
DB_CREATE | DB_THREAD | (enableTransactions ? DB_AUTO_COMMIT : 0),
#else
DB_CREATE | DB_THREAD,
#endif
0);
if(ret != 0)
{
ErrLog( <<"Could not open secondary database " << secondaryFileName << ": " << db_strerror(ret));
mSane = false;
return;
}
// Associate Secondary Database with Primary
mTableInfo[i].mSecondaryDb->set_app_private(this); // retrievable from callback so we can have access to this BerkeleyDb instance
ret = mTableInfo[i].mDb->associate(0, mTableInfo[i].mSecondaryDb, &getSecondaryKeyCallback, 0 /* flags */);
if(ret != 0)
{
ErrLog( <<"Could not associate secondary database " << secondaryFileName << ": " << db_strerror(ret));
mSane = false;
return;
}
DebugLog( << "Opened secondary Berkeley DB: " << secondaryFileName );
ret = mTableInfo[i].mSecondaryDb->cursor(0, &mTableInfo[i].mSecondaryCursor, 0);
if(ret != 0)
{
ErrLog( <<"Could not secondary cursor on database " << secondaryFileName << ": " << db_strerror(ret));
mSane = false;
return;
}
assert(mTableInfo[i].mSecondaryCursor);
}
}
}
| virtual bool repro::BerkeleyDb::isSane | ( | ) | [inline, virtual] |
DbEnv* repro::BerkeleyDb::mEnv [private] |
Definition at line 51 of file BerkeleyDb.hxx.
bool repro::BerkeleyDb::mSane [private] |
Definition at line 54 of file BerkeleyDb.hxx.
TableInfo repro::BerkeleyDb::mTableInfo[MaxTable] [private] |
Definition at line 52 of file BerkeleyDb.hxx.
1.7.5.1