如前介绍,相当于 std::map<Key1,std::map<Key2,Data> >,但接口也不完全相同,这里只贴代码:
- /*vim:settabstop=4:*/
- #ifndef__febird_bdb_kmapdset_h__
- #define__febird_bdb_kmapdset_h__
- #ifdefined(_MSC_VER)&&(_MSC_VER>=1020)
- #pragmaonce
- #endif
- #include<db_cxx.h>
- #include"native_compare.h"
- #include"../io/DataIO.h"
- #include"../io/MemStream.h"
- #include"../refcount.h"
- namespacefebird{
- classFEBIRD_DLL_EXPORTkmapdset_iterator_impl_base:publicRefCounter
- {
- public:
- classkmapdset_base*m_owner;
- DBC*m_curp;
- intm_ret;
- DBTm_bulk;
- public:
- kmapdset_iterator_impl_base(classkmapdset_base*owner);
- voidinit(DB*dbp,DB_TXN*txn,constchar*func);
- virtual~kmapdset_iterator_impl_base();
- virtualvoidclear_vec()=0;
- virtualvoidpush_back(void*data,size_tsize)=0;
- virtualvoidload_key1(void*data,size_tsize)=0;
- virtualvoidsave_key1(PortableDataOutput<AutoGrownMemIO>&oKey)=0;
- boolnext_key(size_t*cnt,constchar*func);
- voidbulk_load(DBT*tk1);
- voidincrement(constchar*func);
- voiddecrement(constchar*func);
- boolfind_pos(constvoid*k1,constvoid*k2,boolbulk,constchar*func);
- boolinsert(constvoid*d,constchar*func);
- boolupdate(constvoid*d,constchar*func);
- boolreplace(constvoid*d,constchar*func);
- boolremove(constvoid*k2,constchar*func);
- boolremove(constchar*func);
- };
- classFEBIRD_DLL_EXPORTkmapdset_base
- {
- DECLARE_NONE_COPYABLE_CLASS(kmapdset_base)
- public:
- DB*m_db;
- size_tm_bulkSize;
- bt_compare_fcn_typem_bt_comp,m_dup_comp;
- kmapdset_base(DB_ENV*env,constchar*dbname
- ,DB_TXN*txn
- ,bt_compare_fcn_typebt_comp
- ,bt_compare_fcn_typedup_comp
- ,constchar*func
- );
- virtual~kmapdset_base();
- virtualvoidsave_key1(PortableDataOutput<AutoGrownMemIO>&dio,constvoid*key1)const=0;
- virtualvoidsave_key2(PortableDataOutput<AutoGrownMemIO>&dio,constvoid*key2)const=0;
- virtualvoidsave_data(PortableDataOutput<AutoGrownMemIO>&dio,constvoid*data)const=0;
- virtualkmapdset_iterator_impl_base*make_iter()=0;
- kmapdset_iterator_impl_base*begin_impl(DB_TXN*txn,constchar*func);
- kmapdset_iterator_impl_base*end_impl(DB_TXN*txn,constchar*func);
- kmapdset_iterator_impl_base*find_impl(constvoid*k1,u_int32_tflags,constchar*func);
- kmapdset_iterator_impl_base*find_impl(constvoid*k1,constchar*func);
- kmapdset_iterator_impl_base*upper_bound_impl(constvoid*k1,constchar*func);
- size_tcount_impl(constvoid*k1,constchar*func);
- boolinsert_impl(constvoid*k1,constvoid*d,constchar*func);
- boolreplace_impl(constvoid*k1,constchar*func);
- boolremove_impl(constvoid*k1,constchar*func);
- boolremove_impl(constvoid*k1,constchar*func);
- voidclear_impl(DB_TXN*txn,constchar*func);
- voidflush_impl(constchar*func);
- };
- template<classData>
- structkmapdset_select_key2
- {
- typedeftypenameData::key_typetype;
- };
- template<classKey2,classNonKeyData>
- structkmapdset_select_key2<std::pair<Key2,NonKeyData>>
- {
- typedefKey2type;
- };
- template<classKey1,classKey2,classData,classValue,classImpl>
- classkmapdset_iterator:
- publicstd::iterator<std::bidirectional_iterator_tag,Value,ptrdiff_t,constValue*,constValue&>
- {
- boost::intrusive_ptr<Impl>m_impl;
- voidcopy_on_write()
- {
- if(m_impl->getRefCount()>1)
- {
- Impl*p=newImpl(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
- //#pragmawarning(disable:4661)//declarationbutnotdefinition
- //!MSVCwillwarningC4661"declarationbutnotdefinition"
- voidoperator++(int){assert(0);}
- voidoperator--(int){assert(0);}
- #else
- //!disable,becausecloneiteratorwillcauseverymuchtimeandresource
- voidoperator++(int);//{assert(0);}
- voidoperator--(int);//{assert(0);}
- #endif
- public:
- kmapdset_iterator(){}
- explicitkmapdset_iterator(kmapdset_iterator_impl_base*impl)
- :m_impl(static_cast<Impl*>(impl))
- {
- assert(impl);
- assert(dynamic_cast<Impl*>(impl));
- }
- //boolexist()const{returnDB_NOTFOUND!=m_impl->m_ret&&DB_KEYEMPTY!=m_impl->m_ret;}
- boolexist()const{return0==m_impl->m_ret;}
- //incrementandgetkey/data-cnt
- boolnext_key(size_t&cnt){returnm_impl->next_key(&cnt,BOOST_CURRENT_FUNCTION);}
- boolinsert(constData&d){returnm_impl->insert(&d,BOOST_CURRENT_FUNCTION);}
- boolupdate(constData&d){returnm_impl->update(&d,BOOST_CURRENT_FUNCTION);}
- boolreplace(constData&d){returnm_impl->replace(&d,BOOST_CURRENT_FUNCTION);}
- boolremove()const{returnm_impl->remove(BOOST_CURRENT_FUNCTION);}
- boolremove(constKey2&k2)const{returnm_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;
- }
- constValue&operator*()const
- {
- assert(0==m_impl->m_ret);
- returnm_impl->m_kdv;
- }
- constValue*operator->()const
- {
- assert(0==m_impl->m_ret);
- return&m_impl->m_kdv;
- }
- Value&get_mutable()const
- {
- assert(0==m_impl->m_ret);
- returnm_impl->m_kdv;
- }
- };
- //!@paramDataKey2isembededinData
- template<classKey1,classData>
- classkmapdset:protectedkmapdset_base
- {
- DECLARE_NONE_COPYABLE_CLASS(kmapdset)
- public:
- typedefKey1
- key1_t,key_type;
- typedeftypenamekmapdset_select_key2<Data>::type
- key2_t;
- typedefData
- data_type,data_t;
- typedefstd::pair<Key1,std::vector<Data>>
- value_type;
- typedefstd::vector<Data>
- data_vec_t;
- typedeftypenamestd::vector<Data>::const_iterator
- data_iter_t;
- protected:
- classkmapdset_iterator_impl:publickmapdset_iterator_impl_base
- {
- public:
- value_typem_kdv;
- kmapdset_iterator_impl(kmapdset_base*owner)
- :kmapdset_iterator_impl_base(owner)
- {}
- virtualvoidclear_vec()
- {
- m_kdv.second.resize(0);
- }
- virtualvoidpush_back(void*data,size_tsize)
- {
- datax;
- PortableDataInput<MinMemIO>iData;
- iData.set(data);
- iData>>x;
- FEBIRD_RT_assert(iData.diff(data)==size,std::logic_error);
- m_kdv.second.push_back(x);
- }
- virtualvoidload_key1(void*data,size_tsize)
- {
- PortableDataInput<MemIO>iKey1;
- iKey1.set(data,size);
- iKey1>>m_kdv.first;
- FEBIRD_RT_assert(iKey1.diff(data)==size,std::logic_error);
- }
- virtualvoidsave_key1(PortableDataOutput<AutoGrownMemIO>&oKey1)
- {
- oKey1<<m_kdv.first;
- }
- };
- //!overrides
- voidsave_key1(PortableDataOutput<AutoGrownMemIO>&dio,constvoid*key1)const{dio<<*(constkey1_t*)key1;}
- voidsave_key2(PortableDataOutput<AutoGrownMemIO>&dio,constvoid*key2)const{dio<<*(constkey2_t*)key2;}
- voidsave_data(PortableDataOutput<AutoGrownMemIO>&dio,constvoid*data)const{dio<<*(constdata_t*)data;}
- kmapdset_iterator_impl_base*make_iter(){returnnewkmapdset_iterator_impl(this);}
- public:
- typedefkmapdset_iterator<Key1,key2_t,Data,value_type,kmapdset_iterator_impl>
- iterator,const_iterator;
- kmapdset(DB_ENV*env,constchar*dbname
- ,DB_TXN*txn=NULL
- ,bt_compare_fcn_typebt_comp=bdb_auto_bt_compare((key1_t*)(0))
- ,bt_compare_fcn_typedup_comp=bdb_auto_bt_compare((key2_t*)(0))
- )
- :kmapdset_base(env,dbname,txn,bt_comp,dup_comp,BOOST_CURRENT_FUNCTION)
- {
- }
- kmapdset(DbEnv*env,DbTxn*txn=NULL
- ,bt_compare_fcn_typedup_comp=bdb_auto_bt_compare((key2_t*)(0))
- )
- :kmapdset_base(env->get_DB_ENV(),txn?txn->get_DB_TXN():NULL,BOOST_CURRENT_FUNCTION)
- {
- }
- iteratorbegin(DB_TXN*txn=NULL){returniterator(begin_impl(txn,BOOST_CURRENT_FUNCTION));}
- iteratorend(DB_TXN*txn=NULL){returniterator(end_impl(txn,BOOST_CURRENT_FUNCTION));}
- iteratorbegin(DbTxn*txn){returniterator(begin_impl(txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION));}
- iteratorend(DbTxn*txn){returniterator(end_impl(txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION));}
- iteratorfind(constKey1&k1,DB_TXN*txn=NULL)
- {
- returniterator(find_impl(&k1,DB_SET|DB_MULTIPLE,BOOST_CURRENT_FUNCTION));
- }
- iteratorfind(constKey1&k1,DbTxn*txn)
- {
- returniterator(find_impl(&k1,txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION));
- }
- iteratorfind(constKey1&k1,constkey2_t&k2,DB_TXN*txn=NULL)
- {
- returniterator(find_impl(&k1,&k2,false,BOOST_CURRENT_FUNCTION));
- }
- iteratorfind(constKey1&k1,DbTxn*txn)
- {
- returniterator(find_impl(&k1,BOOST_CURRENT_FUNCTION));
- }
- iteratorfind_md(constKey1&k1,true,BOOST_CURRENT_FUNCTION));
- }
- iteratorfind_md(constKey1&k1,BOOST_CURRENT_FUNCTION));
- }
- iteratorlower_bound(constKey1&k1,DB_SET_RANGE|DB_MULTIPLE,BOOST_CURRENT_FUNCTION));
- }
- iteratorlower_bound(constKey1&k1,BOOST_CURRENT_FUNCTION));
- }
- iteratorupper_bound(constKey1&k1,DB_TXN*txn=NULL)
- {
- returniterator(upper_bound_impl(&k1,BOOST_CURRENT_FUNCTION));
- }
- boolinsert(constKey1&k1,constData&d,DB_TXN*txn=NULL)
- {
- returninsert_impl(&k1,&d,BOOST_CURRENT_FUNCTION);
- }
- boolinsert(constKey1&k1,DbTxn*txn)
- {
- returninsert_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- boolreplace(constKey1&k1,DB_TXN*txn=NULL)
- {
- returnreplace_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- boolreplace(constKey1&k1,DbTxn*txn)
- {
- returnreplace_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- boolremove(constKey1&k1,DB_TXN*txn=NULL)
- {
- returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- boolremove(constKey1&k1,DbTxn*txn)
- {
- returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- boolremove(constKey1&k1,DB_TXN*txn=NULL)
- {
- returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- boolremove(constKey1&k1,DbTxn*txn)
- {
- returnremove_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- boolerase(constiterator&iter)
- {
- returniter.remove();
- }
- voidclear(DB_TXN*txn=NULL)
- {
- clear_impl(txn,BOOST_CURRENT_FUNCTION);
- }
- voidclear(DbTxn*txn)
- {
- returnclear_impl(txn->get_DB_TXN(),BOOST_CURRENT_FUNCTION);
- }
- voidflush()
- {
- returnflush_impl(BOOST_CURRENT_FUNCTION);
- }
- size_tcount(constKey1&k1,DB_TXN*txn=NULL)
- {
- returncount_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- size_tcount(constKey1&k1,DbTxn*txn)
- {
- returncount_impl(&k1,BOOST_CURRENT_FUNCTION);
- }
- DB*getDB(){returnm_db;}
- constDB*getDB()const{returnm_db;}
- };
- }//namespacefebird
- #endif//__febird_bdb_kmapdset_h__
- /*vim:settabstop=4:*/
- #include"kmapdset.h"
- //#include"../DataBuffer.h"
- #include<sstream>
- namespacefebird{
- kmapdset_iterator_impl_base::kmapdset_iterator_impl_base(classkmapdset_base*owner)
- :m_owner(owner)
- ,m_curp(0),m_ret(-1)
- {
- memset(&m_bulk,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);
- }
- voidkmapdset_iterator_impl_base::init(DB*dbp,constchar*func)
- {
- intret=dbp->cursor(dbp,&m_curp,0);
- if(0!=ret)
- {
- deletethis;
- std::ostringstreamoss;
- oss<<db_strerror(ret)<<"...at:"<<func;
- throwstd::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);
- }
- boolkmapdset_iterator_impl_base::next_key(size_t*cnt,constchar*func)
- {
- FEBIRD_RT_assert(0==m_ret,std::logic_error);
- DBTtk1;memset(&tk1,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_tcnt0=0;
- intret=m_curp->count(m_curp,&cnt0,0);
- if(0!=ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(ret)<<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- *cnt=cnt0;
- returntrue;
- }
- elseif(DB_NOTFOUND==m_ret)
- {
- returnfalse;
- }
- else
- {
- std::ostringstreamoss;
- oss<<db_strerror(m_ret)<<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- }
- voidkmapdset_iterator_impl_base::bulk_load(DBT*tk1)
- {
- FEBIRD_RT_assert(0==m_ret,std::logic_error);
- load_key1(tk1->data,tk1->size);
- clear_vec();
- intret;
- do{
- void*bptr,*data;
- size_tsize;
- DB_MULTIPLE_INIT(bptr,&m_bulk);
- assert(NULL!=bptr);
- for(;;)
- {
- DB_MULTIPLE_NEXT(bptr,data,size);
- if(bptr)
- this->push_back(data,size);
- else
- break;
- }
- ret=m_curp->get(m_curp,tk1,DB_MULTIPLE|DB_NEXT_DUP);
- }while(0==ret);
- }
- voidkmapdset_iterator_impl_base::increment(constchar*func)
- {
- FEBIRD_RT_assert(0==m_ret,DB_NEXT_NODUP|DB_MULTIPLE);
- if(0==m_ret)
- {
- bulk_load(&tk1);
- }
- elseif(DB_NOTFOUND!=m_ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(m_ret)<<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- }
- voidkmapdset_iterator_impl_base::decrement(constchar*func)
- {
- FEBIRD_RT_assert(0==m_ret,std::logic_error);
- DBTtk1;memset(&tk1,sizeof(DBT));
- m_ret=m_curp->get(m_curp,DB_PREV_NODUP);
- if(0==m_ret)
- {
- m_ret=m_curp->get(m_curp,DB_CURRENT|DB_MULTIPLE);
- if(0==m_ret)
- {
- bulk_load(&tk1);
- }
- elseif(DB_KEYEMPTY==m_ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(m_ret)
- <<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- }
- elseif(DB_NOTFOUND!=m_ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(m_ret)<<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- }
- boolkmapdset_iterator_impl_base::find_pos(constvoid*k1,constchar*func)
- {
- PortableDataOutput<AutoGrownMemIO>oKey1,oKey2;
- m_owner->save_key1(oKey1,k1);
- m_owner->save_key2(oKey2,k2);
- DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
- DBTtk2;memset(&tk2,sizeof(DBT));tk2.data=oKey2.begin();tk2.size=oKey2.tell();
- m_ret=m_curp->get(m_curp,&tk2,DB_GET_BOTH);
- if(0==m_ret)
- {
- if(bulk){
- m_ret=m_curp->get(m_curp,DB_CURRENT|DB_MULTIPLE);
- if(0==m_ret){
- bulk_load(&tk1);
- returntrue;
- }
- }else{
- clear_vec();
- load_key1(tk1.data,tk1.size);
- push_back(tk2.data,tk2.size);
- returntrue;
- }
- }
- elseif(DB_NOTFOUND==m_ret)
- {
- returnfalse;
- }
- std::ostringstreamoss;
- oss<<db_strerror(m_ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- /**
- @brief
- @returntruesuccessfulinserted
- falsefail,(key1,d)existed,andnotinserted
- @throwothererrors
- */
- boolkmapdset_iterator_impl_base::insert(constvoid*d,constchar*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);
- DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
- DBTtdd;memset(&tdd,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
- intret=m_curp->put(m_curp,&tdd,DB_NODUPDATA);
- if(DB_KEYEXIST==ret)
- returnfalse;
- if(0==ret)
- returntrue;
- std::ostringstreamoss;
- oss<<db_strerror(m_ret)
- <<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- /**
- @brief
- @returntruesuccessfulupdated
- false(key1,d.key2)didnotexist,notupdated
- @throwothererrors
- */
- boolkmapdset_iterator_impl_base::update(constvoid*d,constchar*func)
- {
- FEBIRD_RT_assert(0==m_ret,std::logic_error);
- PortableDataOutput<AutoGrownMemIO>oKey1,oData;
- this->save_key1(oKey1);
- m_owner->save_data(oData,d);
- DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
- DBTtdd;memset(&tdd,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
- intret=m_curp->get(m_curp,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,DB_CURRENT);
- if(0==ret)
- returntrue;
- }
- elseif(DB_NOTFOUND==ret)
- {
- returnfalse;
- }
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- /**
- @brief
- @returntrueitemwasreplacedby(key1,d)
- falseitemwasinserted
- @throwothererrors
- */
- boolkmapdset_iterator_impl_base::replace(constvoid*d,constchar*func)
- {
- PortableDataOutput<AutoGrownMemIO>oKey1,DB_CURRENT);
- if(0==ret)
- returntrue;
- }
- elseif(DB_NOTFOUND==ret)
- {
- ret=m_curp->put(m_curp,DB_NODUPDATA);
- if(0==ret)
- returnfalse;
- }
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- boolkmapdset_iterator_impl_base::remove(constvoid*k2,oKey2;
- this->save_key1(oKey1);
- m_owner->save_key2(oKey2,sizeof(DBT));tdd.data=oKey2.begin();tdd.size=oKey2.tell();
- intret=m_curp->get(m_curp,DB_GET_BOTH);
- if(0==ret)
- ret=m_curp->del(m_curp,0);
- if(DB_KEYEMPTY==ret)
- returnfalse;
- if(0==ret)
- returntrue;
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- boolkmapdset_iterator_impl_base::remove(constchar*func)
- {
- FEBIRD_RT_assert(0==m_ret,std::logic_error);
- PortableDataOutput<AutoGrownMemIO>oKey1;
- this->save_key1(oKey1);
- DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
- intret=m_owner->m_db->del(m_owner->m_db,m_curp->txn,0);
- if(DB_NOTFOUND==ret)
- returnfalse;
- if(0==ret)
- returntrue;
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- //////////////////////////////////////////////////////////////////////////
- kmapdset_base::kmapdset_base(DB_ENV*env,DB_TXN*txn
- ,bt_compare_fcn_typebt_comp
- ,bt_compare_fcn_typedup_comp
- ,constchar*func
- )
- :m_bt_comp(0)
- {
- m_bulkSize=512*1024;
- m_db=0;
- intret=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);
- intflags=env->open_flags&(DB_THREAD|DB_MULTIVERSION|DB_AUTO_COMMIT);
- ret=m_db->open(m_db,DB_BTREE,DB_CREATE|flags,0);
- }
- if(0!=ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func;
- throwstd::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,constchar*func)
- {
- kmapdset_iterator_impl_base*iter=make_iter();
- iter->init(m_db,func);
- DBTtk1;memset(&tk1,sizeof(DBT));
- iter->m_ret=iter->m_curp->get(iter->m_curp,&iter->m_bulk,DB_FIRST|DB_MULTIPLE);
- if(0==iter->m_ret)
- {
- iter->bulk_load(&tk1);
- }
- elseif(DB_NOTFOUND!=iter->m_ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(iter->m_ret)
- <<"...at:"<<func;
- deleteiter;iter=0;
- throwstd::runtime_error(oss.str());
- }
- returniter;
- }
- kmapdset_iterator_impl_base*kmapdset_base::end_impl(DB_TXN*txn,constchar*func)
- {
- kmapdset_iterator_impl_base*iter=make_iter();
- iter->init(m_db,func);
- returniter;
- }
- kmapdset_iterator_impl_base*kmapdset_base::find_impl(constvoid*k1,constchar*func)
- {
- PortableDataOutput<AutoGrownMemIO>oKey1;
- save_key1(oKey1,k1);
- DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
- kmapdset_iterator_impl_base*iter=make_iter();
- iter->init(m_db,func);
- iter->m_ret=iter->m_curp->get(iter->m_curp,flags);
- if(0==iter->m_ret)
- {
- iter->bulk_load(&tk1);
- }
- elseif(DB_NOTFOUND!=iter->m_ret&&DB_KEYEMPTY!=iter->m_ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(iter->m_ret)
- <<"...at:"<<func
- <<"/n"
- <<"flags="<<flags
- ;
- throwstd::runtime_error(oss.str());
- }
- returniter;
- }
- kmapdset_iterator_impl_base*
- kmapdset_base::find_impl(constvoid*k1,func);
- try{
- boolbRet=iter->find_pos(k1,k2,bulk,func);
- returniter;
- }catch(std::exception&exp){
- deleteiter;iter=0;
- throwexp;
- }
- }
- kmapdset_iterator_impl_base*kmapdset_base::upper_bound_impl(constvoid*k1,constchar*func)
- {
- PortableDataOutput<AutoGrownMemIO>oKey1;
- save_key1(oKey1,k1);
- DBTtk1;memset(&tk1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
- kmapdset_iterator_impl_base*iter=make_iter();
- iter->init(m_db,func);
- iter->m_ret=iter->m_curp->get(iter->m_curp,DB_SET_RANGE|DB_MULTIPLE);
- if(0==iter->m_ret)
- {
- DBTkbak;memset(&kbak,sizeof(DBT));kbak.data=oKey1.begin();kbak.size=oKey1.tell();
- intcmp=m_bt_comp(m_db,&kbak,&tk1);
- assert(cmp<=0);
- if(0==cmp){
- iter->m_ret=iter->m_curp->get(iter->m_curp,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::ostringstreamoss;
- oss<<db_strerror(iter->m_ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- returniter;
- }
- size_tkmapdset_base::count_impl(constvoid*k1,constchar*func)
- {
- PortableDataOutput<AutoGrownMemIO>oKey1;
- try{
- save_key1(oKey1,k1);
- }
- catch(constIOException&exp)
- {
- std::ostringstreamoss;
- oss<<exp.what()<<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- DBTtk1;memset(&tk1,sizeof(DBT));
- DBC*curp=NULL;
- intret=m_db->cursor(m_db,&curp,0);
- if(0==ret)
- {
- ret=curp->get(curp,DB_SET);
- db_recno_tcount=0;
- if(0==ret)
- ret=curp->count(curp,&count,0);
- elseif(DB_NOTFOUND==ret)
- count=0,ret=0;//clearerror
- curp->close(curp);
- if(0!=ret)
- gotoErrorL;
- returncount;
- }
- ErrorL:
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- /**
- @briefinsertarecord
- @returntruesuccess,nosamek1-k2indb,therecordwasinserted
- falseFailed,hassamek1-k2indb,therecordwasnotinserted,notreplacedexistingyet
- @throwsexception,Failed
- */
- boolkmapdset_base::insert_impl(constvoid*k1,oData;
- try{
- save_key1(oKey1,k1);
- save_data(oData,d);
- }
- catch(constIOException&exp)
- {
- std::ostringstreamoss;
- oss<<exp.what()<<"...at:"<<func;
- throwstd::runtime_error(oss.str());
- }
- DBTtk1;memset(&tk1,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
- intret=m_db->put(m_db,DB_NODUPDATA);
- if(DB_KEYEXIST==ret)
- returnfalse;
- if(0==ret)
- returntrue;
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- /**
- @briefreplaceORinsertarecord
- @note
- ifnotthrownanexception,alwayssuccess
- @returntruereplacetherecord
- falseinserttherecord
- @throwsexception,Failed
- */
- boolkmapdset_base::replace_impl(constvoid*k1,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
- DBC*curp=NULL;
- intret=m_db->cursor(m_db,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,DB_CURRENT);
- curp->close(curp);
- if(0==ret)
- returntrue;
- }
- elseif(DB_NOTFOUND==ret)
- {
- ret=curp->put(curp,DB_NODUPDATA);
- curp->close(curp);
- if(0==ret)
- returnfalse;
- }
- }
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- /**
- @brief
- @returntrue(k1,k2)existed,removesuccess
- false(k1,k2)notexisted,nothingdone
- */
- boolkmapdset_base::remove_impl(constvoid*k1,oData;
- oData.resize(4*1024);
- save_key1(oKey1,k1);
- save_key2(oData,sizeof(DBT));tdd.data=oData.begin();tdd.size=oData.tell();
- DBC*curp=NULL;
- intret=m_db->cursor(m_db,0);
- if(0==ret)
- {
- ret=curp->get(curp,DB_GET_BOTH);
- if(0==ret){
- ret=curp->del(curp,0);
- }
- curp->close(curp);
- return0==ret;
- }
- else
- {
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- }
- /**
- @brief
- @returntrue(k1)existed,removesuccess
- false(k1)notexisted,nothingdone
- */
- boolkmapdset_base::remove_impl(constvoid*k1,sizeof(DBT));tk1.data=oKey1.begin();tk1.size=oKey1.tell();
- intret=m_db->del(m_db,0);
- if(DB_NOTFOUND==ret)
- returnfalse;
- if(0==ret)
- returntrue;
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- voidkmapdset_base::clear_impl(DB_TXN*txn,constchar*func)
- {
- u_int32_tcount;
- intret=m_db->truncate(m_db,0);
- if(0!=ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- }
- voidkmapdset_base::flush_impl(constchar*func)
- {
- intret=m_db->sync(m_db,0);
- if(0!=ret)
- {
- std::ostringstreamoss;
- oss<<db_strerror(ret)
- <<"...at:"<<func
- <<"/n"
- ;
- throwstd::runtime_error(oss.str());
- }
- }
- }//namespacefebird