如前介绍,相当于 std::map<Key1,std::map<Key2,Data> >,但接口也不完全相同,这里只贴代码:
- /* vim: set tabstop=4 : */
- #ifndef __febird_bdb_kmapdset_h__
- #define __febird_bdb_kmapdset_h__
- #if defined(_MSC_VER) && (_MSC_VER >= 1020)
- # pragma once
- #endif
- #include <db_cxx.h>
- #include "native_compare.h"
- #include "../io/DataIO.h"
- #include "../io/MemStream.h"
- #include "../refcount.h"
- namespace febird {
- class FEBIRD_DLL_EXPORT kmapdset_iterator_impl_base : public RefCounter
- {
- public:
- class kmapdset_base* m_owner;
- DBC* m_curp;
- int m_ret;
- DBT m_bulk;
- public:
- kmapdset_iterator_impl_base(class kmapdset_base* owner);
- void init(DB* dbp, DB_TXN* txn, const char* func);
- virtual ~kmapdset_iterator_impl_base();
- virtual void clear_vec() = 0;
- virtual void push_back(void* data, size_t size) = 0;
- virtual void load_key1(void* data, size_t size) = 0;
- virtual void save_key1(PortableDataOutput<AutoGrownMemIO>& oKey) = 0;
- bool next_key(size_t* cnt, const char* func);
- void bulk_load(DBT* tk1);
- void increment(const char* func);
- void decrement(const char* func);
- bool find_pos(const void* k1, const void* k2, bool bulk, const char* func);
- bool insert(const void* d, const char* func);
- bool update(const void* d, const char* func);
- bool replace(const void* d, const char* func);
- bool remove(const void* k2, const char* func);
- bool remove(const char* func);
- };
- class FEBIRD_DLL_EXPORT kmapdset_base
- {
- DECLARE_NONE_COPYABLE_CLASS(kmapdset_base)
- public:
- DB* m_db;
- size_t m_bulkSize;
- bt_compare_fcn_type m_bt_comp, m_dup_comp;
- kmapdset_base(DB_ENV* env, const char* dbname
- , DB_TXN* txn
- , bt_compare_fcn_type bt_comp
- , bt_compare_fcn_type dup_comp
- , const char* func
- );
- virtual ~kmapdset_base();
- virtual void save_key1(PortableDataOutput<AutoGrownMemIO>& dio, const void* key1) const = 0;
- virtual void save_key2(PortableDataOutput<AutoGrownMemIO>& dio, const void* key2) const = 0;
- virtual void save_data(PortableDataOutput<AutoGrownMemIO>& dio, const void* data) const = 0;
- virtual kmapdset_iterator_impl_base* make_iter() = 0;
- kmapdset_iterator_impl_base* begin_impl(DB_TXN* txn, const char* func);
- kmapdset_iterator_impl_base* end_impl(DB_TXN* txn, const char* func);
- kmapdset_iterator_impl_base* find_impl(const void* k1, DB_TXN* txn, u_int32_t flags, const char* func);
- kmapdset_iterator_impl_base* find_impl(const void* k1, const void* k2, DB_TXN* txn, bool bulk, const char* func);
- kmapdset_iterator_impl_base* upper_bound_impl(const void* k1, DB_TXN* txn, const char* func);
- size_t count_impl(const void* k1, DB_TXN* txn, const char* func);
- bool insert_impl(const void* k1, const void* d, DB_TXN* txn, const char* func);
- bool replace_impl(const void* k1, const void* d, DB_TXN* txn, const char* func);
- bool remove_impl(const void* k1, const void* k2, DB_TXN* txn, const char* func);
- bool remove_impl(const void* k1, DB_TXN* txn, const char* func);
- void clear_impl(DB_TXN* txn, const char* func);
- void flush_impl(const char* func);
- };
- template<class Data>
- struct kmapdset_select_key2
- {
- typedef typename Data::key_type type;
- };
- template<class Key2, class NonKeyData>
- struct kmapdset_select_key2<std::pair<Key2, NonKeyData> >
- {
- typedef Key2 type;
- };
- template<class Key1, class Key2, class Data, class Value, class Impl>
- class kmapdset_iterator :
- public std::iterator<std::bidirectional_iterator_tag, Value, ptrdiff_t, const Value*, const Value&>
- {
- boost::intrusive_ptr<Impl> m_impl;
- void copy_on_write()
- {
- if (m_impl->getRefCount() > 1)
- {
- Impl* p = new Impl(m_impl->m_owner);
- m_impl->m_ret = m_impl->m_curp->dup(m_impl->m_curp, &p->m_curp, DB_POSITION);
- FEBIRD_RT_assert(0 == m_impl->m_ret, std::runtime_error);
- m_impl.reset(p);
- }
- }
- private:
- #ifdef _MSC_VER
- //# pragma warning(disable: 4661) // declaration but not definition
- //! MSVC will warning C4661 "declaration but not definition"
- void operator++(int) { assert(0); }
- void operator--(int) { assert(0); }
- #else
- //! disable, because clone iterator will cause very much time and resource
- void operator++(int);// { assert(0); }
- void operator--(int);// { assert(0); }
- #endif
- public:
- kmapdset_iterator() {}
- explicit kmapdset_iterator(kmapdset_iterator_impl_base* impl)
- : m_impl(static_cast<Impl*>(impl))
- {
- assert(impl);
- assert(dynamic_cast<Impl*>(impl));
- }
- // bool exist() const { return DB_NOTFOUND != m_impl->m_ret && DB_KEYEMPTY != m_impl->m_ret; }
- bool exist() const { return 0 == m_impl->m_ret; }
- // increment and get key/data-cnt
- bool next_key(size_t& cnt) { return m_impl->next_key(&cnt,BOOST_CURRENT_FUNCTION); }
- bool insert(const Data& d) { return m_impl->insert(&d,BOOST_CURRENT_FUNCTION); }
- bool update(const Data& d) { return m_impl->update(&d,BOOST_CURRENT_FUNCTION); }
- bool replace(const Data& d) { return m_impl->replace(&d,BOOST_CURRENT_FUNCTION); }
- bool remove() const { return m_impl->remove(BOOST_CURRENT_FUNCTION); }
- bool remove(const Key2& k2) const { return m_impl->remove(&k2,BOOST_CURRENT_FUNCTION); }
- kmapdset_iterator& operator++()
- {
- assert(0 == m_impl->m_ret);
- copy_on_write();
- m_impl->increment(BOOST_CURRENT_FUNCTION);
- return *this;
- }
- kmapdset_iterator& operator--()
- {
- assert(0 == m_impl->m_ret);
- copy_on_write();
- m_impl->decrement(BOOST_CURRENT_FUNCTION);
- return *this;
- }
- const Value& operator*() const
- {
- assert(0 == m_impl->m_ret);
- return m_impl->m_kdv;
- }
- const Value* operator->() const
- {
- assert(0 == m_impl->m_ret);
- return &m_impl->m_kdv;
- }
- Value& get_mutable() const
- {
- assert(0 == m_impl->m_ret);
- return m_impl->m_kdv;
- }
- };
- //! @param Data Key2 is embeded in Data
- template<class Key1, class Data>
- class kmapdset : protected kmapdset_base
- {
- DECLARE_NONE_COPYABLE_CLASS(kmapdset)
- public:
- typedef Key1
- key1_t, key_type;
- typedef typename kmapdset_select_key2<Data>::type
- key2_t;
- typedef Data
- data_type, data_t;
- typedef std::pair<Key1, std::vector<Data> >
- value_type;
- typedef std::vector<Data>
- data_vec_t;
- typedef typename std::vector<Data>::const_iterator
- data_iter_t;
- protected:
- class kmapdset_iterator_impl : public kmapdset_iterator_impl_base
- {
- public:
- value_type m_kdv;
- kmapdset_iterator_impl(kmapdset_base* owner)
- : kmapdset_iterator_impl_base(owner)
- {}
- virtual void clear_vec()
- {
- m_kdv.second.resize(0);
- }
- virtual void push_back(void* data, size_t size)
- {
- Data x;
- PortableDataInput<MinMemIO> iData;
- iData.set(data);
- iData >> x;
- FEBIRD_RT_assert(iData.diff(data) == size, std::logic_error);
- m_kdv.second.push_back(x);
- }
- virtual void load_key1(void* data, size_t size)
- {
- PortableDataInput<MemIO> iKey1;
- iKey1.set(data, size);
- iKey1 >> m_kdv.first;
- FEBIRD_RT_assert(iKey1.diff(data) == size, std::logic_error);
- }
- virtual void save_key1(PortableDataOutput<AutoGrownMemIO>& oKey1)
- {
- oKey1 << m_kdv.first;
- }
- };
- //! overrides
- void save_key1(PortableDataOutput<AutoGrownMemIO>& dio, const void* key1) const { dio << *(const key1_t*)key1; }
- void save_key2(PortableDataOutput<AutoGrownMemIO>& dio, const void* key2) const { dio << *(const key2_t*)key2; }
- void save_data(PortableDataOutput<AutoGrownMemIO>& dio, const void* data) const { dio << *(const data_t*)data; }
- kmapdset_iterator_impl_base* make_iter() { return new kmapdset_iterator_impl(this); }
- public:
- typedef kmapdset_iterator<Key1, key2_t, Data, value_type, kmapdset_iterator_impl>
- iterator, const_iterator;
- kmapdset(DB_ENV* env, const char* dbname
- , DB_TXN* txn = NULL
- , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((key1_t*)(0))
- , bt_compare_fcn_type dup_comp = bdb_auto_bt_compare((key2_t*)(0))
- )
- : kmapdset_base(env, dbname, txn, bt_comp, dup_comp, BOOST_CURRENT_FUNCTION)
- {
- }
- kmapdset(DbEnv* env, const char* dbname
- , DbTxn* txn = NULL
- , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((key1_t*)(0))
- , bt_compare_fcn_type dup_comp = bdb_auto_bt_compare((key2_t*)(0))
- )
- : kmapdset_base(env->get_DB_ENV(), dbname, txn ? txn->get_DB_TXN() : NULL, bt_comp, dup_comp, BOOST_CURRENT_FUNCTION)
- {
- }
- iterator begin(DB_TXN* txn = NULL) { return iterator(begin_impl(txn, BOOST_CURRENT_FUNCTION)); }
- iterator end (DB_TXN* txn = NULL) { return iterator(end_impl (txn, BOOST_CURRENT_FUNCTION)); }
- iterator begin(DbTxn* txn) { return iterator(begin_impl(txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION)); }
- iterator end (DbTxn* txn) { return iterator(end_impl (txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION)); }
- iterator find(const Key1& k1, DB_TXN* txn = NULL)
- {
- return iterator(find_impl(&k1, txn, DB_SET|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
- }
- iterator find(const Key1& k1, DbTxn* txn)
- {
- return iterator(find_impl(&k1, txn->get_DB_TXN(), DB_SET|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
- }
- iterator find(const Key1& k1, const key2_t& k2, DB_TXN* txn = NULL)
- {
- return iterator(find_impl(&k1, &k2, txn, false, BOOST_CURRENT_FUNCTION));
- }
- iterator find(const Key1& k1, const key2_t& k2, DbTxn* txn)
- {
- return iterator(find_impl(&k1, &k2, txn->get_DB_TXN(), false, BOOST_CURRENT_FUNCTION));
- }
- iterator find_md(const Key1& k1, const key2_t& k2, DB_TXN* txn = NULL)
- {
- return iterator(find_impl(&k1, &k2, txn, true, BOOST_CURRENT_FUNCTION));
- }
- iterator find_md(const Key1& k1, const key2_t& k2, DbTxn* txn)
- {
- return iterator(find_impl(&k1, &k2, txn->get_DB_TXN(), true, BOOST_CURRENT_FUNCTION));
- }
- iterator lower_bound(const Key1& k1, DB_TXN* txn = NULL)
- {
- return iterator(find_impl(&k1, txn, DB_SET_RANGE|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
- }
- iterator lower_bound(const Key1& k1, DbTxn* txn)
- {
- return iterator(find_impl(&k1, txn->get_DB_TXN(), DB_SET_RANGE|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
- }
- iterator upper_bound(const Key1& k1, DB_TXN* txn = NULL)
- {
- return iterator(upper_bound_impl(&k1, txn, BOOST_CURRENT_FUNCTION));
- }
- bool insert(const Key1& k1, const Data& d, DB_TXN* txn = NULL)
- {
- return insert_impl(&k1, &d, txn, BOOST_CURRENT_FUNCTION);
- }
- bool insert(const Key1& k1, const Data& d, DbTxn* txn)
- {
- return insert_impl(&k1, &d, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
- }
- bool replace(const Key1& k1, const Data& d, DB_TXN* txn = NULL)
- {
- return replace_impl(&k1, &d, txn, BOOST_CURRENT_FUNCTION);
- }
- bool replace(const Key1& k1, const Data& d, DbTxn* txn)
- {
- return replace_impl(&k1, &d, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
- }
- bool remove(const Key1& k1, const key2_t& k2, DB_TXN* txn = NULL)
- {
- return remove_impl(&k1, &k2, txn, BOOST_CURRENT_FUNCTION);
- }
- bool remove(const Key1& k1, const key2_t& k2, DbTxn* txn)
- {
- return remove_impl(&k1, &k2, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
- }
- bool remove(const Key1& k1, DB_TXN* txn = NULL)
- {
- return remove_impl(&k1, txn, BOOST_CURRENT_FUNCTION);
- }
- bool remove(const Key1& k1, DbTxn* txn)
- {
- return remove_impl(&k1, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
- }
- bool erase(const iterator& iter)
- {
- return iter.remove();
- }
- void clear(DB_TXN* txn = NULL)
- {
- clear_impl(txn, BOOST_CURRENT_FUNCTION);
- }
- void clear(DbTxn* txn)
- {
- return clear_impl(txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
- }
- void flush()
- {
- return flush_impl(BOOST_CURRENT_FUNCTION);
- }
- size_t count(const Key1& k1, DB_TXN* txn = NULL)
- {
- return count_impl(&k1, txn, BOOST_CURRENT_FUNCTION);
- }
- size_t count(const Key1& k1, DbTxn* txn)
- {
- return count_impl(&k1, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
- }
- DB* getDB() { return m_db; }
- const DB* getDB() const { return m_db; }
- };
- } // namespace febird
- #endif // __febird_bdb_kmapdset_h__
- /* vim: set tabstop=4 : */
- #include "kmapdset.h"
- //#include "../DataBuffer.h"
- #include <sstream>
- namespace febird {
- kmapdset_iterator_impl_base::kmapdset_iterator_impl_base(class kmapdset_base* owner)
- : m_owner(owner)
- , m_curp(0), m_ret(-1)
- {
- memset(&m_bulk, 0, sizeof(DBT));
- m_bulk.size = (owner->m_bulkSize);
- m_bulk.data = (::malloc(owner->m_bulkSize));
- m_bulk.flags = (DB_DBT_USERMEM);
- m_bulk.ulen = (owner->m_bulkSize);
- }
- void kmapdset_iterator_impl_base::init(DB* dbp, DB_TXN* txn, const char* func)
- {
- int ret = dbp->cursor(dbp, txn, &m_curp, 0);
- if (0 != ret)
- {
- delete this;
- std::ostringstream oss;
- oss << db_strerror(ret) << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- m_ret = 0;
- }
- kmapdset_iterator_impl_base::~kmapdset_iterator_impl_base()
- {
- if (m_bulk.data)
- ::free(m_bulk.data);
- if (m_curp)
- m_curp->close(m_curp);
- }
- bool kmapdset_iterator_impl_base::next_key(size_t* cnt, const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- DBT tk1; memset(&tk1, 0, sizeof(DBT));
- m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_NEXT_NODUP);
- if (0 == m_ret)
- {
- load_key1(tk1.data, tk1.size);
- db_recno_t cnt0 = 0;
- int ret = m_curp->count(m_curp, &cnt0, 0);
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret) << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- *cnt = cnt0;
- return true;
- }
- else if (DB_NOTFOUND == m_ret)
- {
- return false;
- }
- else
- {
- std::ostringstream oss;
- oss << db_strerror(m_ret) << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- void kmapdset_iterator_impl_base::bulk_load(DBT* tk1)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- load_key1(tk1->data, tk1->size);
- clear_vec();
- int ret;
- do {
- void *bptr, *data;
- size_t size;
- DB_MULTIPLE_INIT(bptr, &m_bulk);
- assert(NULL != bptr);
- for (;;)
- {
- DB_MULTIPLE_NEXT(bptr, &m_bulk, data, size);
- if (bptr)
- this->push_back(data, size);
- else
- break;
- }
- ret = m_curp->get(m_curp, tk1, &m_bulk, DB_MULTIPLE|DB_NEXT_DUP);
- } while (0 == ret);
- }
- void kmapdset_iterator_impl_base::increment(const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- DBT tk1; memset(&tk1, 0, sizeof(DBT));
- m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_NEXT_NODUP|DB_MULTIPLE);
- if (0 == m_ret)
- {
- bulk_load(&tk1);
- }
- else if (DB_NOTFOUND != m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(m_ret) << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- void kmapdset_iterator_impl_base::decrement(const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- DBT tk1; memset(&tk1, 0, sizeof(DBT));
- m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_PREV_NODUP);
- if (0 == m_ret)
- {
- m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_CURRENT|DB_MULTIPLE);
- if (0 == m_ret)
- {
- bulk_load(&tk1);
- }
- else if (DB_KEYEMPTY == m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(m_ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- else if (DB_NOTFOUND != m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(m_ret) << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- bool kmapdset_iterator_impl_base::find_pos(const void* k1, const void* k2, bool bulk, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1, oKey2;
- m_owner->save_key1(oKey1, k1);
- m_owner->save_key2(oKey2, k2);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tk2; memset(&tk2, 0, sizeof(DBT)); tk2.data = oKey2.begin(); tk2.size = oKey2.tell();
- m_ret = m_curp->get(m_curp, &tk1, &tk2, DB_GET_BOTH);
- if (0 == m_ret)
- {
- if (bulk) {
- m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_CURRENT|DB_MULTIPLE);
- if (0 == m_ret) {
- bulk_load(&tk1);
- return true;
- }
- } else {
- clear_vec();
- load_key1(tk1.data, tk1.size);
- push_back(tk2.data, tk2.size);
- return true;
- }
- }
- else if (DB_NOTFOUND == m_ret)
- {
- return false;
- }
- std::ostringstream oss;
- oss << db_strerror(m_ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- /**
- @brief
- @return true successful inserted
- false fail, (key1, d) existed, and not inserted
- @throw other errors
- */
- bool kmapdset_iterator_impl_base::insert(const void* d, const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret || DB_NOTFOUND == m_ret || DB_KEYEXIST == m_ret, std::logic_error);
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- this->save_key1(oKey1);
- m_owner->save_data(oData, d);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
- int ret = m_curp->put(m_curp, &tk1, &tdd, DB_NODUPDATA);
- if (DB_KEYEXIST == ret)
- return false;
- if (0 == ret)
- return true;
- std::ostringstream oss;
- oss << db_strerror(m_ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- /**
- @brief
- @return true successful updated
- false (key1, d.key2) did not exist, not updated
- @throw other errors
- */
- bool kmapdset_iterator_impl_base::update(const void* d, const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- this->save_key1(oKey1);
- m_owner->save_data(oData, d);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
- int ret = m_curp->get(m_curp, &tk1, &tdd, DB_GET_BOTH);
- if (0 == ret)
- {
- tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- tdd.data = oData.begin(); tdd.size = oData.tell();
- ret = m_curp->put(m_curp, &tk1, &tdd, DB_CURRENT);
- if (0 == ret)
- return true;
- }
- else if (DB_NOTFOUND == ret)
- {
- return false;
- }
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- /**
- @brief
- @return true item was replaced by (key1,d)
- false item was inserted
- @throw other errors
- */
- bool kmapdset_iterator_impl_base::replace(const void* d, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- this->save_key1(oKey1);
- m_owner->save_data(oData, d);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
- int ret = m_curp->get(m_curp, &tk1, &tdd, DB_GET_BOTH);
- if (0 == ret)
- {
- tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- tdd.data = oData.begin(); tdd.size = oData.tell();
- ret = m_curp->put(m_curp, &tk1, &tdd, DB_CURRENT);
- if (0 == ret)
- return true;
- }
- else if (DB_NOTFOUND == ret)
- {
- ret = m_curp->put(m_curp, &tk1, &tdd, DB_NODUPDATA);
- if (0 == ret)
- return false;
- }
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- bool kmapdset_iterator_impl_base::remove(const void* k2, const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- PortableDataOutput<AutoGrownMemIO> oKey1, oKey2;
- this->save_key1(oKey1);
- m_owner->save_key2(oKey2, k2);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oKey2.begin(); tdd.size = oKey2.tell();
- int ret = m_curp->get(m_curp, &tk1, &tdd, DB_GET_BOTH);
- if (0 == ret)
- ret = m_curp->del(m_curp, 0);
- if (DB_KEYEMPTY == ret)
- return false;
- if (0 == ret)
- return true;
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- bool kmapdset_iterator_impl_base::remove(const char* func)
- {
- FEBIRD_RT_assert(0 == m_ret, std::logic_error);
- PortableDataOutput<AutoGrownMemIO> oKey1;
- this->save_key1(oKey1);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- int ret = m_owner->m_db->del(m_owner->m_db, m_curp->txn, &tk1, 0);
- if (DB_NOTFOUND == ret)
- return false;
- if (0 == ret)
- return true;
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- //
- kmapdset_base::kmapdset_base(DB_ENV* env, const char* dbname
- , DB_TXN* txn
- , bt_compare_fcn_type bt_comp
- , bt_compare_fcn_type dup_comp
- , const char* func
- )
- : m_bt_comp(0)
- {
- m_bulkSize = 512*1024;
- m_db = 0;
- int ret = db_create(&m_db, env, 0);
- if (0 == ret)
- {
- if (bt_comp) {
- m_bt_comp = bt_comp;
- m_db->set_bt_compare(m_db, bt_comp);
- }
- if (dup_comp) {
- m_dup_comp = dup_comp;
- m_db->set_dup_compare(m_db, dup_comp);
- }
- m_db->app_private = (this);
- int flags = env->open_flags & (DB_THREAD|DB_MULTIVERSION|DB_AUTO_COMMIT);
- ret = m_db->open(m_db, txn, dbname, dbname, DB_BTREE, DB_CREATE|flags, 0);
- }
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- }
- kmapdset_base::~kmapdset_base()
- {
- if (m_db)
- m_db->close(m_db, 0);
- }
- kmapdset_iterator_impl_base* kmapdset_base::begin_impl(DB_TXN* txn, const char* func)
- {
- kmapdset_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- DBT tk1; memset(&tk1, 0, sizeof(DBT));
- iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, DB_FIRST|DB_MULTIPLE);
- if (0 == iter->m_ret)
- {
- iter->bulk_load(&tk1);
- }
- else if (DB_NOTFOUND != iter->m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(iter->m_ret)
- << "... at: " << func;
- delete iter; iter = 0;
- throw std::runtime_error(oss.str());
- }
- return iter;
- }
- kmapdset_iterator_impl_base* kmapdset_base::end_impl(DB_TXN* txn, const char* func)
- {
- kmapdset_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- return iter;
- }
- kmapdset_iterator_impl_base* kmapdset_base::find_impl(const void* k1, DB_TXN* txn, u_int32_t flags, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1;
- save_key1(oKey1, k1);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- kmapdset_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, flags);
- if (0 == iter->m_ret)
- {
- iter->bulk_load(&tk1);
- }
- else if (DB_NOTFOUND != iter->m_ret && DB_KEYEMPTY != iter->m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(iter->m_ret)
- << "... at: " << func
- << "/n"
- << "flags=" << flags
- ;
- throw std::runtime_error(oss.str());
- }
- return iter;
- }
- kmapdset_iterator_impl_base*
- kmapdset_base::find_impl(const void* k1, const void* k2, DB_TXN* txn, bool bulk, const char* func)
- {
- kmapdset_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- try {
- bool bRet = iter->find_pos(k1, k2, bulk, func);
- return iter;
- } catch (std::exception& exp) {
- delete iter; iter = 0;
- throw exp;
- }
- }
- kmapdset_iterator_impl_base* kmapdset_base::upper_bound_impl(const void* k1, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1;
- save_key1(oKey1, k1);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- kmapdset_iterator_impl_base* iter = make_iter();
- iter->init(m_db, txn, func);
- iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, DB_SET_RANGE|DB_MULTIPLE);
- if (0 == iter->m_ret)
- {
- DBT kbak; memset(&kbak, 0, sizeof(DBT)); kbak.data = oKey1.begin(); kbak.size = oKey1.tell();
- int cmp = m_bt_comp(m_db, &kbak, &tk1);
- assert(cmp <= 0);
- if (0 == cmp) {
- iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, DB_NEXT_NODUP|DB_MULTIPLE);
- if (0 == iter->m_ret)
- iter->bulk_load(&tk1);
- } else
- iter->bulk_load(&tk1);
- }
- if (0 != iter->m_ret && DB_NOTFOUND != iter->m_ret)
- {
- std::ostringstream oss;
- oss << db_strerror(iter->m_ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- return iter;
- }
- size_t kmapdset_base::count_impl(const void* k1, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1;
- try {
- save_key1(oKey1, k1);
- }
- catch (const IOException& exp)
- {
- std::ostringstream oss;
- oss << exp.what() << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT));
- DBC* curp = NULL;
- int ret = m_db->cursor(m_db, txn, &curp, 0);
- if (0 == ret)
- {
- ret = curp->get(curp, &tk1, &tdd, DB_SET);
- db_recno_t count = 0;
- if (0 == ret)
- ret = curp->count(curp, &count, 0);
- else if (DB_NOTFOUND == ret)
- count = 0, ret = 0; // clear error
- curp->close(curp);
- if (0 != ret)
- goto ErrorL;
- return count;
- }
- ErrorL:
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- /**
- @brief insert a record
- @return true success, no same k1-k2 in db, the record was inserted
- false failed, has same k1-k2 in db, the record was not inserted, not replaced existing yet
- @throws exception, failed
- */
- bool kmapdset_base::insert_impl(const void* k1, const void* d, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- try {
- save_key1(oKey1, k1);
- save_data(oData, d);
- }
- catch (const IOException& exp)
- {
- std::ostringstream oss;
- oss << exp.what() << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
- int ret = m_db->put(m_db, txn, &tk1, &tdd, DB_NODUPDATA);
- if (DB_KEYEXIST == ret)
- return false;
- if (0 == ret)
- return true;
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- /**
- @brief replace OR insert a record
- @note
- if not thrown an exception, always success
- @return true replace the record
- false insert the record
- @throws exception, failed
- */
- bool kmapdset_base::replace_impl(const void* k1, const void* d, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- try {
- save_key1(oKey1, k1);
- save_data(oData, d);
- }
- catch (const IOException& exp)
- {
- std::ostringstream oss;
- oss << exp.what() << "... at: " << func;
- throw std::runtime_error(oss.str());
- }
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
- DBC* curp = NULL;
- int ret = m_db->cursor(m_db, txn, &curp, 0);
- if (0 == ret)
- {
- ret = curp->get(curp, &tk1, &tdd, DB_GET_BOTH);
- if (0 == ret)
- {
- tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- tdd.data = oData.begin(); tdd.size = oData.tell();
- ret = curp->put(curp, &tk1, &tdd, DB_CURRENT);
- curp->close(curp);
- if (0 == ret)
- return true;
- }
- else if (DB_NOTFOUND == ret)
- {
- ret = curp->put(curp, &tk1, &tdd, DB_NODUPDATA);
- curp->close(curp);
- if (0 == ret)
- return false;
- }
- }
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- /**
- @brief
- @return true (k1,k2) existed, remove success
- false (k1,k2) not existed, nothing done
- */
- bool kmapdset_base::remove_impl(const void* k1, const void* k2, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1, oData;
- oData.resize(4*1024);
- save_key1(oKey1, k1);
- save_key2(oData, k2);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
- DBC* curp = NULL;
- int ret = m_db->cursor(m_db, txn, &curp, 0);
- if (0 == ret)
- {
- ret = curp->get(curp, &tk1, &tdd, DB_GET_BOTH);
- if (0 == ret) {
- ret = curp->del(curp, 0);
- }
- curp->close(curp);
- return 0 == ret;
- }
- else
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- }
- /**
- @brief
- @return true (k1) existed, remove success
- false (k1) not existed, nothing done
- */
- bool kmapdset_base::remove_impl(const void* k1, DB_TXN* txn, const char* func)
- {
- PortableDataOutput<AutoGrownMemIO> oKey1;
- save_key1(oKey1, k1);
- DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
- int ret = m_db->del(m_db, txn, &tk1, 0);
- if (DB_NOTFOUND == ret)
- return false;
- if (0 == ret)
- return true;
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- void kmapdset_base::clear_impl(DB_TXN* txn, const char* func)
- {
- u_int32_t count;
- int ret = m_db->truncate(m_db, txn, &count, 0);
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- }
- void kmapdset_base::flush_impl(const char* func)
- {
- int ret = m_db->sync(m_db, 0);
- if (0 != ret)
- {
- std::ostringstream oss;
- oss << db_strerror(ret)
- << "... at: " << func
- << "/n"
- ;
- throw std::runtime_error(oss.str());
- }
- }
- } // namespace febird