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

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

  1. /*vim:settabstop=4:*/
  2. #ifndef__febird_bdb_kmapdset_h__
  3. #define__febird_bdb_kmapdset_h__
  4. #ifdefined(_MSC_VER)&&(_MSC_VER>=1020)
  5. #pragmaonce
  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. namespacefebird{
  13. classFEBIRD_DLL_EXPORTkmapdset_iterator_impl_base:publicRefCounter
  14. {
  15. public:
  16. classkmapdset_base*m_owner;
  17. DBC*m_curp;
  18. intm_ret;
  19. DBTm_bulk;
  20. public:
  21. kmapdset_iterator_impl_base(classkmapdset_base*owner);
  22. voidinit(DB*dbp,DB_TXN*txn,constchar*func);
  23. virtual~kmapdset_iterator_impl_base();
  24. virtualvoidclear_vec()=0;
  25. virtualvoidpush_back(void*data,size_tsize)=0;
  26. virtualvoidload_key1(void*data,size_tsize)=0;
  27. virtualvoidsave_key1(PortableDataOutput<autogrownMemIO>&oKey)=0;
  28. boolnext_key(size_t*cnt,constchar*func);
  29. voidbulk_load(DBT*tk1);
  30. voidincrement(constchar*func);
  31. voiddecrement(constchar*func);
  32. boolfind_pos(constvoid*k1,constvoid*k2,boolbulk,constchar*func);
  33. boolinsert(constvoid*d,constchar*func);
  34. boolupdate(constvoid*d,constchar*func);
  35. boolreplace(constvoid*d,constchar*func);
  36. boolremove(constvoid*k2,constchar*func);
  37. boolremove(constchar*func);
  38. };
  39. classFEBIRD_DLL_EXPORTkmapdset_base
  40. {
  41. DECLARE_NONE_copYABLE_CLASS(kmapdset_base)
  42. public:
  43. DB*m_db;
  44. size_tm_bulkSize;
  45. bt_compare_fcn_typem_bt_comp,m_dup_comp;
  46. kmapdset_base(DB_ENV*env,constchar*dbname
  47. ,DB_TXN*txn
  48. ,bt_compare_fcn_typebt_comp
  49. ,bt_compare_fcn_typedup_comp
  50. ,constchar*func
  51. );
  52. virtual~kmapdset_base();
  53. virtualvoidsave_key1(PortableDataOutput<autogrownMemIO>&dio,constvoid*key1)const=0;
  54. virtualvoidsave_key2(PortableDataOutput<autogrownMemIO>&dio,constvoid*key2)const=0;
  55. virtualvoidsave_data(PortableDataOutput<autogrownMemIO>&dio,constvoid*data)const=0;
  56. virtualkmapdset_iterator_impl_base*make_iter()=0;
  57. kmapdset_iterator_impl_base*begin_impl(DB_TXN*txn,constchar*func);
  58. kmapdset_iterator_impl_base*end_impl(DB_TXN*txn,constchar*func);
  59. kmapdset_iterator_impl_base*find_impl(constvoid*k1,u_int32_tflags,constchar*func);
  60. kmapdset_iterator_impl_base*find_impl(constvoid*k1,constchar*func);
  61. kmapdset_iterator_impl_base*upper_bound_impl(constvoid*k1,constchar*func);
  62. size_tcount_impl(constvoid*k1,constchar*func);
  63. boolinsert_impl(constvoid*k1,constvoid*d,constchar*func);
  64. boolreplace_impl(constvoid*k1,constchar*func);
  65. boolremove_impl(constvoid*k1,constchar*func);
  66. boolremove_impl(constvoid*k1,constchar*func);
  67. voidclear_impl(DB_TXN*txn,constchar*func);
  68. voidflush_impl(constchar*func);
  69. };
  70. template<classData>
  71. structkmapdset_select_key2
  72. {
  73. typedeftypenameData::key_typetype;
  74. };
  75. template<classKey2,classNonKeyData>
  76. structkmapdset_select_key2<std::pair<Key2,NonKeyData>>
  77. {
  78. typedefKey2type;
  79. };
  80. template<classKey1,classKey2,classData,classValue,classImpl>
  81. classkmapdset_iterator:
  82. publicstd::iterator<std::bidirectional_iterator_tag,Value,ptrdiff_t,constValue*,constValue&>
  83. {
  84. boost::intrusive_ptr<Impl>m_impl;
  85. voidcopy_on_write()
  86. {
  87. if(m_impl->getRefCount()>1)
  88. {
  89. Impl*p=newImpl(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. //#pragmawarning(disable:4661)//declarationbutnotdeFinition
  98. //!MSVCwillwarningC4661"declarationbutnotdeFinition"
  99. voidoperator++(int){assert(0);}
  100. voidoperator--(int){assert(0);}
  101. #else
  102. //!disable,becausecloneiteratorwillcauseverymuchtimeandresource
  103. voidoperator++(int);//{assert(0);}
  104. voidoperator--(int);//{assert(0);}
  105. #endif
  106. public:
  107. kmapdset_iterator(){}
  108. explicitkmapdset_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. //boolexist()const{returnDB_NOTFOUND!=m_impl->m_ret&&DB_KEYEMPTY!=m_impl->m_ret;}
  115. boolexist()const{return0==m_impl->m_ret;}
  116. //incrementandgetkey/data-cnt
  117. boolnext_key(size_t&cnt){returnm_impl->next_key(&cnt,BOOST_CURRENT_FUNCTION);}
  118. boolinsert(constData&d){returnm_impl->insert(&d,BOOST_CURRENT_FUNCTION);}
  119. boolupdate(constData&d){returnm_impl->update(&d,BOOST_CURRENT_FUNCTION);}
  120. boolreplace(constData&d){returnm_impl->replace(&d,BOOST_CURRENT_FUNCTION);}
  121. boolremove()const{returnm_impl->remove(BOOST_CURRENT_FUNCTION);}
  122. boolremove(constKey2&k2)const{returnm_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. constValue&operator*()const
  138. {
  139. assert(0==m_impl->m_ret);
  140. returnm_impl->m_kdv;
  141. }
  142. constValue*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. returnm_impl->m_kdv;
  151. }
  152. };
  153. //!@paramDataKey2isembededindata
  154. template<classKey1,classData>
  155. classkmapdset:protectedkmapdset_base
  156. {
  157. DECLARE_NONE_copYABLE_CLASS(kmapdset)
  158. public:
  159. typedefKey1
  160. key1_t,key_type;
  161. typedeftypenamekmapdset_select_key2<Data>::type
  162. key2_t;
  163. typedefData
  164. data_type,data_t;
  165. typedefstd::pair<Key1,std::vector<Data>>
  166. value_type;
  167. typedefstd::vector<Data>
  168. data_vec_t;
  169. typedeftypenamestd::vector<Data>::const_iterator
  170. data_iter_t;
  171. protected:
  172. classkmapdset_iterator_impl:publickmapdset_iterator_impl_base
  173. {
  174. public:
  175. value_typem_kdv;
  176. kmapdset_iterator_impl(kmapdset_base*owner)
  177. :kmapdset_iterator_impl_base(owner)
  178. {}
  179. virtualvoidclear_vec()
  180. {
  181. m_kdv.second.resize(0);
  182. }
  183. virtualvoidpush_back(void*data,size_tsize)
  184. {
  185. datax;
  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. virtualvoidload_key1(void*data,size_tsize)
  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. virtualvoidsave_key1(PortableDataOutput<autogrownMemIO>&oKey1)
  200. {
  201. oKey1<<m_kdv.first;
  202. }
  203. };
  204. //!overrides
  205. voidsave_key1(PortableDataOutput<autogrownMemIO>&dio,constvoid*key1)const{dio<<*(constkey1_t*)key1;}
  206. voidsave_key2(PortableDataOutput<autogrownMemIO>&dio,constvoid*key2)const{dio<<*(constkey2_t*)key2;}
  207. voidsave_data(PortableDataOutput<autogrownMemIO>&dio,constvoid*data)const{dio<<*(constdata_t*)data;}
  208. kmapdset_iterator_impl_base*make_iter(){returnnewkmapdset_iterator_impl(this);}
  209. public:
  210. typedefkmapdset_iterator<Key1,key2_t,Data,value_type,kmapdset_iterator_impl>
  211. iterator,const_iterator;
  212. kmapdset(DB_ENV*env,constchar*dbname
  213. ,DB_TXN*txn=NULL
  214. ,bt_compare_fcn_typebt_comp=bdb_auto_bt_compare((key1_t*)(0))
  215. ,bt_compare_fcn_typedup_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,DbTxn*txn=NULL
  221. ,bt_compare_fcn_typedup_comp=bdb_auto_bt_compare((key2_t*)(0))
  222. )
  223. :kmapdset_base(env->get_DB_ENV(),txn?txn->get_DB_TXN():NULL,BOOST_CURRENT_FUNCTION)
  224. {
  225. }
  226. iteratorbegin(DB_TXN*txn=NULL){returniterator(begin_impl(txn,BOOST_CURRENT_FUNCTION));}
  227. iteratorend(DB_TXN*txn=NULL){returniterator(end_impl(txn,BOOST_CURRENT_FUNCTION));}
  228. iteratorbegin(DbTxn*txn){returniterator(begin_impl(txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION));}
  229. iteratorend(DbTxn*txn){returniterator(end_impl(txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION));}
  230. iteratorfind(constKey1&k1,DB_TXN*txn=NULL)
  231. {
  232. returniterator(find_impl(&k1,DB_SET|DB_MULTIPLE,BOOST_CURRENT_FUNCTION));
  233. }
  234. iteratorfind(constKey1&k1,DbTxn*txn)
  235. {
  236. returniterator(find_impl(&k1,txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION));
  237. }
  238. iteratorfind(constKey1&k1,constkey2_t&k2,DB_TXN*txn=NULL)
  239. {
  240. returniterator(find_impl(&k1,&k2,false,BOOST_CURRENT_FUNCTION));
  241. }
  242. iteratorfind(constKey1&k1,DbTxn*txn)
  243. {
  244. returniterator(find_impl(&k1,BOOST_CURRENT_FUNCTION));
  245. }
  246. iteratorfind_md(constKey1&k1,true,BOOST_CURRENT_FUNCTION));
  247. }
  248. iteratorfind_md(constKey1&k1,BOOST_CURRENT_FUNCTION));
  249. }
  250. iteratorlower_bound(constKey1&k1,DB_SET_RANGE|DB_MULTIPLE,BOOST_CURRENT_FUNCTION));
  251. }
  252. iteratorlower_bound(constKey1&k1,BOOST_CURRENT_FUNCTION));
  253. }
  254. iteratorupper_bound(constKey1&k1,DB_TXN*txn=NULL)
  255. {
  256. returniterator(upper_bound_impl(&k1,BOOST_CURRENT_FUNCTION));
  257. }
  258. boolinsert(constKey1&k1,constData&d,DB_TXN*txn=NULL)
  259. {
  260. returninsert_impl(&k1,&d,BOOST_CURRENT_FUNCTION);
  261. }
  262. boolinsert(constKey1&k1,DbTxn*txn)
  263. {
  264. returninsert_impl(&k1,BOOST_CURRENT_FUNCTION);
  265. }
  266. boolreplace(constKey1&k1,DB_TXN*txn=NULL)
  267. {
  268. returnreplace_impl(&k1,BOOST_CURRENT_FUNCTION);
  269. }
  270. boolreplace(constKey1&k1,DbTxn*txn)
  271. {
  272. returnreplace_impl(&k1,BOOST_CURRENT_FUNCTION);
  273. }
  274. boolremove(constKey1&k1,DB_TXN*txn=NULL)
  275. {
  276. returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
  277. }
  278. boolremove(constKey1&k1,DbTxn*txn)
  279. {
  280. returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
  281. }
  282. boolremove(constKey1&k1,DB_TXN*txn=NULL)
  283. {
  284. returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
  285. }
  286. boolremove(constKey1&k1,DbTxn*txn)
  287. {
  288. returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
  289. }
  290. boolerase(constiterator&iter)
  291. {
  292. returniter.remove();
  293. }
  294. voidclear(DB_TXN*txn=NULL)
  295. {
  296. clear_impl(txn,BOOST_CURRENT_FUNCTION);
  297. }
  298. voidclear(DbTxn*txn)
  299. {
  300. returnclear_impl(txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION);
  301. }
  302. voidflush()
  303. {
  304. returnflush_impl(BOOST_CURRENT_FUNCTION);
  305. }
  306. size_tcount(constKey1&k1,DB_TXN*txn=NULL)
  307. {
  308. returncount_impl(&k1,BOOST_CURRENT_FUNCTION);
  309. }
  310. size_tcount(constKey1&k1,DbTxn*txn)
  311. {
  312. returncount_impl(&k1,BOOST_CURRENT_FUNCTION);
  313. }
  314. DB*getDB(){returnm_db;}
  315. constDB*getDB()const{returnm_db;}
  316. };
  317. }//namespacefebird
  318. #endif//__febird_bdb_kmapdset_h__
  1. /*vim:settabstop=4:*/
  2. #include"kmapdset.h"
  3. //#include"../DataBuffer.h"
  4. #include<sstream>
  5. namespacefebird{
  6. kmapdset_iterator_impl_base::kmapdset_iterator_impl_base(classkmapdset_base*owner)
  7. :m_owner(owner)
  8. ,m_curp(0),m_ret(-1)
  9. {
  10. memset(&m_bulk,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. voidkmapdset_iterator_impl_base::init(DB*dbp,constchar*func)
  17. {
  18. intret=dbp->cursor(dbp,&m_curp,0);
  19. if(0!=ret)
  20. {
  21. deletethis;
  22. std::ostringstreamoss;
  23. oss<<db_strerror(ret)<<"...at:"<<func;
  24. throwstd::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. boolkmapdset_iterator_impl_base::next_key(size_t*cnt,constchar*func)
  36. {
  37. FEBIRD_RT_assert(0==m_ret,std::logic_error);
  38. DBTtk1;memset(&tk1,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_tcnt0=0;
  44. intret=m_curp->count(m_curp,&cnt0,0);
  45. if(0!=ret)
  46. {
  47. std::ostringstreamoss;
  48. oss<<db_strerror(ret)<<"...at:"<<func;
  49. throwstd::runtime_error(oss.str());
  50. }
  51. *cnt=cnt0;
  52. returntrue;
  53. }
  54. elseif(DB_NOTFOUND==m_ret)
  55. {
  56. returnfalse;
  57. }
  58. else
  59. {
  60. std::ostringstreamoss;
  61. oss<<db_strerror(m_ret)<<"...at:"<<func;
  62. throwstd::runtime_error(oss.str());
  63. }
  64. }
  65. voidkmapdset_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. intret;
  71. do{
  72. void*bptr,*data;
  73. size_tsize;
  74. DB_MULTIPLE_INIT(bptr,&m_bulk);
  75. assert(NULL!=bptr);
  76. for(;;)
  77. {
  78. DB_MULTIPLE_NEXT(bptr,data,size);
  79. if(bptr)
  80. this->push_back(data,size);
  81. else
  82. break;
  83. }
  84. ret=m_curp->get(m_curp,tk1,DB_MULTIPLE|DB_NEXT_DUP);
  85. }while(0==ret);
  86. }
  87. voidkmapdset_iterator_impl_base::increment(constchar*func)
  88. {
  89. FEBIRD_RT_assert(0==m_ret,DB_NEXT_NODUP|DB_MULTIPLE);
  90. if(0==m_ret)
  91. {
  92. bulk_load(&tk1);
  93. }
  94. elseif(DB_NOTFOUND!=m_ret)
  95. {
  96. std::ostringstreamoss;
  97. oss<<db_strerror(m_ret)<<"...at:"<<func;
  98. throwstd::runtime_error(oss.str());
  99. }
  100. }
  101. voidkmapdset_iterator_impl_base::decrement(constchar*func)
  102. {
  103. FEBIRD_RT_assert(0==m_ret,std::logic_error);
  104. DBTtk1;memset(&tk1,sizeof(DBT));
  105. m_ret=m_curp->get(m_curp,DB_PREV_NODUP);
  106. if(0==m_ret)
  107. {
  108. m_ret=m_curp->get(m_curp,DB_CURRENT|DB_MULTIPLE);
  109. if(0==m_ret)
  110. {
  111. bulk_load(&tk1);
  112. }
  113. elseif(DB_KEYEMPTY==m_ret)
  114. {
  115. std::ostringstreamoss;
  116. oss<<db_strerror(m_ret)
  117. <<"...at:"<<func;
  118. throwstd::runtime_error(oss.str());
  119. }
  120. }
  121. elseif(DB_NOTFOUND!=m_ret)
  122. {
  123. std::ostringstreamoss;
  124. oss<<db_strerror(m_ret)<<"...at:"<<func;
  125. throwstd::runtime_error(oss.str());
  126. }
  127. }
  128. boolkmapdset_iterator_impl_base::find_pos(constvoid*k1,constchar*func)
  129. {
  130. PortableDataOutput<autogrownMemIO>oKey1,oKey2;
  131. m_owner->save_key1(oKey1,k1);
  132. m_owner->save_key2(oKey2,k2);
  133. DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  134. DBTtk2;memset(&tk2,sizeof(DBT));tk2.data=oKey2.begin();tk2.size=oKey2.tell();
  135. m_ret=m_curp->get(m_curp,&tk2,DB_GET_BOTH);
  136. if(0==m_ret)
  137. {
  138. if(bulk){
  139. m_ret=m_curp->get(m_curp,DB_CURRENT|DB_MULTIPLE);
  140. if(0==m_ret){
  141. bulk_load(&tk1);
  142. returntrue;
  143. }
  144. }else{
  145. clear_vec();
  146. load_key1(tk1.data,tk1.size);
  147. push_back(tk2.data,tk2.size);
  148. returntrue;
  149. }
  150. }
  151. elseif(DB_NOTFOUND==m_ret)
  152. {
  153. returnfalse;
  154. }
  155. std::ostringstreamoss;
  156. oss<<db_strerror(m_ret)
  157. <<"...at:"<<func
  158. <<"/n"
  159. ;
  160. throwstd::runtime_error(oss.str());
  161. }
  162. /**
  163. @brief
  164. @returntruesuccessfulinserted
  165. falsefail,(key1,d)existed,andnotinserted
  166. @throwothererrors
  167. */
  168. boolkmapdset_iterator_impl_base::insert(constvoid*d,constchar*func)
  169. {
  170. FEBIRD_RT_assert(0==m_ret||DB_NOTFOUND==m_ret||DB_KEYEXIST==m_ret,std::logic_error);
  171. PortableDataOutput<autogrownMemIO>oKey1,oData;
  172. this->save_key1(oKey1);
  173. m_owner->save_data(oData,d);
  174. DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  175. DBTtdd;memset(&tdd,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
  176. intret=m_curp->put(m_curp,&tdd,DB_NODUPDATA);
  177. if(DB_KEYEXIST==ret)
  178. returnfalse;
  179. if(0==ret)
  180. returntrue;
  181. std::ostringstreamoss;
  182. oss<<db_strerror(m_ret)
  183. <<"...at:"<<func;
  184. throwstd::runtime_error(oss.str());
  185. }
  186. /**
  187. @brief
  188. @returntruesuccessfulupdated
  189. false(key1,d.key2)didnotexist,notupdated
  190. @throwothererrors
  191. */
  192. boolkmapdset_iterator_impl_base::update(constvoid*d,constchar*func)
  193. {
  194. FEBIRD_RT_assert(0==m_ret,std::logic_error);
  195. PortableDataOutput<autogrownMemIO>oKey1,oData;
  196. this->save_key1(oKey1);
  197. m_owner->save_data(oData,d);
  198. DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  199. DBTtdd;memset(&tdd,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
  200. intret=m_curp->get(m_curp,DB_GET_BOTH);
  201. if(0==ret)
  202. {
  203. tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  204. tdd.data=oData.begin();tdd.size=oData.tell();
  205. ret=m_curp->put(m_curp,DB_CURRENT);
  206. if(0==ret)
  207. returntrue;
  208. }
  209. elseif(DB_NOTFOUND==ret)
  210. {
  211. returnfalse;
  212. }
  213. std::ostringstreamoss;
  214. oss<<db_strerror(ret)
  215. <<"...at:"<<func;
  216. throwstd::runtime_error(oss.str());
  217. }
  218. /**
  219. @brief
  220. @returntrueitemwasreplacedby(key1,d)
  221. falseitemwasinserted
  222. @throwothererrors
  223. */
  224. boolkmapdset_iterator_impl_base::replace(constvoid*d,constchar*func)
  225. {
  226. PortableDataOutput<autogrownMemIO>oKey1,DB_CURRENT);
  227. if(0==ret)
  228. returntrue;
  229. }
  230. elseif(DB_NOTFOUND==ret)
  231. {
  232. ret=m_curp->put(m_curp,DB_NODUPDATA);
  233. if(0==ret)
  234. returnfalse;
  235. }
  236. std::ostringstreamoss;
  237. oss<<db_strerror(ret)
  238. <<"...at:"<<func;
  239. throwstd::runtime_error(oss.str());
  240. }
  241. boolkmapdset_iterator_impl_base::remove(constvoid*k2,oKey2;
  242. this->save_key1(oKey1);
  243. m_owner->save_key2(oKey2,sizeof(DBT));tdd.data=oKey2.begin();tdd.size=oKey2.tell();
  244. intret=m_curp->get(m_curp,DB_GET_BOTH);
  245. if(0==ret)
  246. ret=m_curp->del(m_curp,0);
  247. if(DB_KEYEMPTY==ret)
  248. returnfalse;
  249. if(0==ret)
  250. returntrue;
  251. std::ostringstreamoss;
  252. oss<<db_strerror(ret)
  253. <<"...at:"<<func;
  254. throwstd::runtime_error(oss.str());
  255. }
  256. boolkmapdset_iterator_impl_base::remove(constchar*func)
  257. {
  258. FEBIRD_RT_assert(0==m_ret,std::logic_error);
  259. PortableDataOutput<autogrownMemIO>oKey1;
  260. this->save_key1(oKey1);
  261. DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  262. intret=m_owner->m_db->del(m_owner->m_db,m_curp->txn,0);
  263. if(DB_NOTFOUND==ret)
  264. returnfalse;
  265. if(0==ret)
  266. returntrue;
  267. std::ostringstreamoss;
  268. oss<<db_strerror(ret)
  269. <<"...at:"<<func;
  270. throwstd::runtime_error(oss.str());
  271. }
  272. //////////////////////////////////////////////////////////////////////////
  273. kmapdset_base::kmapdset_base(DB_ENV*env,DB_TXN*txn
  274. ,bt_compare_fcn_typebt_comp
  275. ,bt_compare_fcn_typedup_comp
  276. ,constchar*func
  277. )
  278. :m_bt_comp(0)
  279. {
  280. m_bulkSize=512*1024;
  281. m_db=0;
  282. intret=db_create(&m_db,env,0);
  283. if(0==ret)
  284. {
  285. if(bt_comp){
  286. m_bt_comp=bt_comp;
  287. m_db->set_bt_compare(m_db,bt_comp);
  288. }
  289. if(dup_comp){
  290. m_dup_comp=dup_comp;
  291. m_db->set_dup_compare(m_db,dup_comp);
  292. }
  293. m_db->app_private=(this);
  294. intflags=env->open_flags&(DB_THREAD|DB_MULTIVERSION|DB_AUTO_COMMIT);
  295. ret=m_db->open(m_db,DB_BTREE,DB_CREATE|flags,0);
  296. }
  297. if(0!=ret)
  298. {
  299. std::ostringstreamoss;
  300. oss<<db_strerror(ret)
  301. <<"...at:"<<func;
  302. throwstd::runtime_error(oss.str());
  303. }
  304. }
  305. kmapdset_base::~kmapdset_base()
  306. {
  307. if(m_db)
  308. m_db->close(m_db,0);
  309. }
  310. kmapdset_iterator_impl_base*kmapdset_base::begin_impl(DB_TXN*txn,constchar*func)
  311. {
  312. kmapdset_iterator_impl_base*iter=make_iter();
  313. iter->init(m_db,func);
  314. DBTtk1;memset(&tk1,sizeof(DBT));
  315. iter->m_ret=iter->m_curp->get(iter->m_curp,&iter->m_bulk,DB_FirsT|DB_MULTIPLE);
  316. if(0==iter->m_ret)
  317. {
  318. iter->bulk_load(&tk1);
  319. }
  320. elseif(DB_NOTFOUND!=iter->m_ret)
  321. {
  322. std::ostringstreamoss;
  323. oss<<db_strerror(iter->m_ret)
  324. <<"...at:"<<func;
  325. deleteiter;iter=0;
  326. throwstd::runtime_error(oss.str());
  327. }
  328. returniter;
  329. }
  330. kmapdset_iterator_impl_base*kmapdset_base::end_impl(DB_TXN*txn,constchar*func)
  331. {
  332. kmapdset_iterator_impl_base*iter=make_iter();
  333. iter->init(m_db,func);
  334. returniter;
  335. }
  336. kmapdset_iterator_impl_base*kmapdset_base::find_impl(constvoid*k1,constchar*func)
  337. {
  338. PortableDataOutput<autogrownMemIO>oKey1;
  339. save_key1(oKey1,k1);
  340. DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  341. kmapdset_iterator_impl_base*iter=make_iter();
  342. iter->init(m_db,func);
  343. iter->m_ret=iter->m_curp->get(iter->m_curp,flags);
  344. if(0==iter->m_ret)
  345. {
  346. iter->bulk_load(&tk1);
  347. }
  348. elseif(DB_NOTFOUND!=iter->m_ret&&DB_KEYEMPTY!=iter->m_ret)
  349. {
  350. std::ostringstreamoss;
  351. oss<<db_strerror(iter->m_ret)
  352. <<"...at:"<<func
  353. <<"/n"
  354. <<"flags="<<flags
  355. ;
  356. throwstd::runtime_error(oss.str());
  357. }
  358. returniter;
  359. }
  360. kmapdset_iterator_impl_base*
  361. kmapdset_base::find_impl(constvoid*k1,func);
  362. try{
  363. boolbRet=iter->find_pos(k1,k2,bulk,func);
  364. returniter;
  365. }catch(std::exception&exp){
  366. deleteiter;iter=0;
  367. throwexp;
  368. }
  369. }
  370. kmapdset_iterator_impl_base*kmapdset_base::upper_bound_impl(constvoid*k1,constchar*func)
  371. {
  372. PortableDataOutput<autogrownMemIO>oKey1;
  373. save_key1(oKey1,k1);
  374. DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  375. kmapdset_iterator_impl_base*iter=make_iter();
  376. iter->init(m_db,func);
  377. iter->m_ret=iter->m_curp->get(iter->m_curp,DB_SET_RANGE|DB_MULTIPLE);
  378. if(0==iter->m_ret)
  379. {
  380. DBTkbak;memset(&kbak,sizeof(DBT));kbak.data=oKey1.begin();kbak.size=oKey1.tell();
  381. intcmp=m_bt_comp(m_db,&kbak,&tk1);
  382. assert(cmp<=0);
  383. if(0==cmp){
  384. iter->m_ret=iter->m_curp->get(iter->m_curp,DB_NEXT_NODUP|DB_MULTIPLE);
  385. if(0==iter->m_ret)
  386. iter->bulk_load(&tk1);
  387. }else
  388. iter->bulk_load(&tk1);
  389. }
  390. if(0!=iter->m_ret&&DB_NOTFOUND!=iter->m_ret)
  391. {
  392. std::ostringstreamoss;
  393. oss<<db_strerror(iter->m_ret)
  394. <<"...at:"<<func
  395. <<"/n"
  396. ;
  397. throwstd::runtime_error(oss.str());
  398. }
  399. returniter;
  400. }
  401. size_tkmapdset_base::count_impl(constvoid*k1,constchar*func)
  402. {
  403. PortableDataOutput<autogrownMemIO>oKey1;
  404. try{
  405. save_key1(oKey1,k1);
  406. }
  407. catch(constIOException&exp)
  408. {
  409. std::ostringstreamoss;
  410. oss<<exp.what()<<"...at:"<<func;
  411. throwstd::runtime_error(oss.str());
  412. }
  413. DBTtk1;memset(&tk1,sizeof(DBT));
  414. DBC*curp=NULL;
  415. intret=m_db->cursor(m_db,&curp,0);
  416. if(0==ret)
  417. {
  418. ret=curp->get(curp,DB_SET);
  419. db_recno_tcount=0;
  420. if(0==ret)
  421. ret=curp->count(curp,&count,0);
  422. elseif(DB_NOTFOUND==ret)
  423. count=0,ret=0;//clearerror
  424. curp->close(curp);
  425. if(0!=ret)
  426. gotoErrorL;
  427. returncount;
  428. }
  429. ErrorL:
  430. std::ostringstreamoss;
  431. oss<<db_strerror(ret)
  432. <<"...at:"<<func
  433. <<"/n"
  434. ;
  435. throwstd::runtime_error(oss.str());
  436. }
  437. /**
  438. @briefinsertarecord
  439. @returntruesuccess,nosamek1-k2indb,therecordwasinserted
  440. falseFailed,hassamek1-k2indb,therecordwasnotinserted,notreplacedexistingyet
  441. @throwsexception,Failed
  442. */
  443. boolkmapdset_base::insert_impl(constvoid*k1,oData;
  444. try{
  445. save_key1(oKey1,k1);
  446. save_data(oData,d);
  447. }
  448. catch(constIOException&exp)
  449. {
  450. std::ostringstreamoss;
  451. oss<<exp.what()<<"...at:"<<func;
  452. throwstd::runtime_error(oss.str());
  453. }
  454. DBTtk1;memset(&tk1,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
  455. intret=m_db->put(m_db,DB_NODUPDATA);
  456. if(DB_KEYEXIST==ret)
  457. returnfalse;
  458. if(0==ret)
  459. returntrue;
  460. std::ostringstreamoss;
  461. oss<<db_strerror(ret)
  462. <<"...at:"<<func
  463. <<"/n"
  464. ;
  465. throwstd::runtime_error(oss.str());
  466. }
  467. /**
  468. @briefreplaceORinsertarecord
  469. @note
  470. ifnotthrownanexception,alwayssuccess
  471. @returntruereplacetherecord
  472. falseinserttherecord
  473. @throwsexception,Failed
  474. */
  475. boolkmapdset_base::replace_impl(constvoid*k1,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
  476. DBC*curp=NULL;
  477. intret=m_db->cursor(m_db,DB_GET_BOTH);
  478. if(0==ret)
  479. {
  480. tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  481. tdd.data=oData.begin();tdd.size=oData.tell();
  482. ret=curp->put(curp,DB_CURRENT);
  483. curp->close(curp);
  484. if(0==ret)
  485. returntrue;
  486. }
  487. elseif(DB_NOTFOUND==ret)
  488. {
  489. ret=curp->put(curp,DB_NODUPDATA);
  490. curp->close(curp);
  491. if(0==ret)
  492. returnfalse;
  493. }
  494. }
  495. std::ostringstreamoss;
  496. oss<<db_strerror(ret)
  497. <<"...at:"<<func
  498. <<"/n"
  499. ;
  500. throwstd::runtime_error(oss.str());
  501. }
  502. /**
  503. @brief
  504. @returntrue(k1,k2)existed,removesuccess
  505. false(k1,k2)notexisted,nothingdone
  506. */
  507. boolkmapdset_base::remove_impl(constvoid*k1,oData;
  508. oData.resize(4*1024);
  509. save_key1(oKey1,k1);
  510. save_key2(oData,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
  511. DBC*curp=NULL;
  512. intret=m_db->cursor(m_db,0);
  513. if(0==ret)
  514. {
  515. ret=curp->get(curp,DB_GET_BOTH);
  516. if(0==ret){
  517. ret=curp->del(curp,0);
  518. }
  519. curp->close(curp);
  520. return0==ret;
  521. }
  522. else
  523. {
  524. std::ostringstreamoss;
  525. oss<<db_strerror(ret)
  526. <<"...at:"<<func
  527. <<"/n"
  528. ;
  529. throwstd::runtime_error(oss.str());
  530. }
  531. }
  532. /**
  533. @brief
  534. @returntrue(k1)existed,removesuccess
  535. false(k1)notexisted,nothingdone
  536. */
  537. boolkmapdset_base::remove_impl(constvoid*k1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
  538. intret=m_db->del(m_db,0);
  539. if(DB_NOTFOUND==ret)
  540. returnfalse;
  541. if(0==ret)
  542. returntrue;
  543. std::ostringstreamoss;
  544. oss<<db_strerror(ret)
  545. <<"...at:"<<func
  546. <<"/n"
  547. ;
  548. throwstd::runtime_error(oss.str());
  549. }
  550. voidkmapdset_base::clear_impl(DB_TXN*txn,constchar*func)
  551. {
  552. u_int32_tcount;
  553. intret=m_db->truncate(m_db,0);
  554. if(0!=ret)
  555. {
  556. std::ostringstreamoss;
  557. oss<<db_strerror(ret)
  558. <<"...at:"<<func
  559. <<"/n"
  560. ;
  561. throwstd::runtime_error(oss.str());
  562. }
  563. }
  564. voidkmapdset_base::flush_impl(constchar*func)
  565. {
  566. intret=m_db->sync(m_db,0);
  567. if(0!=ret)
  568. {
  569. std::ostringstreamoss;
  570. oss<<db_strerror(ret)
  571. <<"...at:"<<func
  572. <<"/n"
  573. ;
  574. throwstd::runtime_error(oss.str());
  575. }
  576. }
  577. }//namespacefebird

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...