diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Freeze/DBI.cpp | 196 | ||||
-rw-r--r-- | cpp/src/Freeze/DBI.h | 18 |
2 files changed, 110 insertions, 104 deletions
diff --git a/cpp/src/Freeze/DBI.cpp b/cpp/src/Freeze/DBI.cpp index 158b931460c..c1fc21b49f4 100644 --- a/cpp/src/Freeze/DBI.cpp +++ b/cpp/src/Freeze/DBI.cpp @@ -294,13 +294,10 @@ Freeze::DBTransactionI::abort() _tid = 0; } -DBCursorI::DBCursorI(const ::Ice::CommunicatorPtr& communicator, const std::string& name, DBC* cursor, - bool hasCurrentValue) : +DBCursorI::DBCursorI(const ::Ice::CommunicatorPtr& communicator, const std::string& name, DBC* cursor) : _communicator(communicator), _trace(0), _name(name), - _canRemove(false), - _hasCurrentValue(hasCurrentValue), _cursor(cursor) { PropertiesPtr properties = _communicator->getProperties(); @@ -339,8 +336,42 @@ DBCursorI::getCommunicator() return _communicator; } +void +DBCursorI::curr(Key& key, Value& value) +{ + JTCSyncT<JTCMutex> sync(*this); + + if (!_cursor) + { + ostringstream s; + s << _errorPrefix << "\"" << _name << "\" has been closed"; + DBException ex; + ex.message = s.str(); + throw ex; + } + + DBT dbKey, dbData; + memset(&dbKey, 0, sizeof(dbKey)); + memset(&dbData, 0, sizeof(dbData)); + + if (_trace >= 1) + { + ostringstream s; + s << "reading current value from database \"" << _name << "\""; + _communicator->getLogger()->trace("DBCursor", s.str()); + } + + checkBerkeleyDBReturn(_cursor->c_get(_cursor, &dbKey, &dbData, DB_CURRENT), _errorPrefix, "DBcursor->c_get"); + + // + // Copy the data from the read key & data + // + key = Key(static_cast<Byte*>(dbKey.data), static_cast<Byte*>(dbKey.data) + dbKey.size); + value = Value(static_cast<Byte*>(dbData.data), static_cast<Byte*>(dbData.data) + dbData.size); +} + bool -DBCursorI::hasNext() +DBCursorI::next() { JTCSyncT<JTCMutex> sync(*this); @@ -354,62 +385,35 @@ DBCursorI::hasNext() } // - // Note that the reads are partial reads since this method only - // verifies that there is a next value + // This does a 0 byte partial read of the data for efficiency + // reasons. // DBT dbKey, dbData; memset(&dbKey, 0, sizeof(dbKey)); dbKey.flags = DB_DBT_PARTIAL; - memset(&dbData, 0, sizeof(dbData)); dbData.flags = DB_DBT_PARTIAL; - // - // If we've already verified that there is a next record then - // verify that the current record still exists. - // - if (_hasCurrentValue) + if (_trace >= 1) { - try - { - checkBerkeleyDBReturn(_cursor->c_get(_cursor, &dbKey, &dbData, DB_CURRENT), _errorPrefix, - "DBcursor->c_get");\ - } - catch(const DBNotFoundException&) - { - // - // There is no next record. - // - return false; - } - return true; + ostringstream s; + s << "moving to next value in database \"" << _name << "\""; + _communicator->getLogger()->trace("DBCursor", s.str()); } - // - // Otherwise, move to the next record. - // try { - checkBerkeleyDBReturn(_cursor->c_get(_cursor, &dbKey, &dbData, DB_NEXT), _errorPrefix, - "DBcursor->c_get");\ + checkBerkeleyDBReturn(_cursor->c_get(_cursor, &dbKey, &dbData, DB_NEXT), _errorPrefix, "DBcursor->c_get"); } catch(const DBNotFoundException&) { - // - // There is no next record - // return false; } - - // - // We now have a current value. - // - _hasCurrentValue = true; return true; } -void -DBCursorI::next(Key& key, Value& value) +bool +DBCursorI::prev() { JTCSyncT<JTCMutex> sync(*this); @@ -422,48 +426,36 @@ DBCursorI::next(Key& key, Value& value) throw ex; } + // + // This does a 0 byte partial read of the data for efficiency + // reasons. + // DBT dbKey, dbData; memset(&dbKey, 0, sizeof(dbKey)); + dbKey.flags = DB_DBT_PARTIAL; memset(&dbData, 0, sizeof(dbData)); + dbData.flags = DB_DBT_PARTIAL; - u_int32_t getFlags; - string desc; - - // - // Do we need to move to the next record? - // - if (!_hasCurrentValue) + if (_trace >= 1) { - getFlags = DB_NEXT; - desc = "next"; + ostringstream s; + s << "moving to previous value in database \"" << _name << "\""; + _communicator->getLogger()->trace("DBCursor", s.str()); } - else + + try { - getFlags = DB_CURRENT; - desc = "current"; + checkBerkeleyDBReturn(_cursor->c_get(_cursor, &dbKey, &dbData, DB_PREV), _errorPrefix, "DBcursor->c_get"); } - - if (_trace >= 1) + catch(const DBNotFoundException&) { - ostringstream s; - s << "reading " << desc << " value from database \"" << _name << "\""; - _communicator->getLogger()->trace("DB", s.str()); + return false; } - - checkBerkeleyDBReturn(_cursor->c_get(_cursor, &dbKey, &dbData, getFlags), _errorPrefix, "DBcursor->c_get"); - - // - // Copy the data from the read key & data - // - key = Key(static_cast<Byte*>(dbKey.data), static_cast<Byte*>(dbKey.data) + dbKey.size); - value = Value(static_cast<Byte*>(dbData.data), static_cast<Byte*>(dbData.data) + dbData.size); - - _canRemove = true; - _hasCurrentValue = false; + return true; } void -DBCursorI::remove() +DBCursorI::del() { JTCSyncT<JTCMutex> sync(*this); @@ -476,25 +468,14 @@ DBCursorI::remove() throw ex; } - if (!_canRemove) - { - DBNotFoundException ex; - ex.message = "The next method has not yet been called, or the remove method has already been called " - "after the last call to the next method."; - throw ex; - } - if (_trace >= 1) { ostringstream s; - s << "deleting value from database \"" << _name << "\""; - _communicator->getLogger()->trace("DB", s.str()); + s << "removing the current element in database \"" << _name << "\""; + _communicator->getLogger()->trace("DBCursor", s.str()); } - checkBerkeleyDBReturn( _cursor->c_del(_cursor, 0), _errorPrefix, "DBcursor->c_del"); - - _hasCurrentValue = false; - _canRemove = false; + checkBerkeleyDBReturn(_cursor->c_del(_cursor, 0), _errorPrefix, "DBcursor->c_del"); } DBCursorPtr @@ -513,7 +494,7 @@ DBCursorI::clone() DBC* cursor; _cursor->c_dup(_cursor, &cursor, DB_POSITION); - return new DBCursorI(_communicator, _name, cursor, _hasCurrentValue); + return new DBCursorI(_communicator, _name, cursor); } void @@ -594,7 +575,7 @@ Freeze::DBI::getCommunicator() } Long -Freeze::DBI::getNumberRecords() +Freeze::DBI::getNumberOfRecords() { JTCSyncT<JTCMutex> sync(*this); @@ -607,11 +588,14 @@ Freeze::DBI::getNumberRecords() throw ex; } - DB_BTREE_STAT s; - - checkBerkeleyDBReturn(_db->stat(_db, &s, DB_FAST_STAT), _errorPrefix, "DB->stat"); - - return s.bt_ndata; + // + // TODO: DB_FAST_STAT doesn't seem to do what the documentation says... + // + DB_BTREE_STAT* s; + checkBerkeleyDBReturn(_db->stat(_db, &s, 0), _errorPrefix, "DB->stat"); + Long num = s->bt_ndata; + free(s); + return num; } DBCursorPtr @@ -632,11 +616,35 @@ Freeze::DBI::getCursor() checkBerkeleyDBReturn(_db->cursor(_db, 0, &cursor, 0), _errorPrefix, "DB->cursor"); - return new DBCursorI(_communicator, _name, cursor, false); + // + // Note that the read of the data is partial (that is the data + // will not actually be read into memory since it isn't needed + // yet). + // + DBT dbData, dbKey; + memset(&dbData, 0, sizeof(dbData)); + dbData.flags = DB_DBT_PARTIAL; + memset(&dbKey, 0, sizeof(dbKey)); + dbKey.flags = DB_DBT_PARTIAL; + + try + { + checkBerkeleyDBReturn(cursor->c_get(cursor, &dbKey, &dbData, DB_FIRST), _errorPrefix, "DBcursor->c_get"); + } + catch(const DBNotFoundException&) + { + // + // Cleanup. + // + cursor->c_close(cursor); + throw; + } + + return new DBCursorI(_communicator, _name, cursor); } DBCursorPtr -Freeze::DBI::getCursorForKey(const Key& key) +Freeze::DBI::getCursorAtKey(const Key& key) { JTCSyncT<JTCMutex> sync(*this); @@ -683,7 +691,7 @@ Freeze::DBI::getCursorForKey(const Key& key) throw; } - return new DBCursorI(_communicator, _name, cursor, true); + return new DBCursorI(_communicator, _name, cursor); } void diff --git a/cpp/src/Freeze/DBI.h b/cpp/src/Freeze/DBI.h index fa116d7af2b..3265d6ad6a4 100644 --- a/cpp/src/Freeze/DBI.h +++ b/cpp/src/Freeze/DBI.h @@ -87,15 +87,16 @@ class DBCursorI : public DBCursor, public JTCMutex { public: - DBCursorI(const ::Ice::CommunicatorPtr&, const std::string&, DBC*, bool); + DBCursorI(const ::Ice::CommunicatorPtr&, const std::string&, DBC*); ~DBCursorI(); virtual ::Ice::CommunicatorPtr getCommunicator(); - virtual bool hasNext(); - virtual void next(Key& key, Value& value); - virtual void remove(); - + virtual void curr(Key& key, Value& value); + virtual bool next(); + virtual bool prev(); + virtual void del(); + virtual DBCursorPtr clone(); virtual void close(); @@ -107,9 +108,6 @@ private: std::string _name; std::string _errorPrefix; - bool _canRemove; // Can remove be called? - bool _hasCurrentValue; // Have we already verified that there is a next value? - DBC* _cursor; }; @@ -123,10 +121,10 @@ public: virtual std::string getName(); virtual ::Ice::CommunicatorPtr getCommunicator(); - virtual ::Ice::Long getNumberRecords(); + virtual ::Ice::Long getNumberOfRecords(); virtual DBCursorPtr getCursor(); - virtual DBCursorPtr getCursorForKey(const Key&); + virtual DBCursorPtr getCursorAtKey(const Key&); virtual void put(const Key&, const Value&); virtual Value get(const Key&); |