diff options
author | Bernard Normier <bernard@zeroc.com> | 2005-11-08 00:13:52 +0000 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2005-11-08 00:13:52 +0000 |
commit | 20c342c1c5f35fbe60565dee7fb81ca2baf04e5b (patch) | |
tree | 199faf2102026478de9a1e55f6fff271591e7b98 /cpp/src/Freeze/MapI.cpp | |
parent | fixed bi-dir/shutdown deadlock (diff) | |
download | ice-20c342c1c5f35fbe60565dee7fb81ca2baf04e5b.tar.bz2 ice-20c342c1c5f35fbe60565dee7fb81ca2baf04e5b.tar.xz ice-20c342c1c5f35fbe60565dee7fb81ca2baf04e5b.zip |
Implemented enhancement 415 (Freeze Map compare functors)
Diffstat (limited to 'cpp/src/Freeze/MapI.cpp')
-rw-r--r-- | cpp/src/Freeze/MapI.cpp | 287 |
1 files changed, 273 insertions, 14 deletions
diff --git a/cpp/src/Freeze/MapI.cpp b/cpp/src/Freeze/MapI.cpp index f9473110012..065a48c1fa0 100644 --- a/cpp/src/Freeze/MapI.cpp +++ b/cpp/src/Freeze/MapI.cpp @@ -27,7 +27,10 @@ Freeze::MapIndexBase::~MapIndexBase() { } -Freeze::MapIndexBase::MapIndexBase(const string& name) : +Freeze::MapIndexBase::MapIndexBase( + const string& name, + bool enabled) : + KeyCompareBase(enabled), _name(name), _impl(0), _map(0) @@ -41,9 +44,21 @@ MapIndexBase::name() const } IteratorHelper* -Freeze::MapIndexBase::untypedFind(const Key& k, bool ro) const +Freeze::MapIndexBase::untypedFind(const Key& k, bool ro, bool onlyDups) const { - return _impl->untypedFind(k, ro, *_map); + return _impl->untypedFind(k, ro, *_map, onlyDups); +} + +IteratorHelper* +Freeze::MapIndexBase::untypedLowerBound(const Key& k, bool ro) const +{ + return _impl->untypedLowerBound(k, ro, *_map); +} + +IteratorHelper* +Freeze::MapIndexBase::untypedUpperBound(const Key& k, bool ro) const +{ + return _impl->untypedUpperBound(k, ro, *_map); } int @@ -53,6 +68,19 @@ Freeze::MapIndexBase::untypedCount(const Key& k) const } // +// KeyCompareBase +// +Freeze::KeyCompareBase::KeyCompareBase(bool enabled) : + _enabled(enabled) +{} + +bool +Freeze::KeyCompareBase::compareEnabled() const +{ + return _enabled; +} + +// // MapHelper (from Map.h) // @@ -61,11 +89,12 @@ Freeze::MapHelper::create(const Freeze::ConnectionPtr& connection, const string& dbName, const string& key, const string& value, + const Freeze::KeyCompareBasePtr& keyCompare, const std::vector<MapIndexBasePtr>& indices, bool createDb) { Freeze::ConnectionIPtr connectionI = Freeze::ConnectionIPtr::dynamicCast(connection); - return new MapHelperI(connectionI, dbName, key, value, indices, createDb); + return new MapHelperI(connectionI, dbName, key, value, keyCompare, indices, createDb); } Freeze::MapHelper::~MapHelper() @@ -82,7 +111,8 @@ Freeze::IteratorHelper::create(const MapHelper& m, bool readOnly) { const MapHelperI& actualMap = dynamic_cast<const MapHelperI&>(m); - auto_ptr<IteratorHelperI> r(new IteratorHelperI(actualMap, readOnly, 0)); + auto_ptr<IteratorHelperI> r(new IteratorHelperI(actualMap, readOnly, + 0, false)); if(r->next()) { return r.release(); @@ -104,11 +134,13 @@ Freeze::IteratorHelper::~IteratorHelper() // Freeze::IteratorHelperI::IteratorHelperI(const MapHelperI& m, bool readOnly, - const MapIndexBasePtr& index) : + const MapIndexBasePtr& index, + bool onlyDups) : _map(m), _dbc(0), _indexed(index != 0), - _tx(0) + _tx(0), + _onlyDups(onlyDups) { if(_map._trace >= 2) { @@ -157,7 +189,8 @@ Freeze::IteratorHelperI::IteratorHelperI(const IteratorHelperI& it) : _map(it._map), _dbc(0), _indexed(it._indexed), - _tx(0) + _tx(0), + _onlyDups(it._onlyDups) { if(_map._trace >= 2) { @@ -228,6 +261,85 @@ Freeze::IteratorHelperI::find(const Key& key) const } } +bool +Freeze::IteratorHelperI::lowerBound(const Key& key) const +{ + // + // We retrieve the action key for upperBound + // + Dbt dbKey; + _key = key; + initializeOutDbt(_key, dbKey); + dbKey.set_size(static_cast<u_int32_t>(_key.size())); + + // + // 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 = _dbc->get(&dbKey, &dbValue, DB_SET_RANGE); + if(err == 0) + { + _key.resize(dbKey.get_size()); + return true; + } + else if(err == DB_NOTFOUND) + { + return false; + } + else + { + // + // Bug in Freeze + // + assert(0); + throw DatabaseException(__FILE__, __LINE__); + } + } + catch(const ::DbDeadlockException& dx) + { + if(_tx != 0) + { + _tx->dead(); + } + + DeadlockException ex(__FILE__, __LINE__); + ex.message = dx.what(); + throw ex; + } + catch(const ::DbException& dx) + { + handleDbException(dx, _key, dbKey, __FILE__, __LINE__); + } + } +} + +bool +Freeze::IteratorHelperI::upperBound(const Key& key) const +{ + if(lowerBound(key)) + { + if(_key == key) + { + return next(true); + } + else + { + return true; + } + } + else + { + return false; + } +} + + Freeze::IteratorHelper* Freeze::IteratorHelperI::clone() const { @@ -478,9 +590,15 @@ Freeze::IteratorHelperI::erase() } } -bool +bool Freeze::IteratorHelperI::next() const { + return next(false); +} + +bool +Freeze::IteratorHelperI::next(bool skipDups) const +{ // // Keep 0 length since we're not interested in the data // @@ -489,7 +607,15 @@ Freeze::IteratorHelperI::next() const Dbt dbValue; dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); - int flags = _indexed ? DB_NEXT_DUP : DB_NEXT; + int flags = DB_NEXT; + if(skipDups) + { + flags = DB_NEXT_NODUP; + } + else if(_indexed && _onlyDups) + { + flags = DB_NEXT_DUP; + } try { @@ -660,10 +786,11 @@ Freeze::MapHelperI::MapHelperI(const ConnectionIPtr& connection, const string& dbName, const string& key, const string& value, + const KeyCompareBasePtr& keyCompare, const vector<MapIndexBasePtr>& indices, bool createDb) : _connection(connection), - _db(SharedDb::get(connection, dbName, key, value, indices, createDb)), + _db(SharedDb::get(connection, dbName, key, value, keyCompare, indices, createDb)), _dbName(dbName), _trace(connection->trace()) { @@ -698,7 +825,7 @@ Freeze::MapHelperI::find(const Key& k, bool readOnly) const { try { - auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0)); + auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0, false)); if(r->find(k)) { return r.release(); @@ -731,6 +858,86 @@ Freeze::MapHelperI::find(const Key& k, bool readOnly) const } } +Freeze::IteratorHelper* +Freeze::MapHelperI::lowerBound(const Key& k, bool readOnly) const +{ + for(;;) + { + try + { + auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0, false)); + if(r->lowerBound(k)) + { + return r.release(); + } + else + { + return 0; + } + } + catch(const DeadlockException&) + { + if(_connection->dbTxn() != 0) + { + throw; + } + else + { + if(_connection->deadlockWarning()) + { + Warning out(_connection->communicator()->getLogger()); + out << "Deadlock in Freeze::MapHelperI::lowerBound on Map \"" + << _dbName << "\"; retrying ..."; + } + + // + // Ignored, try again + // + } + } + } +} + +Freeze::IteratorHelper* +Freeze::MapHelperI::upperBound(const Key& k, bool readOnly) const +{ + for(;;) + { + try + { + auto_ptr<IteratorHelperI> r(new IteratorHelperI(*this, readOnly, 0, false)); + if(r->upperBound(k)) + { + return r.release(); + } + else + { + return 0; + } + } + catch(const DeadlockException&) + { + if(_connection->dbTxn() != 0) + { + throw; + } + else + { + if(_connection->deadlockWarning()) + { + Warning out(_connection->communicator()->getLogger()); + out << "Deadlock in Freeze::MapHelperI::upperBound on Map \"" + << _dbName << "\"; retrying ..."; + } + + // + // Ignored, try again + // + } + } + } +} + void Freeze::MapHelperI::put(const Key& key, const Value& value) { @@ -1144,6 +1351,20 @@ Freeze::MapHelperI::closeAllIteratorsExcept(const IteratorHelperI::TxPtr& tx) co // MapIndexI // +extern "C" +{ +static int customIndexCompare(DB* db, const DBT* dbt1, const DBT* dbt2) +{ + MapIndexI* me = static_cast<MapIndexI*>(db->app_private); + Byte* first = static_cast<Byte*>(dbt1->data); + Key k1(first, first + dbt1->size); + first = static_cast<Byte*>(dbt2->data); + Key k2(first, first + dbt2->size); + + return me->getKeyCompare()->compare(k1, k2); +} +} + static int callback(Db* secondary, const Dbt* key, const Dbt* value, Dbt* result) { @@ -1172,6 +1393,13 @@ Freeze::MapIndexI::MapIndexI(const ConnectionIPtr& connection, SharedDb& db, _dbName = db.dbName() + "." + _index->name(); + _db->set_app_private(this); + + if(index->compareEnabled()) + { + _db->set_bt_compare(&customIndexCompare); + } + _db->open(txn, _dbName.c_str(), 0, DB_BTREE, flags, FREEZE_DB_MODE); // @@ -1191,9 +1419,10 @@ Freeze::MapIndexI::~MapIndexI() } IteratorHelper* -Freeze::MapIndexI::untypedFind(const Key& k, bool ro, const MapHelperI& m) const +Freeze::MapIndexI::untypedFind(const Key& k, bool ro, const MapHelperI& m, + bool onlyDups) const { - auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index)); + auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index, onlyDups)); if(r->find(k)) { @@ -1205,6 +1434,36 @@ Freeze::MapIndexI::untypedFind(const Key& k, bool ro, const MapHelperI& m) const } } +IteratorHelper* +Freeze::MapIndexI::untypedLowerBound(const Key& k, bool ro, const MapHelperI& m) const +{ + auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index, false)); + + if(r->lowerBound(k)) + { + return r.release(); + } + else + { + return 0; + } +} + +IteratorHelper* +Freeze::MapIndexI::untypedUpperBound(const Key& k, bool ro, const MapHelperI& m) const +{ + auto_ptr<IteratorHelperI> r(new IteratorHelperI(m, ro, _index, false)); + + if(r->upperBound(k)) + { + return r.release(); + } + else + { + return 0; + } +} + int Freeze::MapIndexI::untypedCount(const Key& k, const ConnectionIPtr& connection) const { |