bool Freeze::ObjectStoreBase::insert(const Identity& ident, const ObjectRecord& rec, const TransactionIPtr& transaction) { DbTxn* tx = 0; if(transaction != 0) { tx = transaction->dbTxn(); if(tx == 0) { throw DatabaseException(__FILE__, __LINE__, "inactive transaction"); } } Key key; marshal(ident, key, _communicator, _encoding); Value value; marshal(rec, value, _communicator, _encoding, _keepStats); Dbt dbKey; Dbt dbValue; initializeInDbt(key, dbKey); initializeInDbt(value, dbValue); u_int32_t flags = DB_NOOVERWRITE; if(tx == 0) { flags |= DB_AUTO_COMMIT; } for(;;) { try { return _db->put(tx, &dbKey, &dbValue, flags) == 0; } catch(const DbDeadlockException& dx) { if(_evictor->deadlockWarning()) { Warning out(_communicator->getLogger()); out << "Deadlock in Freeze::ObjectStoreBase::insert while updating \"" << _evictor->filename() + "/" + _dbName << "\""; } if(tx != 0) { throw DeadlockException(__FILE__, __LINE__, dx.what(), transaction); } // // Otherwise, try again // } catch(const DbException& dx) { handleDbException(dx, __FILE__, __LINE__); } } }
bool Freeze::ObjectStoreBase::remove(const Identity& ident, const TransactionIPtr& transaction) { DbTxn* tx = 0; if(transaction != 0) { tx = transaction->dbTxn(); if(tx == 0) { throw DatabaseException(__FILE__, __LINE__, "inactive transaction"); } } Key key; marshal(ident, key, _communicator, _encoding); Dbt dbKey; initializeInDbt(key, dbKey); for(;;) { try { return _db->del(tx, &dbKey, tx != 0 ? 0 : DB_AUTO_COMMIT) == 0; } catch(const DbDeadlockException& dx) { if(_evictor->deadlockWarning()) { Warning out(_communicator->getLogger()); out << "Deadlock in Freeze::ObjectStoreBase::remove while updating \"" << _evictor->filename() + "/" + _dbName << "\""; } if(tx != 0) { throw DeadlockException(__FILE__, __LINE__, dx.what(), transaction); } // // Otherwise, try again // } catch(const DbException& dx) { handleDbException(dx, __FILE__, __LINE__); } } }
void Freeze::ObjectStoreBase::update(const Identity& ident, const ObjectRecord& rec, const TransactionIPtr& transaction) { if(transaction == 0) { throw DatabaseException(__FILE__, __LINE__, "no active transaction"); } DbTxn* txn = transaction->dbTxn(); if(txn == 0) { throw DatabaseException(__FILE__, __LINE__, "inactive transaction"); } Key key; marshal(ident, key, _communicator, _encoding); Value value; marshal(rec, value, _communicator, _encoding, _keepStats); Dbt dbKey; Dbt dbValue; initializeInDbt(key, dbKey); initializeInDbt(value, dbValue); u_int32_t flags = 0; try { _db->put(txn, &dbKey, &dbValue, flags); } catch(const DbDeadlockException& dx) { if(_evictor->deadlockWarning()) { Warning out(_communicator->getLogger()); out << "Deadlock in Freeze::ObjectStoreBase::update while updating \"" << _evictor->filename() + "/" + _dbName << "\""; } throw DeadlockException(__FILE__, __LINE__, dx.what(), transaction); } catch(const DbException& dx) { handleDbException(dx, __FILE__, __LINE__); } }
vector<Identity> Freeze::IndexI::untypedFindFirst(const Key& bytes, Int firstN) const { DeactivateController::Guard deactivateGuard(_store->evictor()->deactivateController()); Dbt dbKey; initializeInDbt(bytes, dbKey); #if (DB_VERSION_MAJOR <= 4) || (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR <= 1) // // When we have a custom-comparison function, Berkeley DB returns // the key on-disk (when it finds one). We disable this behavior: // (ref Oracle SR 5925672.992) // dbKey.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); #else // // In DB > 5.1 we can not set DB_DBT_PARTIAL in the key Dbt, // when using DB_SET, we must resize the Dbt key param to hold enought // space or Dbc::get fails with DB_BUFFER_SMALL. // dbKey.set_flags(DB_DBT_USERMEM); dbKey.set_ulen(static_cast<u_int32_t>(bytes.size())); #endif Key pkey(1024); Dbt pdbKey; initializeOutDbt(pkey, pdbKey); Dbt dbValue; dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); const Ice::CommunicatorPtr& communicator = _store->communicator(); const Ice::EncodingVersion& encoding = _store->encoding(); TransactionIPtr transaction = _store->evictor()->beforeQuery(); DbTxn* tx = transaction == 0 ? 0 : transaction->dbTxn(); vector<Identity> identities; try { for(;;) { Dbc* dbc = 0; identities.clear(); try { // // Move to the first record // _db->cursor(tx, &dbc, 0); u_int32_t flags = DB_SET; bool found; do { for(;;) { try { // // It is critical to set key size to key capacity before the // get, as a resize that increases the size inserts 0 // pkey.resize(pkey.capacity()); found = (dbc->pget(&dbKey, &pdbKey, &dbValue, flags) == 0); if(found) { pkey.resize(pdbKey.get_size()); Ice::Identity ident; ObjectStoreBase::unmarshal(ident, pkey, communicator, encoding); identities.push_back(ident); flags = DB_NEXT_DUP; } break; // for(;;) } catch(const DbDeadlockException&) { throw; } catch(const DbException& dx) { handleDbException(dx, pkey, pdbKey, __FILE__, __LINE__); } } } while((firstN <= 0 || identities.size() < static_cast<size_t>(firstN)) && found); Dbc* toClose = dbc; dbc = 0; toClose->close(); break; // for (;;) } catch(const DbDeadlockException&) { if(dbc != 0) { try { dbc->close(); } catch(const DbDeadlockException&) { if(tx != 0) { throw; } // Else ignored } } if(_store->evictor()->deadlockWarning()) { Warning out(_store->communicator()->getLogger()); out << "Deadlock in Freeze::IndexI::untypedFindFirst while searching \"" << _store->evictor()->filename() + "/" + _dbName << "\"; retrying ..."; } if(tx != 0) { throw; } // Else retry } catch(...) { if(dbc != 0) { try { dbc->close(); } catch(const DbDeadlockException&) { if(tx != 0) { throw; } // Else ignored } } throw; } } } catch(const DbDeadlockException& dx) { throw DeadlockException(__FILE__, __LINE__, dx.what(), transaction); } catch(const DbException& dx) { handleDbException(dx, __FILE__, __LINE__); } return identities; }
Int Freeze::IndexI::untypedCount(const Key& bytes) const { DeactivateController::Guard deactivateGuard(_store->evictor()->deactivateController()); Dbt dbKey; initializeInDbt(bytes, dbKey); #if (DB_VERSION_MAJOR <= 4) || (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR <= 1) // // When we have a custom-comparison function, Berkeley DB returns // the key on-disk (when it finds one). We disable this behavior: // (ref Oracle SR 5925672.992) // dbKey.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); #else // // In DB > 5.1 we can not set DB_DBT_PARTIAL in the key Dbt, // when using DB_SET, we must resize the Dbt key param to hold enought // space or Dbc::get fails with DB_BUFFER_SMALL. // dbKey.set_flags(DB_DBT_USERMEM); dbKey.set_ulen(static_cast<u_int32_t>(bytes.size())); #endif Dbt dbValue; dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); TransactionIPtr transaction = _store->evictor()->beforeQuery(); DbTxn* tx = transaction == 0 ? 0 : transaction->dbTxn(); Int result = 0; try { for(;;) { Dbc* dbc = 0; try { // // Move to the first record // _db->cursor(tx, &dbc, 0); bool found = (dbc->get(&dbKey, &dbValue, DB_SET) == 0); if(found) { db_recno_t count = 0; dbc->count(&count, 0); result = static_cast<Int>(count); } Dbc* toClose = dbc; dbc = 0; toClose->close(); break; // for (;;) } catch(const DbDeadlockException&) { if(dbc != 0) { try { dbc->close(); } catch(const DbDeadlockException&) { if(tx != 0) { throw; } // Else ignored } } if(_store->evictor()->deadlockWarning()) { Warning out(_store->communicator()->getLogger()); out << "Deadlock in Freeze::IndexI::untypedCount while searching \"" << _store->evictor()->filename() + "/" + _dbName << "\"; retrying ..."; } if(tx != 0) { throw; } // Else retry } catch(...) { if(dbc != 0) { try { dbc->close(); } catch(const DbDeadlockException&) { if(tx != 0) { throw; } // Else ignored } } throw; } } } catch(const DbDeadlockException& dx) { throw DeadlockException(__FILE__, __LINE__, dx.what(), transaction); } catch(const DbException& dx) { DatabaseException ex(__FILE__, __LINE__); ex.message = dx.what(); throw ex; } return result; }
bool Freeze::ObjectStoreBase::load(const Identity& ident, const TransactionIPtr& transaction, ObjectRecord& rec) { if(transaction == 0) { throw DatabaseException(__FILE__, __LINE__, "no active transaction"); } DbTxn* txn = transaction->dbTxn(); if(txn == 0) { throw DatabaseException(__FILE__, __LINE__, "inactive transaction"); } Dbt dbKey; KeyMarshaler km(ident, _communicator, _encoding); km.getDbt(dbKey); const size_t defaultValueSize = 4096; Value value(defaultValueSize); Dbt dbValue; initializeOutDbt(value, dbValue); for(;;) { try { int rs =_db->get(txn, &dbKey, &dbValue, 0); if(rs == DB_NOTFOUND) { return false; } else if(rs != 0) { assert(0); throw DatabaseException(__FILE__, __LINE__); } break; // for(;;) } catch(const DbDeadlockException& dx) { if(_evictor->deadlockWarning()) { Warning out(_communicator->getLogger()); out << "Deadlock in Freeze::ObjectStoreBase::load while searching \"" << _evictor->filename() + "/" + _dbName << "\""; } throw DeadlockException(__FILE__, __LINE__, dx.what(), transaction); } catch(const DbException& dx) { handleDbException(dx, value, dbValue, __FILE__, __LINE__); } } unmarshal(rec, value, _communicator, _encoding, _keepStats); _evictor->initialize(ident, _facet, rec.servant); return true; }
bool Freeze::ObjectStoreBase::dbHasObject(const Identity& ident, const TransactionIPtr& transaction) const { DbTxn* tx = 0; if(transaction != 0) { tx = transaction->dbTxn(); if(tx == 0) { throw DatabaseException(__FILE__, __LINE__, "inactive transaction"); } } Dbt dbKey; KeyMarshaler km(ident, _communicator, _encoding); km.getDbt(dbKey); // // Keep 0 length since we're not interested in the data // Dbt dbValue; dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); for(;;) { try { int err = _db->get(tx, &dbKey, &dbValue, 0); if(err == 0) { return true; } else if(err == DB_NOTFOUND) { return false; } else { assert(0); throw DatabaseException(__FILE__, __LINE__); } } catch(const DbDeadlockException& dx) { if(_evictor->deadlockWarning()) { Warning out(_communicator->getLogger()); out << "Deadlock in Freeze::ObjectStoreBase::dbHasObject while searching \"" << _evictor->filename() + "/" + _dbName << "\"; retrying ..."; } if(tx != 0) { throw DeadlockException(__FILE__, __LINE__, dx.what(), transaction); } // Else, try again } catch(const DbException& dx) { DatabaseException ex(__FILE__, __LINE__); ex.message = dx.what(); throw ex; } } }