|
||||
File indexing completed on 2025-01-17 09:55:19
0001 /*- 0002 * Copyright (c) 2009, 2020 Oracle and/or its affiliates. All rights reserved. 0003 * 0004 * See the file LICENSE for license information. 0005 * 0006 * $Id$ 0007 */ 0008 0009 #ifndef _DB_STL_DB_SET_H_ 0010 #define _DB_STL_DB_SET_H_ 0011 0012 0013 #include "dbstl_common.h" 0014 #include "dbstl_map.h" 0015 #include "dbstl_dbc.h" 0016 #include "dbstl_container.h" 0017 #include "dbstl_resource_manager.h" 0018 #include "dbstl_element_ref.h" 0019 #include "dbstl_base_iterator.h" 0020 0021 START_NS(dbstl) 0022 0023 using std::pair; 0024 using std::make_pair; 0025 0026 ///////////////////////////////////////////////////////////////////////// 0027 ///////////////////////////////////////////////////////////////////////// 0028 // 0029 // _DB_STL_set_value class template definition 0030 // This class is used for db_set as value type because it inherits from 0031 // db_map . It dose not need a byte for DB_HASH to work, hash db can store 0032 // duplicated keys with empty data. 0033 // 0034 template <Typename T> 0035 class _DB_STL_set_value 0036 { 0037 public: 0038 0039 inline _DB_STL_set_value(const ElementRef<T>&){ } 0040 inline _DB_STL_set_value(const T&){} 0041 inline _DB_STL_set_value(){} 0042 }; 0043 0044 /** \ingroup dbstl_iterators 0045 @{ 0046 \defgroup dbset_iterators Iterator classes for db_set and db_multiset. 0047 db_set_base_iterator and db_set_iterator are the const iterator and iterator 0048 class for db_set and db_multiset. They have identical behaviors to 0049 std::set::const_iterator and std::set::iterator respectively. 0050 0051 The difference between the two classes is that the db_set_base_iterator 0052 can only be used to read its referenced value, while db_set_iterator allows 0053 both read and write access. If the access pattern is readonly, it is strongly 0054 recommended that you use the const iterator because it is faster and more 0055 efficient. 0056 0057 The two classes inherit several functions from db_map_base_iterator and 0058 db_map_iterator respectively. 0059 \sa db_map_base_iterator db_map_iterator 0060 0061 @{ 0062 */ 0063 0064 ///////////////////////////////////////////////////////////////////////// 0065 ///////////////////////////////////////////////////////////////////////// 0066 // 0067 // db_set_base_iterator class template definition 0068 // 0069 // db_set_base_iterator class template is the const iterator class for db_set 0070 // and db_multiset, it can only be used to read data. 0071 // This class need to override operator* and operator-> because the 0072 // db_set<>::value_type is different from db_map<>::value_type. We also has 0073 // to copy the iterator movement operators into this class because the "self" 0074 // type is different in db_map_base_iterator and this class. 0075 // In db_set_base_iterator's inherited curpair_base_ pair, we store key to 0076 // its first and second member, to work with db_map and db_multimap. 0077 // Besides this, there is no further difference, so we can still safely make 0078 // use of its inherited methods. 0079 // 0080 template <Typename kdt> 0081 class _exported db_set_base_iterator : public 0082 db_map_base_iterator<kdt, kdt, _DB_STL_set_value<kdt> > 0083 { 0084 protected: 0085 typedef db_set_base_iterator<kdt> self; 0086 typedef db_map_base_iterator<kdt, kdt, _DB_STL_set_value<kdt> > base; 0087 using db_base_iterator<kdt>::replace_current_key; 0088 public: 0089 0090 typedef kdt key_type; 0091 typedef _DB_STL_set_value<kdt> ddt; 0092 typedef kdt value_type; 0093 typedef value_type& reference; 0094 typedef value_type* pointer; 0095 typedef value_type value_type_wrap; 0096 typedef ptrdiff_t difference_type; 0097 typedef difference_type distance_type; 0098 // We have to use std iterator tags to match the parameter list of 0099 // stl internal functions, so we don't need to write our own tag 0100 // classes 0101 // 0102 typedef std::bidirectional_iterator_tag iterator_category; 0103 0104 //////////////////////////////////////////////////////////////// 0105 // Begin constructors and destructor definitions. 0106 // 0107 /// \name Constructors and destructor 0108 /// Do not use these constructors to create iterators, but call 0109 /// db_set::begin() const or db_multiset::begin() const to create 0110 /// valid iterators. 0111 //@{ 0112 /// Destructor. 0113 virtual ~db_set_base_iterator() 0114 { 0115 0116 } 0117 0118 /// Constructor. 0119 /// \param powner The container which creates this iterator. 0120 /// \param b_bulk_retrieval The bulk read buffer size. 0 means 0121 /// bulk read disabled. 0122 /// \param brmw Whether set DB_RMW flag in underlying cursor. 0123 /// \param directdbget Whether do direct database get rather than 0124 /// using key/data values cached in the iterator whenever read. 0125 /// \param b_read_only Whether open a read only cursor. Only effective 0126 /// when using Berkeley DB Concurrent Data Store. 0127 explicit db_set_base_iterator(db_container*powner, 0128 u_int32_t b_bulk_retrieval = 0, bool brmw = false, 0129 bool directdbget = true, bool b_read_only = false) 0130 : base(powner, b_bulk_retrieval, brmw, directdbget, b_read_only) 0131 { 0132 this->is_set_ = true; 0133 } 0134 0135 /// Default constructor, dose not create the cursor for now. 0136 db_set_base_iterator() : base() 0137 { 0138 this->is_set_ = true; 0139 } 0140 0141 /// Copy constructor. 0142 /// \param s The other iterator of the same type to initialize this. 0143 db_set_base_iterator(const db_set_base_iterator&s) : base(s) 0144 { 0145 this->is_set_ = true; 0146 } 0147 0148 /// Base copy constructor. 0149 /// \param bo Initialize from a base class iterator. 0150 db_set_base_iterator(const base& bo) : base(bo) 0151 { 0152 this->is_set_ = true; 0153 } 0154 //@} 0155 //////////////////////////////////////////////////////////////// 0156 0157 //////////////////////////////////////////////////////////////// 0158 // Begin functions that shift iterator positions. 0159 /// \name Iterator movement operators. 0160 /// These functions are identical to those of db_map_base_iterator 0161 /// and db_map_iterator and db_set_iterator. Actually the iterator 0162 /// movement functions in the four classes are the same. 0163 //@{ 0164 // But we have to copy them into the four classes because the 0165 // return type, namely "self" is different in each class. 0166 /// Post-increment. 0167 /// \return This iterator after incremented. 0168 /// \sa db_map_base_iterator::operator++() 0169 inline self& operator++() 0170 { 0171 this->next(); 0172 0173 return *this; 0174 } 0175 0176 /// Pre-increment. 0177 /// \return Another iterator having the old value of this iterator. 0178 /// \sa db_map_base_iterator::operator++(int) 0179 inline self operator++(int) 0180 { 0181 self itr = *this; 0182 0183 this->next(); 0184 0185 return itr; 0186 } 0187 0188 /// Post-decrement. 0189 /// \return This iterator after decremented. 0190 /// \sa db_map_base_iterator::operator--() 0191 inline self& operator--() 0192 { 0193 this->prev(); 0194 0195 return *this; 0196 } 0197 0198 /// Pre-decrement. 0199 /// \return Another iterator having the old value of this iterator. 0200 /// \sa db_map_base_iterator::operator--(int) 0201 self operator--(int) 0202 { 0203 self itr = *this; 0204 this->prev(); 0205 0206 return itr; 0207 } 0208 //@} 0209 //////////////////////////////////////////////////////////////// 0210 0211 //////////////////////////////////////////////////////////////// 0212 // Begin functions that retrieve values from iterator. 0213 // 0214 // This function returns a read only reference, you can only read 0215 // its referenced data, not update it. 0216 // curpair_base_ is always kept updated on iterator movement, but it 0217 // is also updated here before making use of the value it points 0218 // to, which is stored in curpair_base_ . 0219 // Even if this iterator is invalid, this call is allowed, the 0220 // default value of type T is returned. 0221 // 0222 /// \name Functions that retrieve values from iterator. 0223 //@{ 0224 /// Dereference operator. 0225 /// Return the reference to the cached data element, which is an 0226 /// object of type T. You can only use the return value to read 0227 /// its referenced data element, can not update it. 0228 /// \return Current data element reference object, i.e. ElementHolder 0229 /// or ElementRef object. 0230 inline reference operator*() 0231 { 0232 int ret; 0233 0234 if (this->directdb_get_) { 0235 ret = this->pcsr_->get_current_key( 0236 this->curpair_base_.first); 0237 dbstl_assert(ret == 0); 0238 // curpair_base_.second is a _DB_STL_set_value<kdt> object, 0239 // not used at all. Since const iterators can't be used to 0240 // write, so this is not a problem. 0241 } 0242 // Returning reference, no copy construction. 0243 return this->curpair_base_.first; 0244 } 0245 0246 // curpair_base_ is always kept updated on iterator movement, but it 0247 // is also updated here before making use of the value it points 0248 // to, which is stored in curpair_base_ . 0249 // Even if this iterator is invalid, this call is allowed, the 0250 // default value of type T is returned. 0251 /// Arrow operator. 0252 /// Return the pointer to the cached data element, which is an 0253 /// object of type T. You can only use the return value to read 0254 /// its referenced data element, can not update it. 0255 /// \return Current data element reference object's address, i.e. 0256 /// address of ElementHolder or ElementRef object. 0257 inline pointer operator->() const 0258 { 0259 int ret; 0260 0261 if (this->directdb_get_) { 0262 ret = this->pcsr_->get_current_key( 0263 this->curpair_base_.first); 0264 dbstl_assert(ret == 0); 0265 } 0266 0267 return &(this->curpair_base_.first); 0268 } 0269 //@} 0270 //////////////////////////////////////////////////////////////// 0271 0272 /// \brief Refresh iterator cached value. 0273 /// \param from_db If not doing direct database get and this parameter 0274 /// is true, we will retrieve data directly from db. 0275 /// \sa db_base_iterator::refresh(bool) 0276 virtual int refresh(bool from_db = true) const 0277 { 0278 0279 if (from_db && !this->directdb_get_) 0280 this->pcsr_->update_current_key_data_from_db( 0281 DbCursorBase::SKIP_NONE); 0282 this->pcsr_->get_current_key(this->curpair_base_.first); 0283 this->curpair_base_.second = this->curpair_base_.first; 0284 return 0; 0285 } 0286 0287 protected: 0288 0289 // Declare friend classes to access protected/private members, 0290 // while expose to outside only methods in stl specifications. 0291 // 0292 friend class db_set<kdt>; 0293 0294 friend class db_map<kdt, _DB_STL_set_value<kdt>, 0295 ElementHolder<kdt>, self>; 0296 friend class db_map<kdt, _DB_STL_set_value<kdt>, 0297 ElementRef<kdt>, self>; 0298 0299 typedef pair<kdt, value_type> curpair_type; 0300 0301 }; // db_set_base_iterator 0302 0303 0304 ///////////////////////////////////////////////////////////////////////// 0305 ///////////////////////////////////////////////////////////////////////// 0306 // 0307 // db_set_iterator class template definition 0308 // 0309 // db_set_iterator class template is the iterator class for db_set and 0310 // db_multiset, it can be used to update its referenced key/data pair. 0311 // This class need to override operator* and operator-> because the 0312 // db_set<>::value_type is different from db_map<>::value_type. besides 0313 // this, there is no further difference, so we can still safely make 0314 // use of db_set inherited methods. 0315 // 0316 template <Typename kdt, Typename value_type_sub> 0317 class _exported db_set_iterator : 0318 public db_map_iterator<kdt, _DB_STL_set_value<kdt>, value_type_sub> 0319 { 0320 protected: 0321 typedef db_set_iterator<kdt, value_type_sub> self; 0322 typedef db_map_iterator<kdt, _DB_STL_set_value<kdt>, 0323 value_type_sub> base; 0324 0325 public: 0326 0327 typedef kdt key_type; 0328 typedef _DB_STL_set_value<kdt> ddt; 0329 typedef kdt value_type; 0330 typedef value_type_sub value_type_wrap; 0331 typedef value_type_sub& reference; 0332 typedef value_type_sub* pointer; 0333 typedef ptrdiff_t difference_type; 0334 typedef difference_type distance_type; 0335 // We have to use std iterator tags to match the parameter list of 0336 // stl internal functions, so we don't need to write our own tag 0337 // classes 0338 // 0339 typedef std::bidirectional_iterator_tag iterator_category; 0340 0341 //////////////////////////////////////////////////////////////// 0342 // Begin constructors and destructor definitions. 0343 /// \name Constructors and destructor 0344 /// Do not use these constructors to create iterators, but call 0345 /// db_set::begin() or db_multiset::begin() to create valid ones. 0346 //@{ 0347 /// Destructor. 0348 virtual ~db_set_iterator() 0349 { 0350 0351 } 0352 0353 /// Constructor. 0354 /// \param powner The container which creates this iterator. 0355 /// \param b_bulk_retrieval The bulk read buffer size. 0 means 0356 /// bulk read disabled. 0357 /// \param brmw Whether set DB_RMW flag in underlying cursor. 0358 /// \param directdbget Whether do direct database get rather than 0359 /// using key/data values cached in the iterator whenever read. 0360 /// \param b_read_only Whether open a read only cursor. Only effective 0361 /// when using Berkeley DB Concurrent Data Store. 0362 explicit db_set_iterator(db_container*powner, 0363 u_int32_t b_bulk_retrieval = 0, bool brmw = false, 0364 bool directdbget = true, bool b_read_only = false) 0365 : base(powner, b_bulk_retrieval, brmw, directdbget, b_read_only) 0366 { 0367 this->is_set_ = true; 0368 } 0369 0370 /// Default constructor, dose not create the cursor for now. 0371 db_set_iterator() : base() 0372 { 0373 this->is_set_ = true; 0374 } 0375 0376 /// Copy constructor. 0377 /// \param s The other iterator of the same type to initialize this. 0378 db_set_iterator(const db_set_iterator&s) : base(s) 0379 { 0380 this->is_set_ = true; 0381 } 0382 0383 /// Base copy constructor. 0384 /// \param bo Initialize from a base class iterator. 0385 db_set_iterator(const base& bo) : base(bo) 0386 { 0387 this->is_set_ = true; 0388 } 0389 0390 /// Sibling copy constructor. 0391 /// Note that this class does not derive from db_set_base_iterator 0392 /// but from db_map_iterator. 0393 /// \param bs Initialize from a base class iterator. 0394 db_set_iterator(const db_set_base_iterator<kdt>&bs) : base(bs) 0395 { 0396 this->is_set_ = true; 0397 } 0398 //@} 0399 //////////////////////////////////////////////////////////////// 0400 0401 //////////////////////////////////////////////////////////////// 0402 // Begin functions that shift iterator positions. 0403 /// \name Iterator movement operators. 0404 //@{ 0405 /// Pre-increment. 0406 /// Identical to those of db_map_iterator. 0407 /// \return This iterator after incremented. 0408 /// \sa db_map_iterator::operator++() 0409 inline self& operator++() 0410 { 0411 this->next(); 0412 0413 return *this; 0414 } 0415 0416 /// Post-increment. 0417 /// \return Another iterator having the old value of this iterator. 0418 /// \sa db_map_iterator::operator++(int) 0419 inline self operator++(int) 0420 { 0421 self itr = *this; 0422 0423 this->next(); 0424 0425 return itr; 0426 } 0427 0428 /// Pre-decrement. 0429 /// \return This iterator after decremented. 0430 /// \sa db_map_iterator::operator--() 0431 inline self& operator--() 0432 { 0433 this->prev(); 0434 0435 return *this; 0436 } 0437 0438 /// Post-decrement 0439 /// \return Another iterator having the old value of this iterator. 0440 /// \sa db_map_iterator::operator--(int) 0441 self operator--(int) 0442 { 0443 self itr = *this; 0444 this->prev(); 0445 0446 return itr; 0447 } 0448 //@} 0449 //////////////////////////////////////////////////////////////// 0450 0451 //////////////////////////////////////////////////////////////// 0452 // Begin functions that retrieve values from iterator. 0453 // 0454 // This functions returns a read-write reference to its data element. 0455 // Even if this iterator is invalid, this call is allowed, the 0456 // default value of type T is returned. 0457 /// \name Functions that retrieve values from iterator. 0458 //@{ 0459 /// Dereference operator. 0460 /// Return the reference to the cached data element, which is an 0461 /// ElementRef<T> object if T is a class type or an ElementHolder<T> 0462 /// object if T is a C++ primitive data type. 0463 /// \return Current data element reference object, i.e. ElementHolder 0464 /// or ElementRef object. 0465 inline reference operator*() 0466 { 0467 0468 if (this->directdb_get_) 0469 refresh(true); 0470 // returning reference, no copy construction 0471 return this->curpair_.second; 0472 } 0473 0474 // curpair_ is always kept updated on iterator movement, but it 0475 // is also updated here before making use of the value it points 0476 // to, which is stored in curpair_ . 0477 // Even if this iterator is invalid, this call is allowed, the 0478 // default value of type T is returned. 0479 /// Arrow operator. 0480 /// Return the pointer to the cached data element, which is an 0481 /// ElementRef<T> object if T is a class type or an ElementHolder<T> 0482 /// object if T is a C++ primitive data type. 0483 /// \return Current data element reference object's address, i.e. 0484 /// address of ElementHolder or ElementRef object. 0485 inline pointer operator->() const 0486 { 0487 0488 if (this->directdb_get_) 0489 refresh(true); 0490 0491 return &(this->curpair_.second); 0492 } 0493 //@} 0494 //////////////////////////////////////////////////////////////// 0495 0496 /// \brief Refresh iterator cached value. 0497 /// \param from_db If not doing direct database get and this parameter 0498 /// is true, we will retrieve data directly from db. 0499 /// \sa db_base_iterator::refresh(bool) 0500 virtual int refresh(bool from_db = true) const 0501 { 0502 0503 if (from_db && !this->directdb_get_) 0504 this->pcsr_->update_current_key_data_from_db( 0505 DbCursorBase::SKIP_NONE); 0506 this->pcsr_->get_current_key(this->curpair_.first); 0507 this->curpair_.second._DB_STL_CopyData(this->curpair_.first); 0508 this->set_curpair_base(this->curpair_.first, this->curpair_.first); 0509 return 0; 0510 } 0511 0512 protected: 0513 typedef pair<kdt, value_type_sub> curpair_type; 0514 typedef db_set_base_iterator<kdt> const_version; 0515 // Declare friend classes to access protected/private members, 0516 // while expose to outside only methods in stl specifications. 0517 // 0518 friend class db_set<kdt, ElementHolder<kdt> >; 0519 friend class db_set<kdt, ElementRef<kdt> >; 0520 friend class db_multiset<kdt, ElementHolder<kdt> >; 0521 friend class db_multiset<kdt, ElementRef<kdt> >; 0522 friend class db_map<kdt, _DB_STL_set_value<kdt>, 0523 ElementHolder<kdt>, self>; 0524 friend class db_multimap<kdt, _DB_STL_set_value<kdt>, 0525 ElementHolder<kdt>, self>; 0526 friend class db_map<kdt, _DB_STL_set_value<kdt>, 0527 ElementRef<kdt>, self>; 0528 friend class db_multimap<kdt, _DB_STL_set_value<kdt>, 0529 ElementRef<kdt>, self>; 0530 0531 virtual void delete_me() const 0532 { 0533 delete this; 0534 } 0535 0536 }; // db_set_iterator 0537 //@} // dbset_iterators 0538 //@} // dbstl_iterators 0539 0540 ///////////////////////////////////////////////////////////////////////// 0541 ///////////////////////////////////////////////////////////////////////// 0542 // 0543 // db_set class template definition 0544 // 0545 // db_set<> inherits from db_map<>, storing nothing data, because 0546 // we only need the key. It uses db_set_iterator<>/db_set_base_iterator 0547 // as its iterator and const iterator respectively. 0548 // The only difference between db_set<> and db_map<> classes 0549 // is the value_type, so we redefine the insert function by directly copying 0550 // the db_map<>::insert, in order to make use of the newly defined 0551 // value_type of db_set. If typedef could be dynamically bound, we won't 0552 // have to make this duplicated effort. 0553 /// \ingroup dbstl_containers 0554 /// This class is the combination of std::set and hash_set. By setting 0555 /// database handles of DB_BTREE or DB_HASH type, you will be using the 0556 /// equivalent of std::set or hash_set. This container stores the key in the 0557 /// key element of a key/data pair in the underlying database, 0558 /// but doesn't store anything in the data element. 0559 /// Database and environment handle requirement: 0560 /// The same as that of db_map. 0561 /// \param kdt The key data type. 0562 /// \param value_type_sub If kdt is a class/struct type, do not specify 0563 /// anything in this parameter; Otherwise specify ElementHolder<kdt>. 0564 /// \sa db_map db_container 0565 // 0566 template <Typename kdt, Typename value_type_sub> 0567 class _exported db_set : public db_map<kdt, _DB_STL_set_value<kdt>, 0568 value_type_sub, db_set_iterator<kdt, value_type_sub> > 0569 { 0570 protected: 0571 typedef db_set<kdt, value_type_sub> self; 0572 public: 0573 typedef db_set_iterator<kdt, value_type_sub> iterator; 0574 typedef typename iterator::const_version const_iterator; 0575 typedef db_reverse_iterator<iterator, const_iterator> reverse_iterator; 0576 typedef db_reverse_iterator<const_iterator, iterator> 0577 const_reverse_iterator; 0578 typedef kdt key_type; 0579 typedef ptrdiff_t difference_type; 0580 // the ElementRef should store key value because key is also data, 0581 // and *itr is key and data value 0582 // 0583 typedef kdt value_type; 0584 typedef value_type_sub value_type_wrap; 0585 typedef value_type_sub* pointer; 0586 typedef value_type_sub& reference; 0587 typedef value_type& const_reference; 0588 typedef size_t size_type; 0589 0590 //////////////////////////////////////////////////////////////// 0591 // Begin constructors and destructor. 0592 /// \name Constructors and destructor 0593 //@{ 0594 /// Create a std::set/hash_set equivalent associative container. 0595 /// See the handle requirement in class details to pass correct 0596 /// database/environment handles. 0597 /// \param dbp The database handle. 0598 /// \param envp The database environment handle. 0599 /// \sa db_map(Db*, DbEnv*) db_container(Db*, DbEnv*) 0600 explicit db_set (Db *dbp = NULL, DbEnv* envp = NULL) : base(dbp, envp){ 0601 // There are some special handling in db_map_iterator<> 0602 // if owner is set. 0603 this->set_is_set(true); 0604 } 0605 0606 /// Iteration constructor. Iterates between first and last, 0607 /// copying each of the elements in the range into 0608 /// this container. 0609 /// Create a std::set/hash_set equivalent associative container. 0610 /// Insert a range of elements into the database. The range is 0611 /// [first, last), which contains elements that can 0612 /// be converted to type ddt automatically. 0613 /// This function supports auto-commit. 0614 /// See the handle requirement in class details to pass correct 0615 /// database/environment handles. 0616 /// \param dbp The database handle. 0617 /// \param envp The database environment handle. 0618 /// \param first The closed boundary of the range. 0619 /// \param last The open boundary of the range. 0620 /// \sa db_map(Db*, DbEnv*, InputIterator, InputIterator) 0621 template <class InputIterator> 0622 db_set (Db *dbp, DbEnv* envp, InputIterator first, 0623 InputIterator last) : base(*(new BulkRetrievalOption( 0624 BulkRetrievalOption::BulkRetrieval))) 0625 { 0626 0627 const char *errmsg; 0628 0629 this->init_members(dbp, envp); 0630 this->open_db_handles(dbp, envp, DB_BTREE, 0631 DB_CREATE | DB_THREAD, 0); 0632 if ((errmsg = this->verify_config(dbp, envp)) != NULL) { 0633 THROW(InvalidArgumentException, ("Db*", errmsg)); 0634 } 0635 this->set_db_handle_int(dbp, envp); 0636 this->set_auto_commit(dbp); 0637 this->begin_txn(); 0638 try { 0639 insert(first, last); 0640 } catch (...) { 0641 this->abort_txn(); 0642 throw; 0643 } 0644 this->commit_txn(); 0645 // There are some special handling in db_map_iterator<> 0646 // if owner is set. 0647 this->set_is_set(true); 0648 0649 } 0650 0651 /// Copy constructor. 0652 /// Create a database and insert all key/data pairs in x into this 0653 /// container. x's data members are not copied. 0654 /// This function supports auto-commit. 0655 /// \param x The source container to initialize this container. 0656 /// \sa db_map(const db_map&) db_container(const db_container&) 0657 db_set(const self& x) : base(*(new BulkRetrievalOption( 0658 BulkRetrievalOption::BulkRetrieval))) 0659 { 0660 this->init_members(x); 0661 this->verify_db_handles(x); 0662 this->set_db_handle_int(this->clone_db_config( 0663 x.get_db_handle()), x.get_db_env_handle()); 0664 assert(this->get_db_handle() != NULL); 0665 0666 this->begin_txn(); 0667 try { 0668 copy_db((self&)x); 0669 } catch (...) { 0670 this->abort_txn(); 0671 throw; 0672 } 0673 this->commit_txn(); 0674 // There are some special handling in db_map_iterator<> 0675 // if owner is set. 0676 this->set_is_set(true); 0677 } 0678 0679 virtual ~db_set(){} 0680 //@} 0681 //////////////////////////////////////////////////////////////// 0682 0683 /// Container content assignment operator. 0684 /// This function supports auto-commit. 0685 /// \param x The source container whose key/data pairs will be 0686 /// inserted into the target container. Old content in the target 0687 /// container is discarded. 0688 /// \return The container x's reference. 0689 /// \sa http://www.cplusplus.com/reference/stl/set/operator=/ 0690 const self& operator=(const self& x) 0691 { 0692 ASSIGNMENT_PREDCOND(x) 0693 db_container::operator =(x); 0694 this->verify_db_handles(x); 0695 assert(this->get_db_handle() != NULL); 0696 this->begin_txn(); 0697 try { 0698 this->copy_db((self &)x); 0699 } catch (...) { 0700 this->abort_txn(); 0701 throw; 0702 } 0703 this->commit_txn(); 0704 return x; 0705 } 0706 0707 //////////////////////////////////////////////////////////////// 0708 // Begin key/value compare classes/functions. 0709 // 0710 // key_compare class definition, it is defined as an inner class, 0711 // using underlying btree/hash db's compare function. It is the same 0712 // as that of db_map<>, but because we have to redefine value_compare 0713 // in this class, gcc forces us to also define key_compare again. 0714 class key_compare 0715 { 0716 private: 0717 Db*pdb; 0718 public: 0719 key_compare(Db*pdb1) 0720 { 0721 pdb = pdb1; 0722 } 0723 bool operator()(const kdt& k1, const kdt& k2) const 0724 { 0725 return db_set::compare_keys(pdb, k1, k2, NULL); 0726 } 0727 0728 }; // key_compare class definition 0729 0730 class value_compare 0731 { 0732 key_compare kc; 0733 public: 0734 value_compare(Db*pdb) : kc(pdb) 0735 { 0736 0737 } 0738 0739 bool operator()(const value_type& v1, 0740 const value_type& v2) const 0741 { 0742 0743 return kc(v1, v2); 0744 } 0745 0746 }; // value_compare class definition 0747 0748 /// Get value comparison functor. 0749 /// \return The value comparison functor. 0750 /// \sa http://www.cplusplus.com/reference/stl/set/value_comp/ 0751 inline value_compare value_comp() const 0752 { 0753 return value_compare(this->get_db_handle()); 0754 } 0755 //////////////////////////////////////////////////////////////// 0756 0757 //////////////////////////////////////////////////////////////// 0758 // Begin insert functions and swap function. 0759 // 0760 // Note that when secondary index is enabled, each db_container 0761 // can create a db_multimap secondary container, but the insert 0762 // function is not functional. 0763 // 0764 // Insert functions. Note that stl requires if the entry with x.key 0765 // already exists, insert should not overwrite that entry and the 0766 // insert should fail; but bdb Dbc::cursor(DB_KEYLAST) will replace 0767 // existing data with new one, so we will first find whether we 0768 // have this data, if have, return false; 0769 /// \name Insert Functions 0770 /// \sa http://www.cplusplus.com/reference/stl/set/insert/ 0771 //@{ 0772 /// Insert a single key/data pair if the key is not in the container. 0773 /// \param x The key/data pair to insert. 0774 /// \return A pair P, if insert OK, i.e. the inserted key wasn't in the 0775 /// container, P.first will be the iterator positioned on the inserted 0776 /// key/data pair, and P.second is true; otherwise P.first is an invalid 0777 /// iterator equal to that returned by end() and P.second is false. 0778 pair<iterator,bool> insert (const value_type& x ) 0779 { 0780 pair<iterator,bool> ib; 0781 0782 _DB_STL_set_value<kdt> sv; 0783 iterator witr; 0784 0785 this->init_itr(witr); 0786 this->open_itr(witr); 0787 0788 if (witr.move_to(x) == 0) {// has it 0789 ib.first = witr; 0790 ib.second = false; 0791 0792 return ib; 0793 } 0794 witr.itr_status_ = witr.pcsr_->insert(x, sv, DB_KEYLAST); 0795 witr.refresh(false); 0796 ib.first = witr; 0797 ib.second = true; 0798 0799 return ib; 0800 } 0801 0802 // NOT_AUTOCOMMIT_TAG 0803 // Note that if first and last are on same db as this container, 0804 // then insert may deadlock if there is no common transaction context 0805 // for first and witr (when they are on the same page). 0806 // The insert function in base class can not be directly used, 0807 // got compile errors. 0808 /// Range insertion. Insert a range [first, last) of key/data pairs 0809 /// into this container. 0810 /// \param first The closed boundary of the range. 0811 /// \param last The open boundary of the range. 0812 inline void insert (const_iterator& first, const_iterator& last) 0813 { 0814 const_iterator ii; 0815 _DB_STL_set_value<kdt> v; 0816 iterator witr; 0817 0818 this->init_itr(witr); 0819 this->open_itr(witr); 0820 0821 for (ii = first; ii != last; ++ii) 0822 witr.pcsr_->insert(*ii, v, DB_KEYLAST); 0823 } 0824 0825 /// Range insertion. Insert a range [first, last) of key/data pairs 0826 /// into this container. 0827 /// \param first The closed boundary of the range. 0828 /// \param last The open boundary of the range. 0829 void insert (iterator& first, iterator& last) 0830 { 0831 iterator ii, witr; 0832 _DB_STL_set_value<kdt> d; 0833 0834 this->init_itr(witr); 0835 this->open_itr(witr); 0836 0837 for (ii = first; ii != last; ++ii) 0838 witr.pcsr_->insert(*ii, d, DB_KEYLAST); 0839 0840 } 0841 0842 // Ignore the position parameter because bdb knows better 0843 // where to insert. 0844 /// Insert with hint position. We ignore the hint position because 0845 /// Berkeley DB knows better where to insert. 0846 /// \param position The hint position. 0847 /// \param x The key/data pair to insert. 0848 /// \return The iterator positioned on the inserted key/data pair, 0849 /// or an invalid iterator if the key was already in the container. 0850 inline iterator insert ( iterator position, const value_type& x ) 0851 { 0852 pair<iterator,bool> ib = insert(x); 0853 return ib.first; 0854 } 0855 0856 /// Range insertion. Insert a range [first, last) of key/data pairs 0857 /// into this container. 0858 /// \param first The closed boundary of the range. 0859 /// \param last The open boundary of the range. 0860 template <class InputIterator> 0861 void insert (InputIterator first, InputIterator last) 0862 { 0863 InputIterator ii; 0864 _DB_STL_set_value<kdt> v; 0865 iterator witr; 0866 0867 this->init_itr(witr); 0868 this->open_itr(witr); 0869 0870 for (ii = first; ii != last; ++ii) 0871 witr.pcsr_->insert(*ii, v, DB_KEYLAST); 0872 0873 } 0874 //@} 0875 0876 /// Swap content with another container. 0877 /// This function supports auto-commit. 0878 /// \param mp The container to swap content with. 0879 /// \param b_truncate See db_vector::swap's b_truncate parameter 0880 /// for details. 0881 /// \sa db_map::swap() db_vector::clear() 0882 void swap (db_set<kdt, value_type_sub>& mp, bool b_truncate = true) 0883 { 0884 Db *swapdb = NULL; 0885 std::string dbfname(64, '\0'); 0886 0887 this->verify_db_handles(mp); 0888 this->begin_txn(); 0889 try { 0890 swapdb = this->clone_db_config(this->get_db_handle(), 0891 dbfname); 0892 0893 db_set<kdt, value_type_sub> tmap(swapdb, 0894 swapdb->get_env(), this->begin(), this->end()); 0895 typename db_set<kdt, value_type_sub>:: 0896 iterator itr1, itr2; 0897 0898 this->clear(b_truncate);// Clear this db_map<> object. 0899 itr1 = mp.begin(); 0900 itr2 = mp.end(); 0901 this->insert(itr1, itr2); 0902 mp.clear(b_truncate); 0903 itr1 = tmap.begin(); 0904 itr2 = tmap.end(); 0905 mp.insert(itr1, itr2); 0906 // tmap has no opened cursor, so simply truncate. 0907 tmap.clear(); 0908 0909 swapdb->close(0); 0910 if (dbfname[0] != '\0') { 0911 swapdb = new Db(NULL, DB_CXX_NO_EXCEPTIONS); 0912 swapdb->remove(dbfname.c_str(), NULL, 0); 0913 swapdb->close(0); 0914 delete swapdb; 0915 } 0916 this->commit_txn(); 0917 } catch (...) { 0918 this->abort_txn(); 0919 throw; 0920 } 0921 0922 } 0923 //////////////////////////////////////////////////////////////// 0924 0925 //////////////////////////////////////////////////////////////// 0926 // Begin container comparison functions. 0927 // 0928 // Return true if contents in m1 and m2 are identical otherwise 0929 // return false. 0930 // 0931 // Note that we don't require the keys' order be identical, we are 0932 // doing mathmatical set comparisons. 0933 /// Set content equality comparison operator. 0934 /// Return if the two containers have identical content. This function 0935 /// does not rely on key order. 0936 /// Two sets A and B are equal if and only if A contains B and B 0937 /// contains A. 0938 /// \param m2 The container to compare against. 0939 /// \return Returns true if the two containers are equal, 0940 /// false otherwise. 0941 // 0942 bool operator==(const db_set<kdt, value_type_sub>& m2) const 0943 { 0944 bool ret; 0945 0946 COMPARE_CHECK(m2) 0947 this->verify_db_handles(m2); 0948 const db_set<kdt, value_type_sub>& m1 = *this; 0949 0950 try { 0951 this->begin_txn(); 0952 if (m1.size() != m2.size()) 0953 ret = false; 0954 else { 0955 typename db_set<kdt, value_type_sub>:: 0956 const_iterator i1; 0957 0958 for (i1 = m1.begin(); i1 != m1.end(); ++i1) { 0959 if (m2.count(*i1) == 0) { 0960 ret = false; 0961 goto exit; 0962 } 0963 0964 } // for 0965 ret = true; 0966 } // else 0967 exit: 0968 this->commit_txn(); 0969 // Now that m1 and m2 has the same number of unique elements and 0970 // all elements of m1 are in m2, thus there can be no element of m2 0971 // that dose not belong to m1, so we won't verify each element of 0972 // m2 are in m1. 0973 return ret; 0974 } catch (...) { 0975 this->abort_txn(); 0976 throw; 0977 } 0978 }// operator== 0979 0980 /// Inequality comparison operator. 0981 bool operator!=(const db_set<kdt, value_type_sub>& m2) const 0982 { 0983 return !this->operator==(m2); 0984 } 0985 //////////////////////////////////////////////////////////////// 0986 0987 protected: 0988 typedef int (*db_compare_fcn_t)(Db *db, const Dbt *dbt1, 0989 const Dbt *dbt2, size_t *locp); 0990 0991 0992 typedef db_map<kdt, _DB_STL_set_value<kdt>, value_type_sub, 0993 db_set_iterator<kdt, value_type_sub> > base; 0994 private: 0995 0996 value_type_sub operator[] (const key_type& x) 0997 { 0998 THROW(NotSupportedException, ("db_set<>::operator[]")); 0999 1000 } 1001 1002 value_type_sub operator[] (const key_type& x) const 1003 { 1004 THROW(NotSupportedException, ("db_set<>::operator[]")); 1005 1006 } 1007 1008 inline void copy_db(db_set<kdt, value_type_sub> &x) 1009 { 1010 1011 // Make sure clear can succeed if there are cursors 1012 // open in other threads. 1013 this->clear(false); 1014 insert(x.begin(), x.end()); 1015 1016 } 1017 1018 }; // db_set<> 1019 1020 1021 ///////////////////////////////////////////////////////////////////////// 1022 ///////////////////////////////////////////////////////////////////////// 1023 // 1024 // db_multiset class template definition 1025 // 1026 // db_multiset<> inherits from db_multimap, storing nothing as data, because 1027 // we only need the key. It uses db_set_iterator<> and db_set_base_iterator<> 1028 // as its iterator and const iterator respectively, so that 1029 // we can safely make use of the inherited methods. The only difference 1030 // is the value_type, so we redefine the insert functions by directly copying 1031 // the db_map<>::insert versions, in order to make use of the newly defined 1032 // value_type of db_multiset. If typedef could be dynamically bound, we won't 1033 // have to make this duplicated effort. 1034 /// \ingroup dbstl_containers 1035 /// This class is the combination of std::multiset and hash_multiset. By 1036 /// setting database handles of DB_BTREE or DB_HASH type respectively, you 1037 /// will be using the equivalent of std::multiset or hash_multiset respectively. 1038 /// This container stores the key in the key element of a key/data pair in 1039 /// the underlying database, but doesn't store anything in the data element. 1040 /// Database and environment handle requirement: 1041 /// The requirement to these handles is the same as that to db_multimap. 1042 /// \param kdt The key data type. 1043 /// \param value_type_sub If kdt is a class/struct type, do not specify 1044 /// anything in this parameter; Otherwise specify ElementHolder<kdt>. 1045 /// \sa db_multimap db_map db_container db_set 1046 // 1047 template <Typename kdt, Typename value_type_sub> 1048 class _exported db_multiset : public db_multimap<kdt, _DB_STL_set_value<kdt>, 1049 value_type_sub, db_set_iterator<kdt, value_type_sub> > 1050 { 1051 protected: 1052 typedef db_multiset<kdt, value_type_sub> self; 1053 public: 1054 typedef db_set_iterator<kdt, value_type_sub> iterator; 1055 typedef typename iterator::const_version const_iterator; 1056 typedef db_reverse_iterator<iterator, const_iterator> reverse_iterator; 1057 typedef db_reverse_iterator<const_iterator, iterator> 1058 const_reverse_iterator; 1059 typedef kdt key_type; 1060 typedef ptrdiff_t difference_type; 1061 // The ElementRef should store key value because key is also data, 1062 // and *itr is key and data value. 1063 // 1064 typedef kdt value_type; 1065 typedef value_type_sub value_type_wrap; 1066 typedef value_type_sub& reference; 1067 typedef const value_type& const_reference; 1068 typedef value_type_sub* pointer; 1069 typedef size_t size_type; 1070 1071 public: 1072 //////////////////////////////////////////////////////////////// 1073 // Begin constructors and destructor. 1074 /// \name Constructors and destructor 1075 //@{ 1076 /// Create a std::multiset/hash_multiset equivalent associative 1077 /// container. 1078 /// See the handle requirement in class details to pass correct 1079 /// database/environment handles. 1080 /// \param dbp The database handle. 1081 /// \param envp The database environment handle. 1082 /// \sa db_multimap(Db*, DbEnv*) 1083 explicit db_multiset (Db *dbp = NULL, DbEnv* envp = NULL) : 1084 base(dbp, envp) { 1085 // There are special handling in db_map_iterator<> if owner 1086 // is a set. 1087 this->set_is_set(true); 1088 } 1089 1090 /// Iteration constructor. Iterates between first and last, 1091 /// copying each of the elements in the range into 1092 /// this container. 1093 /// Create a std::multi/hash_multiset equivalent associative container. 1094 /// Insert a range of elements into the database. The range is 1095 /// [first, last), which contains elements that can 1096 /// be converted to type ddt automatically. 1097 /// This function supports auto-commit. 1098 /// See the handle requirement in class details to pass correct 1099 /// database/environment handles. 1100 /// \param dbp The database handle. 1101 /// \param envp The database environment handle. 1102 /// \param first The closed boundary of the range. 1103 /// \param last The open boundary of the range. 1104 /// \sa db_multimap(Db*, DbEnv*, InputIterator, InputIterator) 1105 template <class InputIterator> 1106 db_multiset (Db *dbp, DbEnv* envp, InputIterator first, 1107 InputIterator last) : base(*(new BulkRetrievalOption( 1108 BulkRetrievalOption::BulkRetrieval))) 1109 { 1110 1111 const char *errmsg; 1112 1113 this->init_members(dbp, envp); 1114 this->open_db_handles(dbp, envp, DB_BTREE, DB_CREATE | 1115 DB_THREAD, DB_DUP); 1116 // Note that we can't call base(dbp, envp) here because it 1117 // will verify failed; And we can't call db_container 1118 // directly because it is illegal to do so. 1119 if ((errmsg = verify_config(dbp, envp)) != NULL) { 1120 THROW(InvalidArgumentException, ("Db*", errmsg)); 1121 1122 } 1123 this->set_db_handle_int(dbp, envp); 1124 this->set_auto_commit(dbp); 1125 1126 this->begin_txn(); 1127 try { 1128 insert(first, last); 1129 } catch (...) { 1130 this->abort_txn(); 1131 throw; 1132 } 1133 this->commit_txn(); 1134 1135 // There are special handling in db_map_iterator<> if owner 1136 // is a set. 1137 this->set_is_set(true); 1138 1139 } 1140 1141 /// Copy constructor. 1142 /// Create a database and insert all key/data pairs in x into this 1143 /// container. x's data members are not copied. 1144 /// This function supports auto-commit. 1145 /// \param x The source container to initialize this container. 1146 /// \sa db_multimap(const db_multimap&) db_container(const db_container&) 1147 db_multiset(const self& x) : base(*(new BulkRetrievalOption( 1148 BulkRetrievalOption::BulkRetrieval))) 1149 { 1150 this->init_members(x); 1151 this->verify_db_handles(x); 1152 this->set_db_handle_int(this->clone_db_config( 1153 x.get_db_handle()), x.get_db_env_handle()); 1154 assert(this->get_db_handle() != NULL); 1155 1156 this->begin_txn(); 1157 try { 1158 copy_db((self&)x); 1159 } catch (...) { 1160 this->abort_txn(); 1161 throw; 1162 } 1163 this->commit_txn(); 1164 1165 // There are special handling in db_map_iterator<> if owner 1166 // is a set. 1167 this->set_is_set(true); 1168 } 1169 1170 virtual ~db_multiset(){} 1171 //@} 1172 //////////////////////////////////////////////////////////////// 1173 1174 //////////////////////////////////////////////////////////////// 1175 // Begin functions that modify the container's content, i.e. insert, 1176 // erase, assignment and swap functions. 1177 // 1178 /// Container content assignment operator. 1179 /// This function supports auto-commit. 1180 /// \param x The source container whose key/data pairs will be 1181 /// inserted into the target container. Old content in the target 1182 /// container is discarded. 1183 /// \return The container x's reference. 1184 /// \sa http://www.cplusplus.com/reference/stl/multiset/operator=/ 1185 inline const self& operator=(const self& x) 1186 { 1187 ASSIGNMENT_PREDCOND(x) 1188 db_container::operator =(x); 1189 this->verify_db_handles(x); 1190 assert(this->get_db_handle() != NULL); 1191 this->begin_txn(); 1192 try { 1193 this->copy_db((self &)x); 1194 } catch (...) { 1195 this->abort_txn(); 1196 throw; 1197 } 1198 this->commit_txn(); 1199 return x; 1200 } 1201 1202 // Note that when secondary index is enabled, each db_container 1203 // can create a db_multimap secondary container, but the insert 1204 // function is not functional. 1205 /// \name Insert Functions 1206 /// \sa http://www.cplusplus.com/reference/stl/multiset/insert/ 1207 //@{ 1208 /// Insert a single key if the key is not in the container. 1209 /// \param x The key to insert. 1210 /// \return An iterator positioned on the newly inserted key. If the 1211 /// key x already exists, an invalid iterator equal to that returned 1212 /// by end() function is returned. 1213 inline iterator insert(const value_type& x ) 1214 { 1215 pair<iterator,bool> ib; 1216 _DB_STL_set_value<kdt> sv; 1217 iterator witr; 1218 1219 this->init_itr(witr); 1220 this->open_itr(witr); 1221 1222 witr.itr_status_ = witr.pcsr_->insert(x, sv, DB_KEYLAST); 1223 witr.refresh(false); 1224 return witr; 1225 } 1226 1227 // Ignore the position parameter because bdb knows better 1228 // where to insert. 1229 /// Insert a single key with hint if the key is not in the container. 1230 /// The hint position is ignored because Berkeley DB controls where 1231 /// to insert the key. 1232 /// \param x The key to insert. 1233 /// \param position The hint insert position, ignored. 1234 /// \return An iterator positioned on the newly inserted key. If the 1235 /// key x already exists, an invalid iterator equal to that returned 1236 /// by end() function is returned. 1237 inline iterator insert ( iterator position, const value_type& x ) 1238 { 1239 return insert(x); 1240 } 1241 1242 /// Range insertion. Insert a range [first, last) of key/data pairs 1243 /// into this container. 1244 /// \param first The closed boundary of the range. 1245 /// \param last The open boundary of the range. 1246 template <class InputIterator> 1247 void insert (InputIterator first, InputIterator last) 1248 { 1249 InputIterator ii; 1250 _DB_STL_set_value<kdt> v; 1251 1252 iterator witr; 1253 1254 this->init_itr(witr); 1255 this->open_itr(witr); 1256 for (ii = first; ii != last; ++ii) 1257 witr.pcsr_->insert(*ii, v, DB_KEYLAST); 1258 1259 } 1260 1261 // Member function template overload. 1262 // This function is a specialization for the member template version 1263 // dedicated to db_set<>. 1264 // 1265 /// Range insertion. Insert a range [first, last) of key/data pairs 1266 /// into this container. 1267 /// \param first The closed boundary of the range. 1268 /// \param last The open boundary of the range. 1269 void insert (db_set_iterator<kdt, value_type_sub>& first, 1270 db_set_iterator<kdt, value_type_sub>& last) 1271 { 1272 db_set_iterator<kdt, value_type_sub> ii; 1273 iterator witr; 1274 _DB_STL_set_value<kdt> d; 1275 1276 this->init_itr(witr); 1277 this->open_itr(witr); 1278 1279 for (ii = first; ii != last; ++ii) 1280 witr.pcsr_->insert(*ii, d, DB_KEYLAST); 1281 1282 1283 } 1284 1285 // Member function template overload. 1286 // This function is a specialization for the member template version 1287 // dedicated to db_set<>. 1288 // 1289 /// Range insertion. Insert a range [first, last) of key/data pairs 1290 /// into this container. 1291 /// \param first The closed boundary of the range. 1292 /// \param last The open boundary of the range. 1293 void insert (db_set_base_iterator<kdt>& first, 1294 db_set_base_iterator<kdt>& last) 1295 { 1296 db_set_base_iterator<kdt> ii; 1297 iterator witr; 1298 _DB_STL_set_value<kdt> d; 1299 1300 this->init_itr(witr); 1301 this->open_itr(witr); 1302 1303 for (ii = first; ii != last; ++ii) 1304 witr.pcsr_->insert(*ii, d, DB_KEYLAST); 1305 } 1306 //@} 1307 1308 // There is identical function in db_multimap<> and db_multiset 1309 // for this function, we MUST keep the code consistent on update! 1310 // Go to db_multimap<>::erase(const key_type&) to see why. 1311 /// \name Erase Functions 1312 /// \sa http://www.cplusplus.com/reference/stl/multiset/erase/ 1313 //@{ 1314 /// Erase elements by key. 1315 /// All key/data pairs with specified key x will be removed from 1316 /// the underlying database. 1317 /// This function supports auto-commit. 1318 /// \param x The key to remove from the container. 1319 /// \return The number of key/data pairs removed. 1320 size_type erase (const key_type& x) 1321 { 1322 size_type cnt; 1323 iterator itr; 1324 1325 this->begin_txn(); 1326 try { 1327 pair<iterator, iterator> rg = this->equal_range(x); 1328 for (itr = rg.first, cnt = 0; 1329 itr != rg.second; ++itr) { 1330 cnt++; 1331 itr.pcsr_->del(); 1332 } 1333 } catch (...) { 1334 this->abort_txn(); 1335 throw; 1336 } 1337 this->commit_txn(); 1338 return cnt; 1339 } 1340 1341 // Can not reopen external/outside iterator's cursor, pos must 1342 // already have been in a transactional context. 1343 // There is identical function in db_multimap<> and db_multiset 1344 // for this function, we MUST keep the code consistent on update! 1345 // Go to db_multimap<>::erase(const key_type&) to see why. 1346 // 1347 /// Erase a key/data pair at specified position. 1348 /// \param pos A valid iterator of this container to erase. 1349 inline void erase (iterator pos) 1350 { 1351 if (pos == this->end()) 1352 return; 1353 pos.pcsr_->del(); 1354 } 1355 1356 // Can not be auto commit because first and last are already open. 1357 // There is identical function in db_multimap<> and db_multiset 1358 // for this function, we MUST keep the code consistent on update! 1359 // Go to db_multimap<>::erase(const key_type&) to see why. 1360 // 1361 /// Range erase. Erase all key/data pairs within the valid range 1362 /// [first, last). 1363 /// \param first The closed boundary of the range. 1364 /// \param last The open boundary of the range. 1365 inline void erase (iterator first, iterator last) 1366 { 1367 iterator i; 1368 1369 for (i = first; i != last; ++i) 1370 i.pcsr_->del(); 1371 } 1372 //@} 1373 1374 /// Swap content with another container. 1375 /// This function supports auto-commit. 1376 /// \param mp The container to swap content with. 1377 /// \param b_truncate See db_multimap::swap() for details. 1378 /// \sa db_map::swap() db_vector::clear() 1379 void swap (db_multiset<kdt, value_type_sub>& mp, bool b_truncate = true) 1380 { 1381 Db *swapdb = NULL; 1382 std::string dbfname(64, '\0'); 1383 1384 this->verify_db_handles(mp); 1385 this->begin_txn(); 1386 try { 1387 swapdb = this->clone_db_config(this->get_db_handle(), 1388 dbfname); 1389 1390 db_multiset<kdt, value_type_sub> tmap(swapdb, 1391 swapdb->get_env(), this->begin(), this->end()); 1392 this->clear(b_truncate);// Clear this db_map<> object. 1393 typename db_multiset<kdt, value_type_sub>:: 1394 iterator itr1, itr2; 1395 itr1 = mp.begin(); 1396 itr2 = mp.end(); 1397 this->insert(itr1, itr2); 1398 mp.clear(b_truncate); 1399 itr1 = tmap.begin(); 1400 itr2 = tmap.end(); 1401 mp.insert(itr1, itr2); 1402 1403 tmap.clear(); 1404 1405 swapdb->close(0); 1406 if (dbfname[0] != '\0') { 1407 swapdb = new Db(NULL, DB_CXX_NO_EXCEPTIONS); 1408 swapdb->remove(dbfname.c_str(), NULL, 0); 1409 swapdb->close(0); 1410 delete swapdb; 1411 } 1412 this->commit_txn(); 1413 1414 } catch (...) { 1415 swapdb->close(0); 1416 this->abort_txn(); 1417 throw; 1418 } 1419 1420 } 1421 //////////////////////////////////////////////////////////////// 1422 1423 //////////////////////////////////////////////////////////////// 1424 // Begin container comparison functions. 1425 // 1426 // Compare two db_multiset containers for equality, containers 1427 // containing identical set of keys are considered equal, keys' 1428 // order are not presumed or relied upon by this comparison. 1429 /// Container content equality compare operator. 1430 /// This function does not rely on key order. 1431 /// Two sets A and B are equal if and only if 1432 /// for each and every key K having n occurrences in A, K has n 1433 /// occurrences in B, and for each and every key K` having N 1434 /// occurrences in B, K` has n occurrences in A. 1435 /// \param m2 The container to compare against. 1436 /// \return Returns true if the two containers are equal, 1437 /// false otherwise. 1438 bool operator==(const self& m2) const 1439 { 1440 COMPARE_CHECK(m2) 1441 this->verify_db_handles(m2); 1442 1443 const db_multiset<kdt, value_type_sub> &m1 = *this; 1444 const_iterator i1, i11; 1445 pair<const_iterator, const_iterator> resrg1, resrg2; 1446 size_t n1, n2; 1447 bool ret = false; 1448 1449 try { 1450 this->begin_txn(); 1451 if (m1.size() != m2.size()) 1452 ret = false; 1453 else { 1454 for (i1 = m1.begin(); i1 != m1.end(); ) { 1455 resrg1 = m1.equal_range_N(*i1, n1); 1456 resrg2 = m2.equal_range_N(*i1, n2); 1457 if (n1 != n2) { 1458 ret = false; 1459 goto exit; 1460 } 1461 1462 // If both is 1, resrg2 may contain no i1->first. 1463 if (n2 == 1 && !(*(resrg2.first) == 1464 *(resrg1.first))) { 1465 ret = false; 1466 goto exit; 1467 } 1468 // m1 and m2 contains identical set of i1->first key, 1469 // so move on, skip all equal keys in the range. 1470 // 1471 i1 = resrg1.second; 1472 1473 } // for 1474 ret = true; 1475 1476 }// else 1477 exit: 1478 this->commit_txn(); 1479 return ret; 1480 } catch (...) { 1481 this->abort_txn(); 1482 throw; 1483 } 1484 1485 // Now that m1 and m2 has the same number of unique elements and all 1486 // elements of m1 are in m2, thus there can be no element of m2 that 1487 // dose not belong to m1, so we won't verify each element of m2 are 1488 // in m1. 1489 1490 } // operator== 1491 1492 /// Inequality comparison operator. 1493 bool operator!=(const self& m2) const 1494 { 1495 return !this->operator==(m2); 1496 } 1497 //////////////////////////////////////////////////////////////// 1498 1499 protected: 1500 1501 typedef int (*db_compare_fcn_t)(Db *db, const Dbt *dbt1, 1502 const Dbt *dbt2, size_t *locp); 1503 typedef db_multimap<kdt, _DB_STL_set_value<kdt>, 1504 value_type_sub, db_set_iterator<kdt, value_type_sub> > base; 1505 1506 // Declare base our friend, we can't use 'friend class base' to do 1507 // this declaration on gcc. 1508 friend class db_multimap<kdt, _DB_STL_set_value<kdt>, 1509 value_type_sub, db_set_iterator<kdt, value_type_sub> >; 1510 // Declare iterator our friend, we can't use 'friend class iterator' 1511 // to do this declaration on gcc. 1512 friend class db_set_iterator<kdt, value_type_sub>; 1513 friend class db_map_iterator<kdt, _DB_STL_set_value<kdt>, 1514 value_type_sub>; 1515 friend class db_map_iterator<kdt, _DB_STL_set_value<kdt> >; 1516 1517 private: 1518 1519 inline void copy_db(db_multiset<kdt, value_type_sub> &x) 1520 { 1521 1522 // Make sure clear can succeed if there are cursors 1523 // open in other threads. 1524 this->clear(false); 1525 insert(x.begin(), x.end()); 1526 1527 } 1528 1529 // Prevent user calling the inherited version. 1530 value_type operator[] (const key_type& x) 1531 { 1532 THROW(NotSupportedException, ("db_multiset<>::operator[]")); 1533 1534 } 1535 1536 value_type operator[] (const key_type& x) const 1537 { 1538 THROW(NotSupportedException, ("db_multiset<>::operator[]")); 1539 1540 } 1541 1542 virtual const char* verify_config(Db*dbp, DbEnv* envp) const 1543 { 1544 DBTYPE dbtype; 1545 u_int32_t oflags, sflags; 1546 int ret; 1547 const char *err = NULL; 1548 1549 err = db_container::verify_config(dbp, envp); 1550 if (err) 1551 return err; 1552 1553 BDBOP(dbp->get_type(&dbtype), ret); 1554 BDBOP(dbp->get_open_flags(&oflags), ret); 1555 BDBOP(dbp->get_flags(&sflags), ret); 1556 1557 if (dbtype != DB_BTREE && dbtype != DB_HASH) 1558 err = 1559 "wrong database type, only DB_BTREE and DB_HASH allowed for db_map<> class"; 1560 if (oflags & DB_TRUNCATE) 1561 err = 1562 "do not specify DB_TRUNCATE flag to create a db_map<> object"; 1563 1564 // Must set DB_DUP and NOT DB_DUPSORT. 1565 if (!(sflags & DB_DUP) || (sflags & DB_DUPSORT)) 1566 err = 1567 "db_multiset<> requires a database with DB_DUP set and without DB_DUPSORT set."; 1568 1569 if (sflags & DB_RECNUM) 1570 err = "no DB_RECNUM flag allowed in db_map<>"; 1571 1572 return err; 1573 1574 } 1575 1576 }; // db_multiset<> 1577 1578 1579 END_NS 1580 1581 #endif// !_DB_STL_DB_SET_H_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |