持久化的多键映射,使用BerkeleyDB

 如前介绍,相当于 std::map<Key1,std::map<Key2,Data> >,但接口也不完全相同,这里只贴代码:

 

  1. /* vim: set tabstop=4 : */
  2. #ifndef __febird_bdb_kmapdset_h__
  3. #define __febird_bdb_kmapdset_h__
  4. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  5. # pragma once
  6. #endif
  7. #include <db_cxx.h>
  8. #include "native_compare.h"
  9. #include "../io/DataIO.h"
  10. #include "../io/MemStream.h"
  11. #include "../refcount.h"
  12. namespace febird {
  13. class FEBIRD_DLL_EXPORT kmapdset_iterator_impl_base : public RefCounter
  14. {
  15. public:
  16.     class kmapdset_base* m_owner;
  17.     DBC* m_curp;
  18.     int  m_ret;
  19.     DBT  m_bulk;
  20. public:
  21.     kmapdset_iterator_impl_base(class kmapdset_base* owner);
  22.     void init(DB* dbp, DB_TXN* txn, const char* func);
  23.     virtual ~kmapdset_iterator_impl_base();
  24.     virtual void clear_vec() = 0;
  25.     virtual void push_back(void* data, size_t size) = 0;
  26.     virtual void load_key1(void* data, size_t size) = 0;
  27.     virtual void save_key1(PortableDataOutput<AutoGrownMemIO>& oKey) = 0;
  28.     bool next_key(size_t* cnt, const char* func);
  29.     void bulk_load(DBT* tk1);
  30.     void increment(const char* func);
  31.     void decrement(const char* func);
  32.     bool find_pos(const void* k1, const void* k2, bool bulk, const char* func);
  33.     bool insert(const void* d, const char* func);
  34.     bool update(const void* d, const char* func);
  35.     bool replace(const void* d, const char* func);
  36.     bool remove(const void* k2, const char* func);
  37.     bool remove(const char* func);
  38. };
  39. class FEBIRD_DLL_EXPORT kmapdset_base
  40. {
  41.     DECLARE_NONE_COPYABLE_CLASS(kmapdset_base)
  42. public:
  43.     DB*    m_db;
  44.     size_t m_bulkSize;
  45.     bt_compare_fcn_type m_bt_comp, m_dup_comp;
  46.     kmapdset_base(DB_ENV* env, const char* dbname
  47.         , DB_TXN* txn
  48.         , bt_compare_fcn_type bt_comp
  49.         , bt_compare_fcn_type dup_comp
  50.         , const char* func
  51.         );
  52.     virtual ~kmapdset_base();
  53.     virtual void save_key1(PortableDataOutput<AutoGrownMemIO>& dio, const void* key1) const = 0;
  54.     virtual void save_key2(PortableDataOutput<AutoGrownMemIO>& dio, const void* key2) const = 0;
  55.     virtual void save_data(PortableDataOutput<AutoGrownMemIO>& dio, const void* data) const = 0;
  56.     virtual kmapdset_iterator_impl_base* make_iter() = 0;
  57.     kmapdset_iterator_impl_base* begin_impl(DB_TXN* txn, const char* func);
  58.     kmapdset_iterator_impl_base* end_impl(DB_TXN* txn, const char* func);
  59.     kmapdset_iterator_impl_base* find_impl(const void* k1, DB_TXN* txn, u_int32_t flags, const char* func);
  60.     kmapdset_iterator_impl_base* find_impl(const void* k1, const void* k2, DB_TXN* txn, bool bulk, const char* func);
  61.     kmapdset_iterator_impl_base* upper_bound_impl(const void* k1, DB_TXN* txn, const char* func);
  62.     size_t count_impl(const void* k1, DB_TXN* txn, const char* func);
  63.     bool insert_impl(const void* k1, const void* d, DB_TXN* txn, const char* func);
  64.     bool replace_impl(const void* k1, const void* d, DB_TXN* txn, const char* func);
  65.     bool remove_impl(const void* k1, const void* k2, DB_TXN* txn, const char* func);
  66.     bool remove_impl(const void* k1, DB_TXN* txn, const char* func);
  67.     void clear_impl(DB_TXN* txn, const char* func);
  68.     void flush_impl(const char* func);
  69. };
  70. template<class Data>
  71. struct kmapdset_select_key2
  72. {
  73.     typedef typename Data::key_type type;
  74. };
  75. template<class Key2, class NonKeyData>
  76. struct kmapdset_select_key2<std::pair<Key2, NonKeyData> >
  77. {
  78.     typedef Key2 type;
  79. };
  80. template<class Key1, class Key2, class Data, class Value, class Impl>
  81. class kmapdset_iterator :
  82.     public std::iterator<std::bidirectional_iterator_tag, Value, ptrdiff_tconst Value*, const Value&>
  83. {
  84.     boost::intrusive_ptr<Impl> m_impl;
  85.     void copy_on_write()
  86.     {
  87.         if (m_impl->getRefCount() > 1)
  88.         {
  89.             Impl* p = new Impl(m_impl->m_owner);
  90.             m_impl->m_ret = m_impl->m_curp->dup(m_impl->m_curp, &p->m_curp, DB_POSITION);
  91.             FEBIRD_RT_assert(0 == m_impl->m_ret, std::runtime_error);
  92.             m_impl.reset(p);
  93.         }
  94.     }
  95. private:
  96. #ifdef _MSC_VER
  97. //# pragma warning(disable: 4661) // declaration but not definition
  98. //! MSVC will warning C4661 "declaration but not definition"
  99. void operator++(int) { assert(0); }
  100. void operator--(int) { assert(0); }
  101. #else
  102. //! disable, because clone iterator will cause very much time and resource
  103. void operator++(int);// { assert(0); }
  104. void operator--(int);// { assert(0); }
  105. #endif
  106. public:
  107.     kmapdset_iterator() {}
  108.     explicit kmapdset_iterator(kmapdset_iterator_impl_base* impl)
  109.         : m_impl(static_cast<Impl*>(impl))
  110.     {
  111.         assert(impl);
  112.         assert(dynamic_cast<Impl*>(impl));
  113.     }
  114. //  bool exist() const { return DB_NOTFOUND != m_impl->m_ret && DB_KEYEMPTY != m_impl->m_ret; }
  115.     bool exist() const { return 0 == m_impl->m_ret; }
  116.     // increment and get key/data-cnt
  117.     bool next_key(size_t& cnt) { return m_impl->next_key(&cnt,BOOST_CURRENT_FUNCTION); }
  118.     bool insert(const Data& d) { return m_impl->insert(&d,BOOST_CURRENT_FUNCTION); }
  119.     bool update(const Data& d) { return m_impl->update(&d,BOOST_CURRENT_FUNCTION); }
  120.     bool replace(const Data& d) { return m_impl->replace(&d,BOOST_CURRENT_FUNCTION); }
  121.     bool remove() const { return m_impl->remove(BOOST_CURRENT_FUNCTION); }
  122.     bool remove(const Key2& k2) const { return m_impl->remove(&k2,BOOST_CURRENT_FUNCTION); }
  123.     kmapdset_iterator& operator++()
  124.     {
  125.         assert(0 == m_impl->m_ret);
  126.         copy_on_write();
  127.         m_impl->increment(BOOST_CURRENT_FUNCTION);
  128.         return *this;
  129.     }
  130.     kmapdset_iterator& operator--()
  131.     {
  132.         assert(0 == m_impl->m_ret);
  133.         copy_on_write();
  134.         m_impl->decrement(BOOST_CURRENT_FUNCTION);
  135.         return *this;
  136.     }
  137.     const Value& operator*() const
  138.     {
  139.         assert(0 == m_impl->m_ret);
  140.         return m_impl->m_kdv;
  141.     }
  142.     const Value* operator->() const
  143.     {
  144.         assert(0 == m_impl->m_ret);
  145.         return &m_impl->m_kdv;
  146.     }
  147.     Value& get_mutable() const
  148.     {
  149.         assert(0 == m_impl->m_ret);
  150.         return m_impl->m_kdv;
  151.     }
  152. };
  153. //! @param Data Key2 is embeded in Data
  154. template<class Key1, class Data>
  155. class kmapdset : protected kmapdset_base
  156. {
  157.     DECLARE_NONE_COPYABLE_CLASS(kmapdset)
  158. public:
  159.     typedef Key1
  160.             key1_t, key_type;
  161.     typedef typename kmapdset_select_key2<Data>::type
  162.             key2_t;
  163.     typedef Data
  164.             data_type, data_t;
  165.     typedef std::pair<Key1, std::vector<Data> >
  166.             value_type;
  167.     typedef std::vector<Data>
  168.             data_vec_t;
  169.     typedef typename std::vector<Data>::const_iterator
  170.             data_iter_t;
  171. protected:
  172.     class kmapdset_iterator_impl : public kmapdset_iterator_impl_base
  173.     {
  174.     public:
  175.         value_type m_kdv;
  176.         kmapdset_iterator_impl(kmapdset_base* owner)
  177.             : kmapdset_iterator_impl_base(owner)
  178.         {}
  179.         virtual void clear_vec()
  180.         {
  181.             m_kdv.second.resize(0);
  182.         }
  183.         virtual void push_back(void* data, size_t size)
  184.         {
  185.             Data x;
  186.             PortableDataInput<MinMemIO> iData;
  187.             iData.set(data);
  188.             iData >> x;
  189.             FEBIRD_RT_assert(iData.diff(data) == size, std::logic_error);
  190.             m_kdv.second.push_back(x);
  191.         }
  192.         virtual void load_key1(void* data, size_t size)
  193.         {
  194.             PortableDataInput<MemIO> iKey1;
  195.             iKey1.set(data, size);
  196.             iKey1 >> m_kdv.first;
  197.             FEBIRD_RT_assert(iKey1.diff(data) == size, std::logic_error);
  198.         }
  199.         virtual void save_key1(PortableDataOutput<AutoGrownMemIO>& oKey1)
  200.         {
  201.             oKey1 << m_kdv.first;
  202.         }
  203.     };
  204.     //! overrides
  205.     void save_key1(PortableDataOutput<AutoGrownMemIO>& dio, const void* key1) const { dio << *(const key1_t*)key1; }
  206.     void save_key2(PortableDataOutput<AutoGrownMemIO>& dio, const void* key2) const { dio << *(const key2_t*)key2; }
  207.     void save_data(PortableDataOutput<AutoGrownMemIO>& dio, const void* data) const { dio << *(const data_t*)data; }
  208.     kmapdset_iterator_impl_base* make_iter() { return new kmapdset_iterator_impl(this); }
  209. public:
  210.     typedef kmapdset_iterator<Key1, key2_t, Data, value_type, kmapdset_iterator_impl>
  211.             iterator, const_iterator;
  212.     kmapdset(DB_ENV* env, const char* dbname
  213.         , DB_TXN* txn = NULL
  214.         , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((key1_t*)(0))
  215.         , bt_compare_fcn_type dup_comp = bdb_auto_bt_compare((key2_t*)(0))
  216.         )
  217.         : kmapdset_base(env, dbname, txn, bt_comp, dup_comp, BOOST_CURRENT_FUNCTION)
  218.     {
  219.     }
  220.     kmapdset(DbEnv* env, const char* dbname
  221.         , DbTxn* txn = NULL
  222.         , bt_compare_fcn_type bt_comp = bdb_auto_bt_compare((key1_t*)(0))
  223.         , bt_compare_fcn_type dup_comp = bdb_auto_bt_compare((key2_t*)(0))
  224.         )
  225.         : kmapdset_base(env->get_DB_ENV(), dbname, txn ? txn->get_DB_TXN() : NULL, bt_comp, dup_comp, BOOST_CURRENT_FUNCTION)
  226.     {
  227.     }
  228.     iterator begin(DB_TXN* txn = NULL) { return iterator(begin_impl(txn, BOOST_CURRENT_FUNCTION)); }
  229.     iterator end  (DB_TXN* txn = NULL) { return iterator(end_impl  (txn, BOOST_CURRENT_FUNCTION)); }
  230.     iterator begin(DbTxn* txn) { return iterator(begin_impl(txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION)); }
  231.     iterator end  (DbTxn* txn) { return iterator(end_impl  (txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION)); }
  232.     iterator find(const Key1& k1, DB_TXN* txn = NULL)
  233.     {
  234.         return iterator(find_impl(&k1, txn, DB_SET|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
  235.     }
  236.     iterator find(const Key1& k1, DbTxn* txn)
  237.     {
  238.         return iterator(find_impl(&k1, txn->get_DB_TXN(), DB_SET|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
  239.     }
  240.     iterator find(const Key1& k1, const key2_t& k2, DB_TXN* txn = NULL)
  241.     {
  242.         return iterator(find_impl(&k1, &k2, txn, false, BOOST_CURRENT_FUNCTION));
  243.     }
  244.     iterator find(const Key1& k1, const key2_t& k2, DbTxn* txn)
  245.     {
  246.         return iterator(find_impl(&k1, &k2, txn->get_DB_TXN(), false, BOOST_CURRENT_FUNCTION));
  247.     }
  248.     iterator find_md(const Key1& k1, const key2_t& k2, DB_TXN* txn = NULL)
  249.     {
  250.         return iterator(find_impl(&k1, &k2, txn, true, BOOST_CURRENT_FUNCTION));
  251.     }
  252.     iterator find_md(const Key1& k1, const key2_t& k2, DbTxn* txn)
  253.     {
  254.         return iterator(find_impl(&k1, &k2, txn->get_DB_TXN(), true, BOOST_CURRENT_FUNCTION));
  255.     }
  256.     iterator lower_bound(const Key1& k1, DB_TXN* txn = NULL)
  257.     {
  258.         return iterator(find_impl(&k1, txn, DB_SET_RANGE|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
  259.     }
  260.     iterator lower_bound(const Key1& k1, DbTxn* txn)
  261.     {
  262.         return iterator(find_impl(&k1, txn->get_DB_TXN(), DB_SET_RANGE|DB_MULTIPLE, BOOST_CURRENT_FUNCTION));
  263.     }
  264.     iterator upper_bound(const Key1& k1, DB_TXN* txn = NULL)
  265.     {
  266.         return iterator(upper_bound_impl(&k1, txn, BOOST_CURRENT_FUNCTION));
  267.     }
  268.     bool insert(const Key1& k1, const Data& d, DB_TXN* txn = NULL)
  269.     {
  270.         return insert_impl(&k1, &d, txn, BOOST_CURRENT_FUNCTION);
  271.     }
  272.     bool insert(const Key1& k1, const Data& d, DbTxn* txn)
  273.     {
  274.         return insert_impl(&k1, &d, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
  275.     }
  276.     bool replace(const Key1& k1, const Data& d, DB_TXN* txn = NULL)
  277.     {
  278.         return replace_impl(&k1, &d, txn, BOOST_CURRENT_FUNCTION);
  279.     }
  280.     bool replace(const Key1& k1, const Data& d, DbTxn* txn)
  281.     {
  282.         return replace_impl(&k1, &d, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
  283.     }
  284.     bool remove(const Key1& k1, const key2_t& k2, DB_TXN* txn = NULL)
  285.     {
  286.         return remove_impl(&k1, &k2, txn, BOOST_CURRENT_FUNCTION);
  287.     }
  288.     bool remove(const Key1& k1, const key2_t& k2, DbTxn* txn)
  289.     {
  290.         return remove_impl(&k1, &k2, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
  291.     }
  292.     bool remove(const Key1& k1, DB_TXN* txn = NULL)
  293.     {
  294.         return remove_impl(&k1, txn, BOOST_CURRENT_FUNCTION);
  295.     }
  296.     bool remove(const Key1& k1, DbTxn* txn)
  297.     {
  298.         return remove_impl(&k1, txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
  299.     }
  300.     bool erase(const iterator& iter)
  301.     {
  302.         return iter.remove();
  303.     }
  304.     void clear(DB_TXN* txn = NULL)
  305.     {
  306.         clear_impl(txn, BOOST_CURRENT_FUNCTION);
  307.     }
  308.     void clear(DbTxn* txn)
  309.     {
  310.         return clear_impl(txn->get_DB_TXN(), BOOST_CURRENT_FUNCTION);
  311.     }
  312.     void flush()
  313.     {
  314.         return flush_impl(BOOST_CURRENT_FUNCTION);
  315.     }
  316.     size_t count(const Key1& k1, DB_TXN* txn = NULL)
  317.     {
  318.         return count_impl(&k1, txn, BOOST_CURRENT_FUNCTION);
  319.     }
  320.     size_t count(const Key1& k1, DbTxn* txn)
  321.     {
  322.         return count_impl(&k1, txn ? txn->get_DB_TXN() : NULL, BOOST_CURRENT_FUNCTION);
  323.     }
  324.     DB* getDB() { return m_db; }
  325.     const DB* getDB() const { return m_db; }
  326. };
  327. // namespace febird
  328. #endif // __febird_bdb_kmapdset_h__

 

  1. /* vim: set tabstop=4 : */
  2. #include "kmapdset.h"
  3. //#include "../DataBuffer.h"
  4. #include <sstream>
  5. namespace febird {
  6. kmapdset_iterator_impl_base::kmapdset_iterator_impl_base(class kmapdset_base* owner)
  7.     : m_owner(owner)
  8.     , m_curp(0), m_ret(-1)
  9. {
  10.     memset(&m_bulk, 0, sizeof(DBT));
  11.     m_bulk.size = (owner->m_bulkSize);
  12.     m_bulk.data = (::malloc(owner->m_bulkSize));
  13.     m_bulk.flags = (DB_DBT_USERMEM);
  14.     m_bulk.ulen = (owner->m_bulkSize);
  15. }
  16. void kmapdset_iterator_impl_base::init(DB* dbp, DB_TXN* txn, const char* func)
  17. {
  18.     int ret = dbp->cursor(dbp, txn, &m_curp, 0);
  19.     if (0 != ret)
  20.     {
  21.         delete this;
  22.         std::ostringstream oss;
  23.         oss << db_strerror(ret) << "... at: " << func;
  24.         throw std::runtime_error(oss.str());
  25.     }
  26.     m_ret = 0;
  27. }
  28. kmapdset_iterator_impl_base::~kmapdset_iterator_impl_base()
  29. {
  30.     if (m_bulk.data)
  31.         ::free(m_bulk.data);
  32.     if (m_curp)
  33.         m_curp->close(m_curp);
  34. }
  35. bool kmapdset_iterator_impl_base::next_key(size_t* cnt, const char* func)
  36. {
  37.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  38.     DBT tk1; memset(&tk1, 0, sizeof(DBT));
  39.     m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_NEXT_NODUP);
  40.     if (0 == m_ret)
  41.     {
  42.         load_key1(tk1.data, tk1.size);
  43.         db_recno_t cnt0 = 0;
  44.         int ret = m_curp->count(m_curp, &cnt0, 0);
  45.         if (0 != ret)
  46.         {
  47.             std::ostringstream oss;
  48.             oss << db_strerror(ret) << "... at: " << func;
  49.             throw std::runtime_error(oss.str());
  50.         }
  51.         *cnt = cnt0;
  52.         return true;
  53.     }
  54.     else if (DB_NOTFOUND == m_ret)
  55.     {
  56.         return false;
  57.     }
  58.     else
  59.     {
  60.         std::ostringstream oss;
  61.         oss << db_strerror(m_ret) << "... at: " << func;
  62.         throw std::runtime_error(oss.str());
  63.     }
  64. }
  65. void kmapdset_iterator_impl_base::bulk_load(DBT* tk1)
  66. {
  67.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  68.     load_key1(tk1->data, tk1->size);
  69.     clear_vec();
  70.     int ret;
  71.     do {
  72.         void  *bptr, *data;
  73.         size_t size;
  74.         DB_MULTIPLE_INIT(bptr, &m_bulk);
  75.         assert(NULL != bptr);
  76.         for (;;)
  77.         {
  78.             DB_MULTIPLE_NEXT(bptr, &m_bulk, data, size);
  79.             if (bptr)
  80.                 this->push_back(data, size);
  81.             else
  82.                 break;
  83.         }
  84.         ret = m_curp->get(m_curp, tk1, &m_bulk, DB_MULTIPLE|DB_NEXT_DUP);
  85.     } while (0 == ret);
  86. }
  87. void kmapdset_iterator_impl_base::increment(const char* func)
  88. {
  89.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  90.     DBT tk1; memset(&tk1, 0, sizeof(DBT));
  91.     m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_NEXT_NODUP|DB_MULTIPLE);
  92.     if (0 == m_ret)
  93.     {
  94.         bulk_load(&tk1);
  95.     }
  96.     else if (DB_NOTFOUND != m_ret)
  97.     {
  98.         std::ostringstream oss;
  99.         oss << db_strerror(m_ret) << "... at: " << func;
  100.         throw std::runtime_error(oss.str());
  101.     }
  102. }
  103. void kmapdset_iterator_impl_base::decrement(const char* func)
  104. {
  105.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  106.     DBT tk1; memset(&tk1, 0, sizeof(DBT));
  107.     m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_PREV_NODUP);
  108.     if (0 == m_ret)
  109.     {
  110.         m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_CURRENT|DB_MULTIPLE);
  111.         if (0 == m_ret)
  112.         {
  113.             bulk_load(&tk1);
  114.         }
  115.         else if (DB_KEYEMPTY == m_ret)
  116.         {
  117.             std::ostringstream oss;
  118.             oss << db_strerror(m_ret)
  119.                 << "... at: " << func;
  120.             throw std::runtime_error(oss.str());
  121.         }
  122.     }
  123.     else if (DB_NOTFOUND != m_ret)
  124.     {
  125.         std::ostringstream oss;
  126.         oss << db_strerror(m_ret) << "... at: " << func;
  127.         throw std::runtime_error(oss.str());
  128.     }
  129. }
  130. bool kmapdset_iterator_impl_base::find_pos(const void* k1, const void* k2, bool bulk, const char* func)
  131. {
  132.     PortableDataOutput<AutoGrownMemIO> oKey1, oKey2;
  133.     m_owner->save_key1(oKey1, k1);
  134.     m_owner->save_key2(oKey2, k2);
  135.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  136.     DBT tk2; memset(&tk2, 0, sizeof(DBT)); tk2.data = oKey2.begin(); tk2.size = oKey2.tell();
  137.     m_ret = m_curp->get(m_curp, &tk1, &tk2, DB_GET_BOTH);
  138.     if (0 == m_ret)
  139.     {
  140.         if (bulk) {
  141.             m_ret = m_curp->get(m_curp, &tk1, &m_bulk, DB_CURRENT|DB_MULTIPLE);
  142.             if (0 == m_ret) {
  143.                 bulk_load(&tk1);
  144.                 return true;
  145.             }
  146.         } else {
  147.             clear_vec();
  148.             load_key1(tk1.data, tk1.size);
  149.             push_back(tk2.data, tk2.size);
  150.             return true;
  151.         }
  152.     }
  153.     else if (DB_NOTFOUND == m_ret)
  154.     {
  155.         return false;
  156.     }
  157.     std::ostringstream oss;
  158.     oss << db_strerror(m_ret)
  159.         << "... at: " << func
  160.         << "/n"
  161.         ;
  162.     throw std::runtime_error(oss.str());
  163. }
  164. /**
  165.  @brief 
  166.  @return true successful inserted
  167.         false fail, (key1, d) existed, and not inserted
  168.  @throw other errors
  169.  */
  170. bool kmapdset_iterator_impl_base::insert(const void* d, const char* func)
  171. {
  172.     FEBIRD_RT_assert(0 == m_ret || DB_NOTFOUND == m_ret || DB_KEYEXIST == m_ret, std::logic_error);
  173.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  174.     this->save_key1(oKey1);
  175.     m_owner->save_data(oData, d);
  176.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  177.     DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
  178.     int ret = m_curp->put(m_curp, &tk1, &tdd, DB_NODUPDATA);
  179.     if (DB_KEYEXIST == ret)
  180.         return false;
  181.     if (0 == ret)
  182.         return true;
  183.     std::ostringstream oss;
  184.     oss << db_strerror(m_ret)
  185.         << "... at: " << func;
  186.     throw std::runtime_error(oss.str());
  187. }
  188. /**
  189.  @brief 
  190.  @return true successful updated
  191.         false (key1, d.key2) did not exist, not updated
  192.  @throw other errors
  193.  */
  194. bool kmapdset_iterator_impl_base::update(const void* d, const char* func)
  195. {
  196.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  197.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  198.     this->save_key1(oKey1);
  199.     m_owner->save_data(oData, d);
  200.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  201.     DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
  202.     int ret = m_curp->get(m_curp, &tk1, &tdd, DB_GET_BOTH);
  203.     if (0 == ret)
  204.     {
  205.         tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  206.         tdd.data = oData.begin(); tdd.size = oData.tell();
  207.         ret = m_curp->put(m_curp, &tk1, &tdd, DB_CURRENT);
  208.         if (0 == ret)
  209.             return true;
  210.     }
  211.     else if (DB_NOTFOUND == ret)
  212.     {
  213.         return false;
  214.     }
  215.     std::ostringstream oss;
  216.     oss << db_strerror(ret)
  217.         << "... at: " << func;
  218.     throw std::runtime_error(oss.str());
  219. }
  220. /**
  221.  @brief 
  222.  @return true  item was replaced by (key1,d)
  223.          false item was inserted
  224.  @throw  other errors
  225.  */
  226. bool kmapdset_iterator_impl_base::replace(const void* d, const char* func)
  227. {
  228.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  229.     this->save_key1(oKey1);
  230.     m_owner->save_data(oData, d);
  231.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  232.     DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
  233.     int ret = m_curp->get(m_curp, &tk1, &tdd, DB_GET_BOTH);
  234.     if (0 == ret)
  235.     {
  236.         tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  237.         tdd.data = oData.begin(); tdd.size = oData.tell();
  238.         ret = m_curp->put(m_curp, &tk1, &tdd, DB_CURRENT);
  239.         if (0 == ret)
  240.             return true;
  241.     }
  242.     else if (DB_NOTFOUND == ret)
  243.     {
  244.         ret = m_curp->put(m_curp, &tk1, &tdd, DB_NODUPDATA);
  245.         if (0 == ret)
  246.             return false;
  247.     }
  248.     std::ostringstream oss;
  249.     oss << db_strerror(ret)
  250.         << "... at: " << func;
  251.     throw std::runtime_error(oss.str());
  252. }
  253. bool kmapdset_iterator_impl_base::remove(const void* k2, const char* func)
  254. {
  255.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  256.     PortableDataOutput<AutoGrownMemIO> oKey1, oKey2;
  257.     this->save_key1(oKey1);
  258.     m_owner->save_key2(oKey2, k2);
  259.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  260.     DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oKey2.begin(); tdd.size = oKey2.tell();
  261.     int ret = m_curp->get(m_curp, &tk1, &tdd, DB_GET_BOTH);
  262.     if (0 == ret)
  263.         ret = m_curp->del(m_curp, 0);
  264.     if (DB_KEYEMPTY == ret)
  265.         return false;
  266.     if (0 == ret)
  267.         return true;
  268.     std::ostringstream oss;
  269.     oss << db_strerror(ret)
  270.         << "... at: " << func;
  271.     throw std::runtime_error(oss.str());
  272. }
  273. bool kmapdset_iterator_impl_base::remove(const char* func)
  274. {
  275.     FEBIRD_RT_assert(0 == m_ret, std::logic_error);
  276.     PortableDataOutput<AutoGrownMemIO> oKey1;
  277.     this->save_key1(oKey1);
  278.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  279.     int ret = m_owner->m_db->del(m_owner->m_db, m_curp->txn, &tk1, 0);
  280.     if (DB_NOTFOUND == ret)
  281.         return false;
  282.     if (0 == ret)
  283.         return true;
  284.     std::ostringstream oss;
  285.     oss << db_strerror(ret)
  286.         << "... at: " << func;
  287.     throw std::runtime_error(oss.str());
  288. }
  289. //
  290. kmapdset_base::kmapdset_base(DB_ENV* env, const char* dbname
  291.     , DB_TXN* txn
  292.     , bt_compare_fcn_type bt_comp
  293.     , bt_compare_fcn_type dup_comp
  294.     , const char* func
  295.     )
  296.     : m_bt_comp(0)
  297. {
  298.     m_bulkSize = 512*1024;
  299.     m_db = 0;
  300.     int ret = db_create(&m_db, env, 0);
  301.     if (0 == ret)
  302.     {
  303.         if (bt_comp) {
  304.             m_bt_comp = bt_comp;
  305.             m_db->set_bt_compare(m_db, bt_comp);
  306.         }
  307.         if (dup_comp) {
  308.             m_dup_comp = dup_comp;
  309.             m_db->set_dup_compare(m_db, dup_comp);
  310.         }
  311.         m_db->app_private = (this);
  312.         int flags = env->open_flags & (DB_THREAD|DB_MULTIVERSION|DB_AUTO_COMMIT);
  313.         ret = m_db->open(m_db, txn, dbname, dbname, DB_BTREE, DB_CREATE|flags, 0);
  314.     }
  315.     if (0 != ret)
  316.     {
  317.         std::ostringstream oss;
  318.         oss << db_strerror(ret)
  319.             << "... at: " << func;
  320.         throw std::runtime_error(oss.str());
  321.     }
  322. }
  323. kmapdset_base::~kmapdset_base()
  324. {
  325.     if (m_db)
  326.         m_db->close(m_db, 0);
  327. }
  328. kmapdset_iterator_impl_base* kmapdset_base::begin_impl(DB_TXN* txn, const char* func)
  329. {
  330.     kmapdset_iterator_impl_base* iter = make_iter();
  331.     iter->init(m_db, txn, func);
  332.     DBT tk1; memset(&tk1, 0, sizeof(DBT));
  333.     iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, DB_FIRST|DB_MULTIPLE);
  334.     if (0 == iter->m_ret)
  335.     {
  336.         iter->bulk_load(&tk1);
  337.     }
  338.     else if (DB_NOTFOUND != iter->m_ret)
  339.     {
  340.         std::ostringstream oss;
  341.         oss << db_strerror(iter->m_ret)
  342.             << "... at: " << func;
  343.         delete iter; iter = 0;
  344.         throw std::runtime_error(oss.str());
  345.     }
  346.     return iter;
  347. }
  348. kmapdset_iterator_impl_base* kmapdset_base::end_impl(DB_TXN* txn, const char* func)
  349. {
  350.     kmapdset_iterator_impl_base* iter = make_iter();
  351.     iter->init(m_db, txn, func);
  352.     return iter;
  353. }
  354. kmapdset_iterator_impl_base* kmapdset_base::find_impl(const void* k1, DB_TXN* txn, u_int32_t flags, const char* func)
  355. {
  356.     PortableDataOutput<AutoGrownMemIO> oKey1;
  357.     save_key1(oKey1, k1);
  358.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  359.     kmapdset_iterator_impl_base* iter = make_iter();
  360.     iter->init(m_db, txn, func);
  361.     iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, flags);
  362.     if (0 == iter->m_ret)
  363.     {
  364.         iter->bulk_load(&tk1);
  365.     }
  366.     else if (DB_NOTFOUND != iter->m_ret && DB_KEYEMPTY != iter->m_ret)
  367.     {
  368.         std::ostringstream oss;
  369.         oss << db_strerror(iter->m_ret)
  370.             << "... at: " << func
  371.             << "/n"
  372.             << "flags=" << flags
  373.             ;
  374.         throw std::runtime_error(oss.str());
  375.     }
  376.     return iter;
  377. }
  378. kmapdset_iterator_impl_base* 
  379. kmapdset_base::find_impl(const void* k1, const void* k2, DB_TXN* txn, bool bulk, const char* func)
  380. {
  381.     kmapdset_iterator_impl_base* iter = make_iter();
  382.     iter->init(m_db, txn, func);
  383.     try {
  384.         bool bRet = iter->find_pos(k1, k2, bulk, func);
  385.         return iter;
  386.     } catch (std::exception& exp) {
  387.         delete iter; iter = 0;
  388.         throw exp;
  389.     }
  390. }
  391. kmapdset_iterator_impl_base* kmapdset_base::upper_bound_impl(const void* k1, DB_TXN* txn, const char* func)
  392. {
  393.     PortableDataOutput<AutoGrownMemIO> oKey1;
  394.     save_key1(oKey1, k1);
  395.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  396.     kmapdset_iterator_impl_base* iter = make_iter();
  397.     iter->init(m_db, txn, func);
  398.     iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, DB_SET_RANGE|DB_MULTIPLE);
  399.     if (0 == iter->m_ret)
  400.     {
  401.         DBT kbak; memset(&kbak, 0, sizeof(DBT)); kbak.data = oKey1.begin(); kbak.size = oKey1.tell();
  402.         int cmp = m_bt_comp(m_db, &kbak, &tk1);
  403.         assert(cmp <= 0);
  404.         if (0 == cmp) {
  405.             iter->m_ret = iter->m_curp->get(iter->m_curp, &tk1, &iter->m_bulk, DB_NEXT_NODUP|DB_MULTIPLE);
  406.             if (0 == iter->m_ret)
  407.                 iter->bulk_load(&tk1);
  408.         } else
  409.             iter->bulk_load(&tk1);
  410.     }
  411.     if (0 != iter->m_ret && DB_NOTFOUND != iter->m_ret)
  412.     {
  413.         std::ostringstream oss;
  414.         oss << db_strerror(iter->m_ret)
  415.             << "... at: " << func
  416.             << "/n"
  417.             ;
  418.         throw std::runtime_error(oss.str());
  419.     }
  420.     return iter;
  421. }
  422. size_t kmapdset_base::count_impl(const void* k1, DB_TXN* txn, const char* func)
  423. {
  424.     PortableDataOutput<AutoGrownMemIO> oKey1;
  425.     try {
  426.         save_key1(oKey1, k1);
  427.     }
  428.     catch (const IOException& exp)
  429.     {
  430.         std::ostringstream oss;
  431.         oss << exp.what() << "... at: " << func;
  432.         throw std::runtime_error(oss.str());
  433.     }
  434.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  435.     DBT tdd; memset(&tdd, 0, sizeof(DBT));
  436.     DBC* curp = NULL;
  437.     int ret = m_db->cursor(m_db, txn, &curp, 0);
  438.     if (0 == ret)
  439.     {
  440.         ret = curp->get(curp, &tk1, &tdd, DB_SET);
  441.         db_recno_t count = 0;
  442.         if (0 == ret)
  443.             ret = curp->count(curp, &count, 0);
  444.         else if (DB_NOTFOUND == ret)
  445.             count = 0, ret = 0; // clear error
  446.         curp->close(curp);
  447.         if (0 != ret)
  448.             goto ErrorL;
  449.         return count;
  450.     }
  451. ErrorL:
  452.     std::ostringstream oss;
  453.     oss << db_strerror(ret)
  454.         << "... at: " << func
  455.         << "/n"
  456.         ;
  457.     throw std::runtime_error(oss.str());
  458. }
  459. /**
  460.  @brief insert a record
  461.  @return true success,  no same k1-k2 in db, the record was inserted
  462.          false failed, has same k1-k2 in db, the record was not inserted, not replaced existing yet
  463.  @throws exception, failed
  464.  */
  465. bool kmapdset_base::insert_impl(const void* k1, const void* d, DB_TXN* txn, const char* func)
  466. {
  467.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  468.     try {
  469.         save_key1(oKey1, k1);
  470.         save_data(oData, d);
  471.     }
  472.     catch (const IOException& exp)
  473.     {
  474.         std::ostringstream oss;
  475.         oss << exp.what() << "... at: " << func;
  476.         throw std::runtime_error(oss.str());
  477.     }
  478.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  479.     DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
  480.     int ret = m_db->put(m_db, txn, &tk1, &tdd, DB_NODUPDATA);
  481.     if (DB_KEYEXIST == ret)
  482.         return false;
  483.     if (0 == ret)
  484.         return true;
  485.     std::ostringstream oss;
  486.     oss << db_strerror(ret)
  487.         << "... at: " << func
  488.         << "/n"
  489.         ;
  490.     throw std::runtime_error(oss.str());
  491. }
  492. /**
  493.  @brief replace OR insert a record
  494.  @note
  495.   if not thrown an exception, always success
  496.  @return true replace the record
  497.          false insert the record
  498.  @throws exception, failed
  499.  */
  500. bool kmapdset_base::replace_impl(const void* k1, const void* d, DB_TXN* txn, const char* func)
  501. {
  502.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  503.     try {
  504.         save_key1(oKey1, k1);
  505.         save_data(oData, d);
  506.     }
  507.     catch (const IOException& exp)
  508.     {
  509.         std::ostringstream oss;
  510.         oss << exp.what() << "... at: " << func;
  511.         throw std::runtime_error(oss.str());
  512.     }
  513.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  514.     DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
  515.     DBC* curp = NULL;
  516.     int ret = m_db->cursor(m_db, txn, &curp, 0);
  517.     if (0 == ret)
  518.     {
  519.         ret = curp->get(curp, &tk1, &tdd, DB_GET_BOTH);
  520.         if (0 == ret)
  521.         {
  522.             tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  523.             tdd.data = oData.begin(); tdd.size = oData.tell();
  524.             ret = curp->put(curp, &tk1, &tdd, DB_CURRENT);
  525.             curp->close(curp);
  526.             if (0 == ret)
  527.                 return true;
  528.         }
  529.         else if (DB_NOTFOUND == ret)
  530.         {
  531.             ret = curp->put(curp, &tk1, &tdd, DB_NODUPDATA);
  532.             curp->close(curp);
  533.             if (0 == ret)
  534.                 return false;
  535.         }
  536.     }
  537.     std::ostringstream oss;
  538.     oss << db_strerror(ret)
  539.         << "... at: " << func
  540.         << "/n"
  541.         ;
  542.     throw std::runtime_error(oss.str());
  543. }
  544. /**
  545.  @brief 
  546.  @return true (k1,k2) existed, remove success
  547.         false (k1,k2) not existed, nothing done
  548.  */
  549. bool kmapdset_base::remove_impl(const void* k1, const void* k2, DB_TXN* txn, const char* func)
  550. {
  551.     PortableDataOutput<AutoGrownMemIO> oKey1, oData;
  552.     oData.resize(4*1024);
  553.     save_key1(oKey1, k1);
  554.     save_key2(oData, k2);
  555.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  556.     DBT tdd; memset(&tdd, 0, sizeof(DBT)); tdd.data = oData.begin(); tdd.size = oData.tell();
  557.     DBC* curp = NULL;
  558.     int ret = m_db->cursor(m_db, txn, &curp, 0);
  559.     if (0 == ret)
  560.     {
  561.         ret = curp->get(curp, &tk1, &tdd, DB_GET_BOTH);
  562.         if (0 == ret) {
  563.             ret = curp->del(curp, 0);
  564.         }
  565.         curp->close(curp);
  566.         return 0 == ret;
  567.     }
  568.     else
  569.     {
  570.         std::ostringstream oss;
  571.         oss << db_strerror(ret)
  572.             << "... at: " << func
  573.             << "/n"
  574.             ;
  575.         throw std::runtime_error(oss.str());
  576.     }
  577. }
  578. /**
  579.  @brief 
  580.  @return true (k1) existed, remove success
  581.         false (k1) not existed, nothing done
  582.  */
  583. bool kmapdset_base::remove_impl(const void* k1, DB_TXN* txn, const char* func)
  584. {
  585.     PortableDataOutput<AutoGrownMemIO> oKey1;
  586.     save_key1(oKey1, k1);
  587.     DBT tk1; memset(&tk1, 0, sizeof(DBT)); tk1.data = oKey1.begin(); tk1.size = oKey1.tell();
  588.     int ret = m_db->del(m_db, txn, &tk1, 0);
  589.     if (DB_NOTFOUND == ret)
  590.         return false;
  591.     if (0 == ret)
  592.         return true;
  593.     std::ostringstream oss;
  594.     oss << db_strerror(ret)
  595.         << "... at: " << func
  596.         << "/n"
  597.         ;
  598.     throw std::runtime_error(oss.str());
  599. }
  600. void kmapdset_base::clear_impl(DB_TXN* txn, const char* func)
  601. {
  602.     u_int32_t count;
  603.     int ret = m_db->truncate(m_db, txn, &count, 0);
  604.     if (0 != ret)
  605.     {
  606.         std::ostringstream oss;
  607.         oss << db_strerror(ret)
  608.             << "... at: " << func
  609.             << "/n"
  610.             ;
  611.         throw std::runtime_error(oss.str());
  612.     }
  613. }
  614. void kmapdset_base::flush_impl(const char* func)
  615. {
  616.     int ret = m_db->sync(m_db, 0);
  617.     if (0 != ret)
  618.     {
  619.         std::ostringstream oss;
  620.         oss << db_strerror(ret)
  621.             << "... at: " << func
  622.             << "/n"
  623.             ;
  624.         throw std::runtime_error(oss.str());
  625.     }
  626. }
  627. // namespace febird
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值