Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-05-18 08:29:47

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_