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_MAP_H_
0010 #define _DB_STL_DB_MAP_H_
0011 
0012 #include <string>
0013 
0014 #include "dbstl_common.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 using std::string;
0026 // Forward declarations, DO NOT delete the default argument values
0027 // because class templates defintions need them. No need for _export here.
0028 //
0029 template <Typename T>
0030 class _DB_STL_set_value;
0031 
0032 template <Typename kdt, Typename ddt, Typename value_type_sub = 
0033     ElementRef<ddt> >
0034 class db_map_iterator;
0035 
0036 template <Typename kdt, Typename ddt, Typename value_type_sub = 
0037     ElementRef<ddt>, Typename iterator_t = 
0038     db_map_iterator<kdt, ddt, value_type_sub> >
0039 class db_map;
0040 
0041 template<Typename kdt, Typename ddt, Typename value_type_sub = 
0042     ElementRef<ddt>, Typename iterator_t = 
0043     db_map_iterator<kdt, ddt, value_type_sub> >
0044 class db_multimap;
0045 
0046 template <Typename kdt>
0047 class db_set_base_iterator;
0048 
0049 template <Typename kdt, Typename value_type_sub = ElementRef<kdt> >
0050 class db_set_iterator;
0051 
0052 template <Typename kdt, Typename value_type_sub = ElementRef<kdt> >
0053 class db_set;
0054 
0055 template <Typename kdt, Typename value_type_sub = ElementRef<kdt> >
0056 class db_multiset;
0057 
0058 #if NO_MEMBER_FUNCTION_PARTIAL_SPECIALIZATION
0059 template <Typename kdt, Typename datadt, Typename value_type_sub>
0060 void assign_second0(pair<kdt, value_type_sub>& v, const datadt& d) ;
0061 #endif
0062 
0063 /** \ingroup dbstl_iterators
0064 @{
0065 \defgroup db_map_iterators Iterator classes for db_map and db_multimap.
0066 db_map has two iterator class templates -- db_map_base_iterator and
0067 db_map_iterator. They are the const iterator class and iterator class for
0068 db_map and db_multimap. db_map_iterator inherits from db_map_base_iterator.
0069 
0070 The two classes have identical behaviors to std::map::const_iterator and
0071 std::map::iterator respectively. Note that the common public member function
0072 behaviors are described in the db_base_iterator section.
0073 
0074 The differences between the two classes are that the db_map_base_iterator can 
0075 only be used to read its referenced value, while db_map_iterator allows both 
0076 read and write access. If your access pattern is readonly, it is strongly 
0077 recommended that you use the const iterator because it is faster and more 
0078 efficient.
0079 @{
0080 */
0081 //////////////////////////////////////////////////////////////////////
0082 // db_map_base_iterator class definition
0083 //
0084 // This class is a const iterator class for db_map and db_multimap, it can
0085 // be used only to read data under the iterator, can't be used to write.
0086 //
0087 // Iterator const-ness implementation:
0088 //
0089 // const iterators can not update key/data pairs, other than this, 
0090 // they can do anything else like non-const iterators, so we define
0091 // db_map_base_iterator to be the const iterator which can only be used
0092 // to read its underlying key/data pair, but not updating them; We 
0093 // derive the db_map_iterator from the base iterator to be the 
0094 // read-write iterator. We also maintain a "readonly" property in all
0095 // iterators so that users can specify a db_map_iterator to be
0096 // read only. db_map_base_iterator is more efficient to read data then
0097 // db_map_iterator, so read only accesses are strongly recommended to be 
0098 // done using a const iterator.
0099 //
0100 template <Typename kdt, Typename ddt, Typename csrddt = ddt>
0101 class _exported db_map_base_iterator : public 
0102     db_base_iterator<ddt>
0103 {
0104 protected:
0105     typedef db_map_base_iterator<kdt, ddt, csrddt> self;
0106     typedef db_base_iterator<ddt> base;
0107     using base::replace_current_key;
0108 public:
0109     typedef kdt key_type;
0110     typedef ddt data_type;
0111     typedef pair<kdt, ddt> value_type;
0112     // Not used in this class, but required to satisfy 
0113     // db_reverse_iterator type extraction.
0114     typedef ptrdiff_t difference_type;
0115     typedef difference_type distance_type;
0116     typedef value_type& reference;
0117     typedef value_type* pointer;
0118     typedef value_type value_type_wrap;
0119     // We have to use standard iterator tags to match the parameter 
0120     // list of stl internal functions, we can't use our own tag 
0121     // classes, so we don't write tag classes in dbstl.
0122     //
0123     typedef std::bidirectional_iterator_tag iterator_category;
0124 
0125     ////////////////////////////////////////////////////////////////////
0126     //
0127     // Begin public constructors and destructor.
0128     /// @name Constructors and destructor
0129     /// Do not create iterators directly using these constructors, but
0130     /// call db_map::begin or db_multimap_begin to get instances of
0131     /// this class.
0132     /// \sa db_map::begin() db_multimap::begin()
0133     //@{
0134     /// Copy constructor.
0135     /// \param vi The other iterator of the same type to initialize this.
0136     db_map_base_iterator(const self& vi)
0137         : db_base_iterator<ddt>(vi)
0138     {
0139         // Lazy-dup another cursor, cursor to iterator mapping 
0140         // is 1 to 1.
0141         pcsr_ = vi.pcsr_;
0142         curpair_base_.first = vi.curpair_base_.first;
0143         curpair_base_.second = vi.curpair_base_.second;
0144     }
0145 
0146     /// Base copy constructor.
0147     /// \param vi Initialize from a base class iterator.
0148     db_map_base_iterator(const base& vi) : base(vi), 
0149         pcsr_(new cursor_type(vi.get_bulk_retrieval(), 
0150         vi.is_rmw(), vi.is_directdb_get()))
0151     {
0152         
0153     }
0154     
0155     /// Constructor.
0156     /// \param powner The container which creates this iterator.
0157     /// \param b_bulk_retrieval The bulk read buffer size. 0 means 
0158     /// bulk read disabled.
0159     /// \param rmw Whether set DB_RMW flag in underlying cursor.
0160     /// \param directdbget Whether do direct database get rather than
0161     /// using key/data values cached in the iterator whenever read.
0162     /// \param readonly Whether open a read only cursor. Only effective 
0163     /// when using Berkeley DB Concurrent Data Store.
0164     explicit db_map_base_iterator(db_container*powner, 
0165         u_int32_t b_bulk_retrieval = 0, bool rmw = false, 
0166         bool directdbget = true, bool readonly = false)
0167         : db_base_iterator<ddt>(
0168         powner, directdbget, readonly, b_bulk_retrieval, rmw),
0169         pcsr_(new cursor_type(b_bulk_retrieval, rmw, directdbget)) 
0170     {   
0171     }
0172 
0173     /// Default constructor, dose not create the cursor for now.
0174     db_map_base_iterator()
0175     {
0176     }
0177 
0178     // Use virtual because ElementRef<> uses a db_base_iterator* pointer
0179     // to refer to the iterator, and also use "dead_" flag to avoid 
0180     // multiple calls to the same destructor by ~ElementRef<>().
0181     /// Destructor.
0182     virtual ~db_map_base_iterator() 
0183     {
0184         this->dead_ = true;
0185         if (pcsr_)
0186             pcsr_->close(); 
0187     }
0188     //@}
0189 
0190     ////////////////////////////////////////////////////////////////////
0191 
0192     ////////////////////////////////////////////////////////////////////
0193     // Begin functions that shift iterator position.
0194     //
0195     // Do not throw exceptions here because it is likely and normal 
0196     // to iterate to the "end iterator". 
0197     //
0198     /// @name Iterator increment movement functions.
0199     /// The two functions moves the iterator one element backward, so that
0200     /// the element it sits on has a bigger key. The btree/hash key
0201     /// comparison routine determines which key is greater.
0202     /// Use ++iter rather than iter++ where possible to avoid two useless
0203     /// iterator copy constructions.
0204     //@{
0205     /// Pre-increment.
0206     /// \return This iterator after incremented.
0207     inline self& operator++()
0208     {
0209         next();
0210         
0211         return *this;
0212     }
0213 
0214     /// Post-increment.
0215     /// \return Another iterator having the old value of this iterator.
0216     inline self operator++(int)
0217     {
0218         self itr = *this;
0219 
0220         next();
0221         
0222         return itr;
0223     }
0224     //@}
0225 
0226     /// @name Iterator decrement movement functions.
0227     /// The two functions moves the iterator one element forward, so that
0228     /// the element it sits on has a smaller key. The btree/hash key 
0229     /// comparison routine determines which key is greater.
0230     /// Use --iter rather than iter-- where possible to avoid two useless
0231     /// iterator copy constructions.
0232     //@{
0233     /// Pre-decrement.
0234     /// \return This iterator after decremented.
0235     inline  self& operator--() 
0236     {
0237         prev();
0238         
0239         return *this;
0240     }
0241 
0242     /// Post-decrement.
0243     /// \return Another iterator having the old value of this iterator.
0244     self operator--(int)
0245     {
0246         self itr = *this;
0247         prev();
0248         
0249         return itr;
0250     }
0251     //@}
0252 
0253     /// Assignment operator. This iterator will point to the same key/data
0254     /// pair as itr, and have the same configurations as itr.
0255     /// \param itr The right value of assignment.
0256     /// \return The reference of itr.
0257     /// \sa db_base_iterator::operator=(const self&)
0258     // We will duplicate the Dbc cursor here.
0259     inline const self& operator=(const self&itr) 
0260     {
0261         ASSIGNMENT_PREDCOND(itr)
0262         base::operator=(itr);
0263 
0264         curpair_base_.first = itr.curpair_base_.first;
0265         curpair_base_.second = itr.curpair_base_.second;
0266         if (pcsr_)
0267             pcsr_->close();
0268         pcsr_ = itr.pcsr_;
0269         
0270         return itr;
0271     }
0272 
0273     ////////////////////////////////////////////////////////////////////
0274 
0275     ////////////////////////////////////////////////////////////////////
0276     // Begin iterator comparison functions.
0277     //
0278     /// \name Compare operators.
0279     /// Only equal comparison is supported.
0280     //@{
0281     /// Compare two iterators.
0282     /// Two iterators compare equal when they are both invalid or 
0283     /// both valid and underlying cursor compare equal(i.e. sitting on the
0284     /// same key/data pair).
0285     //
0286     // Note that the iterator itr or this iterator may be an invalid
0287     // one, i.e. its this->itr_status_ is INVALID_ITERATOR_POSITION. 
0288     // We do not distinguish between end and rend iterators although
0289     // we are able to do so, because they are never compared together.
0290     /// Equal comparison operator.
0291     /// \param itr The iterator to compare against.
0292     /// \return Returns true if equal, false otherwise.
0293     inline bool operator==(const self&itr) const
0294     {
0295         COMPARE_CHECK(itr)  
0296         if (((itr.itr_status_ == this->itr_status_) && 
0297             (this->itr_status_ == INVALID_ITERATOR_POSITION)) ||
0298             ((itr.itr_status_ == this->itr_status_) && 
0299             (pcsr_->compare((itr.pcsr_.base_ptr())) == 0)))
0300             return true;
0301         return false;
0302         
0303     }
0304 
0305     /// Unequal comparison operator.
0306     /// \param itr The iterator to compare against.
0307     /// \return Returns false if equal, true otherwise.
0308     /// \sa bool operator==(const self&itr) const
0309     inline bool operator!=(const self&itr) const 
0310     {
0311         return !(*this == itr) ;
0312     }
0313     //@}
0314     ////////////////////////////////////////////////////////////////////
0315 
0316     ////////////////////////////////////////////////////////////////////
0317     // Begin functions that retrieve values from the iterator.
0318     //
0319     // curpair_base_ is always kept updated on iterator movement, but if 
0320     // directdb_get_ is true, curpair_base_ is also updated here before 
0321     // making use of the value it references.
0322     // Even if this iterator is invalid, this call is allowed, the
0323     // default value of type T is returned.
0324     //
0325     // Note that the returned reference can only be used to read data,
0326     // can't be used to update data.
0327     /// \name Functions that retrieve values from the iterator.
0328     //@{
0329     /// Dereference operator.
0330     /// Return the reference to the cached data element, which is an 
0331     /// pair<Key_type, T>. You can only read its referenced data via 
0332     /// this iterator but can not update it.
0333     /// \return Current data element reference object, i.e. ElementHolder
0334     /// or ElementRef object.
0335     inline reference operator*() const 
0336     {
0337         
0338         if (this->directdb_get_) { 
0339             csrddt d;
0340             pcsr_->get_current_key_data(curpair_base_.first, d);
0341             assign_second0(curpair_base_, d);
0342         }
0343         // Returning reference, no copy construction.
0344         return curpair_base_;
0345     }
0346      
0347     // curpair_base_ is always kept updated on iterator movement, but if 
0348     // directdb_get_ is true, curpair_base_ is also updated here before 
0349     // making use of the value it references.
0350     // Even if this iterator is invalid, this call is allowed, the
0351     // default value of type T is returned.
0352     //
0353     // Note that the returned reference can only be used to read data,
0354     // can't be used to update data.
0355     /// Arrow operator.
0356     /// Return the pointer to the cached data element, which is an 
0357     /// pair<Key_type, T>. You can only read its referenced data via 
0358     /// this iterator but can not update it.
0359     /// \return Current data element reference object's address, i.e. 
0360     /// address of ElementHolder or ElementRef object.
0361     inline pointer operator->() const
0362     {
0363         
0364         if (this->directdb_get_) {
0365             csrddt d;
0366             pcsr_->get_current_key_data(curpair_base_.first, d);
0367             assign_second0(curpair_base_, d);
0368         }
0369 
0370         return &curpair_base_;
0371     }
0372     //@}
0373     ////////////////////////////////////////////////////////////////////
0374         
0375     ////////////////////////////////////////////////////////////////////
0376     // Begin dbstl specific functions.
0377     //
0378     // Refresh the underlying cursor's current data and this object's 
0379     // curpair_base_. It need to be called only if directdb_get is 
0380     // disabled, and other iterators updated
0381     // the key/data pair this iterator points to and we are about to use 
0382     // this iterator to access that key/data pair. 
0383     // If direct db get is enabled, this method never needs to be called.
0384     /// @name dbstl specific functions
0385     //@{
0386     /// \brief Refresh iterator cached value.
0387     /// \param from_db If not doing direct database get and this parameter
0388     /// is true, we will retrieve data directly from db.
0389     /// \sa db_base_iterator::refresh(bool) 
0390     virtual int refresh(bool from_db = true) const
0391     {
0392         csrddt d;
0393 
0394         if (from_db && !this->directdb_get_)
0395             pcsr_->update_current_key_data_from_db(
0396                 DbCursorBase::SKIP_NONE);
0397         pcsr_->get_current_key_data(curpair_base_.first, d);
0398         assign_second0(curpair_base_, d);
0399 
0400         return 0;
0401     }
0402 
0403     // By calling this function, users can choose to close the underlying 
0404     // cursor before iterator destruction to get better performance 
0405     // potentially.
0406     /// \brief Close underlying Berkeley DB cursor of this iterator.
0407     /// \sa db_base_iterator::close_cursor() const
0408     inline void close_cursor() const
0409     {
0410         if (pcsr_)
0411             pcsr_->close();
0412     }
0413 
0414     /// Iterator movement function.
0415     /// Move this iterator to the specified key k, by default moves
0416     /// exactly to k, and update cached data element, you can
0417     /// also specify DB_SET_RANGE, to move to the biggest key smaller 
0418     /// than k. The btree/hash key comparison routine determines which
0419     /// key is bigger. When the iterator is on a multiple container, 
0420     /// move_to will move itself to the first key/data pair of the 
0421     /// identical keys.
0422     /// \param k The target key value to move to.
0423     /// \param flag Flags available: DB_SET(default) or DB_SET_RANGE.
0424     /// DB_SET will move this iterator exactly at k; DB_SET_RANGE moves
0425     /// this iterator to k or the smallest key greater than k. If fail
0426     /// to find such a key, this iterator will become invalid.
0427     /// \return 0 if succeed; non-0 otherwise, and this iterator becomes
0428     /// invalid. Call db_strerror with the return value to get the error 
0429     /// message.
0430     inline int move_to(const kdt& k, int flag = DB_SET) const
0431     {
0432         int ret;
0433         // Use tmpk2 to avoid k being modified.
0434         kdt tmpk2 = k;
0435 
0436         this->itr_status_ = (ret = pcsr_->move_to(tmpk2, flag));
0437         if (ret != 0) {
0438             this->inval_pos_type_ = base::IPT_UNSET;
0439             return ret;
0440         }
0441 
0442         refresh();
0443 
0444         return ret;
0445     }
0446 
0447     /// Modify bulk buffer size. 
0448     /// Bulk read is enabled when creating an
0449     /// iterator, so users later can only modify the bulk buffer size
0450     /// to another value, but can't enable/disable bulk read while an
0451     /// iterator is already alive. 
0452     /// \param sz The new size of the bulk read buffer of this iterator.
0453     /// \return Returns true if succeeded, false otherwise.
0454     /// \sa db_base_iterator::set_bulk_buffer(u_int32_t )
0455     bool set_bulk_buffer(u_int32_t sz)
0456     {
0457         bool ret = this->pcsr_->set_bulk_buffer(sz);
0458         if (ret)
0459             this->bulk_retrieval_ = 
0460                 this->pcsr_->get_bulk_bufsize();
0461         return ret;
0462     }
0463 
0464     /// \brief Get bulk retrieval buffer size in bytes.
0465     /// \return Return current bulk buffer size or 0 if bulk retrieval is
0466     /// not enabled.
0467     /// \sa db_base_iterator::get_bulk_bufsize()
0468     u_int32_t get_bulk_bufsize()
0469     {
0470         this->bulk_retrieval_ = pcsr_->get_bulk_bufsize();
0471         return this->bulk_retrieval_;
0472     }
0473     //@}
0474     ////////////////////////////////////////////////////////////////////
0475 
0476 protected:
0477     
0478     // The cursor_type is used to directly return the pair object, 
0479     // rather than a reference to it
0480     typedef DbCursor<kdt, csrddt> cursor_type;
0481 
0482     friend class db_map_iterator<kdt, ddt, ElementRef<ddt> >;
0483     friend class db_map_iterator<kdt, ddt, ElementHolder<ddt> >;
0484     // Use friend classes to hide internal members from users.
0485     friend class db_map<kdt, ddt, ElementHolder<ddt> >;
0486     friend class db_map<kdt, ddt, ElementHolder<kdt>, 
0487         db_set_iterator<kdt, ElementHolder<kdt> > >;
0488     friend class db_map<kdt, _DB_STL_set_value<kdt>, ElementHolder<kdt>, 
0489         db_set_iterator<kdt, ElementHolder<kdt> > >;
0490 
0491     friend class db_set<kdt, ElementHolder<kdt> >;
0492     friend class db_set_iterator<kdt, ElementHolder<kdt> >;
0493     friend class db_multiset<kdt, ElementHolder<kdt> >;
0494     friend class db_multimap<kdt, ddt, ElementHolder<ddt> >;
0495     friend class db_multimap<kdt, _DB_STL_set_value<kdt>, 
0496         ElementHolder<kdt>, db_set_iterator<kdt, ElementHolder<kdt> > >;
0497 
0498     friend class db_map<kdt, ddt, ElementRef<ddt> >;
0499     friend class db_map<kdt, _DB_STL_set_value<kdt>, ElementRef<kdt>, 
0500         db_set_iterator<kdt, ElementRef<kdt> > >;
0501 
0502     friend class db_set<kdt, ElementRef<kdt> >;
0503     friend class db_set_iterator<kdt, ElementRef<kdt> >;
0504     friend class db_multiset<kdt, ElementRef<kdt> >;
0505     friend class db_multimap<kdt, ddt, ElementRef<ddt> >;
0506     friend class db_multimap<kdt, _DB_STL_set_value<kdt>, ElementRef<kdt>,
0507         db_set_iterator<kdt, ElementRef<kdt> > >;
0508 
0509 
0510     ////////////////////////////////////////////////////////////////////
0511     // Begin db_map_base_iterator data members.
0512     //
0513     // Cursor of this iterator, note that each db_map_base_iterator has a  
0514     // unique DbCursor, not shared with any other iterator, and when copy 
0515     // constructing or assigning, the cursor is duplicated
0516     // when it is actually used to access db.
0517     //
0518     mutable LazyDupCursor<DbCursor<kdt, csrddt> > pcsr_;
0519 
0520     // In order for std::map style iterator to work, we need a pair 
0521     // here to store the key-value pair this iterator currently points
0522     // to in the db_map. 
0523     //
0524     // curpair_base_ is always kept updated on every cursor/iterator 
0525     // movement and initialized to point to the first key-value pair when
0526     // db_map<>::begin() is called.
0527     //
0528     mutable value_type curpair_base_;   
0529     ////////////////////////////////////////////////////////////////////
0530 
0531     ////////////////////////////////////////////////////////////////////
0532     // Begin internal helper functions.
0533     //
0534     // Open the iterator and its cursor.
0535     //
0536     void open() const
0537     {   
0538         u_int32_t oflags = 0, coflags = 0;
0539         int ret;
0540         Db *pdb = this->owner_->get_db_handle();
0541         DbEnv *penv = pdb->get_env();
0542 
0543         coflags = this->owner_->get_cursor_open_flags();
0544         assert(this->owner_ != NULL);
0545         if (!this->read_only_ && penv != NULL) {
0546             BDBOP((penv->get_open_flags(&oflags)), ret);
0547             if ((oflags & DB_INIT_CDB) != 0)
0548                 this->owner_->set_cursor_open_flags(coflags |= 
0549                     DB_WRITECURSOR);
0550         }
0551         if (!pcsr_)
0552             pcsr_.set_cursor(new DbCursor<kdt, csrddt>(
0553                 this->bulk_retrieval_, 
0554                 this->rmw_csr_, this->directdb_get_));
0555         this->itr_status_ = pcsr_->open((db_container*)this->owner_, 
0556             coflags);
0557         
0558     }
0559 
0560     // Move this iterator as well as the underlying Dbc* cursor to 
0561     // first element and update cur_pair_.
0562     //
0563     int first() const
0564     {
0565 
0566         assert(this->owner_ != NULL);
0567         this->itr_status_ = pcsr_->first();
0568         if (this->itr_status_ == 0) 
0569             refresh();
0570         else
0571             this->inval_pos_type_ = base::IPT_UNSET;
0572 
0573         return this->itr_status_;
0574         
0575     }
0576 
0577     // Move this iterator as well as the underlying Dbc* cursor
0578     // to last effective(valid) element and update cur_pair_.
0579     //
0580     int last() const
0581     {
0582 
0583         assert(this->owner_ != NULL);
0584         this->itr_status_ = pcsr_->last();
0585         if (this->itr_status_ == 0)
0586             refresh();
0587         else
0588             this->inval_pos_type_ = base::IPT_UNSET;
0589 
0590         return this->itr_status_;
0591     }
0592 
0593     // Move this iterator as well as the underlying Dbc* cursor
0594     // to next element, then update its position flags and cur_pair_.
0595     //
0596     int next(int flags = DB_NEXT) const
0597     {
0598 
0599         assert(this->owner_ != NULL);
0600         
0601         if (this->itr_status_ == INVALID_ITERATOR_POSITION) {
0602             if (this->inval_pos_type_ == base::IPT_BEFORE_FIRST) {
0603                 // This rend itr must have an non-NULL owner.
0604                 open();
0605                 // rend itr can go back to first element.
0606                 this->itr_status_ = first();
0607             } else if (this->inval_pos_type_ == base::IPT_UNSET) {
0608                 THROW0(InvalidIteratorException);
0609             }
0610             // Else, return itr_status_ in last line.
0611         } else {
0612             
0613             this->itr_status_ = pcsr_->next(flags);
0614             if (this->itr_status_ == 0)
0615                 refresh();
0616             else 
0617                 this->inval_pos_type_ = base::IPT_AFTER_LAST;
0618             
0619         }
0620         
0621         return this->itr_status_;
0622     }
0623 
0624     // Move this iterator as well as the underlying Dbc* cursor
0625     // to previous element.
0626     //
0627     int prev(int flags = DB_PREV) const
0628     {
0629 
0630         assert(this->owner_ != NULL);
0631         if (this->itr_status_ == INVALID_ITERATOR_POSITION) { 
0632             if (this->inval_pos_type_ == base::IPT_AFTER_LAST) {
0633                 // This rend itr must have an non-NULL owner.
0634                 open();
0635                 // end itr can go back to last element.
0636                 this->itr_status_ = last();
0637             } else if (this->inval_pos_type_ == base::IPT_UNSET) {
0638                 THROW0(InvalidIteratorException);
0639             }
0640             // Else, return itr stat in last line.
0641         } else {
0642             this->itr_status_ = pcsr_->prev(flags);
0643             if (this->itr_status_ == 0)
0644                 refresh();
0645             else 
0646                 this->inval_pos_type_ = base::IPT_BEFORE_FIRST;
0647             
0648         }
0649 
0650         return this->itr_status_;
0651     }
0652 
0653     void set_curpair_base(const kdt& k, const csrddt &d) const
0654     {
0655         curpair_base_.first = k;
0656         assign_second0(curpair_base_, d);
0657     }
0658 
0659     ////////////////////////////////////////////////////////////////////
0660 
0661 protected: // Do not remove this line, otherwise assign_second0 may be public.
0662 #ifndef DOXYGEN_CANNOT_SEE_THIS
0663 #if NO_MEMBER_FUNCTION_PARTIAL_SPECIALIZATION
0664 };// end of db_map_base_iterator<>
0665 template <Typename kdt, Typename datadt, Typename ddt>
0666 void assign_second0(pair<kdt, ddt>& v, const datadt& d) 
0667 {
0668     v.second = d;
0669 }
0670 
0671 template<Typename kdt, Typename ddt>
0672 void assign_second0(pair<kdt, ddt> &v, 
0673     const _DB_STL_set_value<kdt>&
0674     /* d unused, use v.first to assign v.second */) 
0675 {
0676     v.second = v.first;
0677 }
0678 #else
0679 
0680 template <Typename datadt>
0681 inline void assign_second0(value_type& v, const datadt& d) const
0682 {
0683     v.second = d;
0684 }
0685 
0686 template<>
0687 inline void 
0688 assign_second0(value_type &v, const _DB_STL_set_value<kdt>& 
0689     /* d unused, use v.first to assign v.second */) const
0690 {
0691     v.second = v.first;
0692 }
0693 
0694 };// end of db_map_base_iterator<>
0695 
0696 #endif
0697 
0698 #else
0699 };
0700 #endif // DOXYGEN_CANNOT_SEE_THIS
0701 //@} // db_map_iterators
0702 //@} // dbstl_iterators
0703 
0704 //////////////////////////////////////////////////////////////////////////
0705 //////////////////////////////////////////////////////////////////////////
0706 //
0707 // db_map_iterator class template definition
0708 //
0709 // db_map_iterator is the iterator class template for db_map and 
0710 // db_multimap, it is also the base class for db_set_iterator. It can be
0711 // used to both read and write the database.
0712 //
0713 // Template parameters info:
0714 // kdt is "key data type", ddt is "data data type", value_type_sub is
0715 // either ElementRef<ddt> (by default, in this case ElementRef inherits
0716 // from ddt, so ddt must not be a primitive type) or ElementHolder<ddt>,
0717 // in this case ElementHolder has a data member of type ddt, so suitable for
0718 // primitive types, but don't apply it to classes otherwise you can't access
0719 // members like this : *iterator.member = value.  
0720 //
0721 /// \ingroup dbstl_iterators 
0722 //@{
0723 /// \ingroup db_map_iterators
0724 //@{
0725 template <Typename kdt, Typename ddt, Typename value_type_sub>
0726 class _exported db_map_iterator : public 
0727     db_map_base_iterator<kdt, typename value_type_sub::content_type, ddt>
0728 {
0729 protected:
0730     typedef db_map_iterator<kdt, ddt, value_type_sub> self;
0731     typedef typename value_type_sub::content_type realddt;
0732     using db_base_iterator<typename value_type_sub::content_type>::
0733         replace_current_key;
0734 public:
0735     typedef kdt key_type;
0736     typedef ddt data_type;
0737     typedef pair<kdt, ddt> value_type;
0738     typedef pair<kdt, value_type_sub> value_type_wrap;
0739     // Not used in this class, but required to satisfy 
0740     // db_reverse_iterator type extraction.
0741     typedef ptrdiff_t difference_type;
0742     typedef difference_type distance_type;
0743     typedef value_type_wrap& reference;
0744     typedef value_type_wrap* pointer;
0745 
0746     // We have to use standard iterator tags to match the parameter 
0747     // list of stl internal functions, we can't use our own tag 
0748     // classes, so we don't write tag classes in dbstl.
0749     //
0750     typedef std::bidirectional_iterator_tag iterator_category;
0751     
0752     // Refresh the underlying cursor's current data and this object's 
0753     // curpair_. It need to be called only if other iterators updated the 
0754     // key/data pair this iterator points to and we are about to use 
0755     // this iterator to access that key/data pair. If direct db get is
0756     // enabled, this method never needs to be called.
0757     /// \brief Refresh iterator cached value.
0758     /// \param from_db If not doing direct database get and this parameter
0759     /// is true, we will retrieve data directly from db.
0760     /// \sa db_base_iterator::refresh(bool )
0761     virtual int refresh(bool from_db = true) const
0762     {
0763         kdt k;
0764         ddt d;
0765 
0766         if (from_db && !this->directdb_get_)
0767             this->pcsr_->update_current_key_data_from_db(
0768                 DbCursorBase::SKIP_NONE);
0769         this->pcsr_->get_current_key_data(k, d);
0770         curpair_.first = k;
0771         assign_second(curpair_, d);
0772         this->set_curpair_base(k, d);
0773 
0774         return 0;
0775     }
0776 
0777     ////////////////////////////////////////////////////////////////
0778     // Begin constructors and destructor definitions.
0779     /// \name Constructors and destructor
0780     /// Do not create iterators directly using these constructors, but
0781     /// call db_map::begin or db_multimap_begin to get instances of
0782     /// this class.
0783     /// \sa db_map::begin() db_multimap::begin()
0784     //@{
0785     /// Copy constructor.
0786     /// \param vi The other iterator of the same type to initialize this.
0787     db_map_iterator(const db_map_iterator<kdt, ddt, value_type_sub>& vi)
0788         : db_map_base_iterator<kdt, realddt, ddt>(vi)
0789     {
0790         // Lazy-dup another cursor, cursor to iterator mapping 
0791         // is 1 to 1.
0792         curpair_.first = vi.curpair_.first;
0793         curpair_.second._DB_STL_CopyData(vi.curpair_.second);
0794         curpair_.second._DB_STL_SetIterator(this);
0795     }
0796 
0797     /// Base copy constructor.
0798     /// \param vi Initialize from a base class iterator.
0799     db_map_iterator(const db_map_base_iterator<kdt, realddt, ddt>& vi) :
0800         db_map_base_iterator<kdt, realddt, ddt>(vi)
0801 
0802     {
0803         curpair_.second._DB_STL_SetIterator(this);
0804         curpair_.first = vi->first;
0805         curpair_.second._DB_STL_CopyData(vi->second);
0806     }
0807 
0808     /// Constructor.
0809     /// \param powner The container which creates this iterator.
0810     /// \param b_bulk_retrieval The bulk read buffer size. 0 means 
0811     /// bulk read disabled.
0812     /// \param brmw Whether set DB_RMW flag in underlying cursor.
0813     /// \param directdbget Whether do direct database get rather than
0814     /// using key/data values cached in the iterator whenever read.
0815     /// \param b_read_only Whether open a read only cursor. Only effective
0816     /// when using Berkeley DB Concurrent Data Store.
0817     explicit db_map_iterator(db_container*powner, 
0818         u_int32_t b_bulk_retrieval = 0, bool brmw = false, 
0819         bool directdbget = true, bool b_read_only = false)
0820         : db_map_base_iterator<kdt, realddt, ddt>
0821         (powner, b_bulk_retrieval, brmw, directdbget, b_read_only) 
0822     { 
0823         curpair_.second._DB_STL_SetIterator(this);
0824     }
0825 
0826     /// Default constructor, dose not create the cursor for now.
0827     db_map_iterator() : db_map_base_iterator<kdt, realddt, ddt>()
0828     {
0829         curpair_.second._DB_STL_SetIterator(this);
0830     }
0831 
0832     // Use virtual because ElementRef<> uses a db_base_iterator* pointer 
0833     // to refer to the iterator, and also use "dead_" flag to avoid 
0834     // multiple call to the same destructor by ~ElementRef<>().
0835     /// Destructor.
0836     virtual ~db_map_iterator() 
0837     {
0838         // Required here though set in base destructor too.
0839         this->dead_ = true;
0840     }
0841     //@}
0842     ////////////////////////////////////////////////////////////////
0843 
0844     ////////////////////////////////////////////////////////////////////
0845     // Begin functions that shift iterator position.
0846     //
0847     // Do not throw exceptions here because it is likely and normal 
0848     // to iterate to the "end iterator". 
0849     /// \name Iterator movement operators.
0850     //@{
0851     /// Pre-increment \sa db_map_base_iterator::operator++()
0852     /// \return This iterator after incremented.
0853     inline self& operator++()
0854     {
0855         this->next();
0856         
0857         return *this;
0858     }
0859 
0860     /// Post-increment \sa db_map_base_iterator::operator++(int)
0861     /// \return Another iterator having the old value of this iterator.
0862     inline self operator++(int)
0863     {
0864         self itr = *this;
0865 
0866         this->next();
0867         
0868         return itr;
0869     }
0870 
0871     /// Pre-decrement \sa db_map_base_iterator::operator--()
0872     /// \return This iterator after decremented.
0873     inline  self& operator--() 
0874     {
0875         this->prev();
0876         
0877         return *this;
0878     }
0879 
0880     /// Post-decrement \sa db_map_base_iterator::operator--(int)
0881     /// \return Another iterator having the old value of this iterator.
0882     self operator--(int)
0883     {
0884         self itr = *this;
0885         this->prev();
0886         
0887         return itr;
0888     }
0889     //@}
0890     // Assignment operator, we will duplicate the Dbc cursor here.
0891     /// Assignment operator. This iterator will point to the same key/data
0892     /// pair as itr, and have the same configurations as itr.
0893     /// \param itr The right value of assignment.
0894     /// \return The reference of itr.
0895     /// \sa db_base_iterator::operator=(const self&)
0896     inline const self& operator=(const self&itr) 
0897     {
0898         ASSIGNMENT_PREDCOND(itr)
0899         base::operator=(itr);
0900 
0901         curpair_.first = itr.curpair_.first;
0902 
0903         // Only copy data from itr.curpair_ into curpair_, 
0904         // don't store into db. Note that we can not assign 
0905         // itr.curpair_ to curpair_ simply by curpair_ = itr.curpair_,
0906         // otherwise, ElementRef<>::operator= is called, which will
0907         // update the data element referenced by this iterator.
0908         //
0909         curpair_.second._DB_STL_CopyData(itr.curpair_.second);
0910         
0911         return itr;
0912     }
0913     ////////////////////////////////////////////////////////////////////
0914 
0915     ////////////////////////////////////////////////////////////////////
0916     // Begin functions that retrieve values from the iterator.
0917     //
0918     // curpair_base_ is always kept updated on iterator movement, but if 
0919     // directdb_get_ is true, curpair_base_ is also updated here before 
0920     // making use of the value it references.
0921     // Even if this iterator is invalid, this call is allowed, the
0922     // default value of type T is returned.
0923     //
0924     /// \name Functions that retrieve values from the iterator.
0925     //@{
0926     /// Dereference operator.
0927     /// Return the reference to the cached data element, which is an
0928     /// pair<Key_type, ElementRef<T> > object if T is a class type or an
0929     /// pair<Key_type, ElementHolder<T> > object if T is a C++ primitive
0930     /// data type. 
0931     /// \return Current data element reference object, i.e. ElementHolder
0932     /// or ElementRef object.
0933     inline reference operator*() const 
0934     {
0935         
0936         if (this->directdb_get_) {
0937             ddt d;
0938             this->pcsr_->get_current_key_data(curpair_.first, d);
0939             assign_second(curpair_, d);
0940         }
0941 
0942         return curpair_;// returning reference, no copy construction
0943     }
0944      
0945     // curpair_base_ is always kept updated on iterator movement, but if 
0946     // directdb_get_ is true, curpair_base_ is also updated here before 
0947     // making use of the value it references.
0948     // Even if this iterator is invalid, this call is allowed, the
0949     // default value of type T is returned.
0950     /// Arrow operator.
0951     /// Return the pointer to the cached data element, which is an
0952     /// pair<Key_type, ElementRef<T> > object if T is a class type or an
0953     /// pair<Key_type, ElementHolder<T> > object if T is a C++ primitive
0954     /// data type. 
0955     /// \return Current data element reference object's address, i.e. 
0956     /// address of ElementHolder or ElementRef object.
0957     inline pointer operator->() const
0958     {
0959     
0960         if (this->directdb_get_) {
0961             ddt d;
0962             this->pcsr_->get_current_key_data(curpair_.first, d);
0963             assign_second(curpair_, d);
0964         }
0965         return &curpair_;
0966     }
0967     //@}
0968     ////////////////////////////////////////////////////////////////////
0969 
0970 //@} // db_map_iterators
0971 //@} // dbstl_iterators
0972 protected:
0973     // The cursor_type is used to directly return the pair object, 
0974     // rather than a reference to it.
0975     typedef DbCursor<kdt, ddt> cursor_type;
0976     typedef db_map_base_iterator<kdt, realddt, ddt> base;
0977     typedef db_map_base_iterator<kdt, realddt> const_version;
0978 
0979     // Use friend classes to hide internal members from users.
0980     friend class db_map<kdt, ddt, value_type_sub>;
0981     friend class db_map<kdt, ddt, value_type_sub, 
0982         db_set_iterator<kdt, value_type_sub> >;
0983     friend class db_set<kdt, value_type_sub>;
0984     friend class db_set_iterator<kdt, value_type_sub>;
0985     friend class db_multiset<kdt, value_type_sub>;
0986     friend class db_multimap<kdt, ddt, value_type_sub>;
0987     friend class db_multimap<kdt, _DB_STL_set_value<kdt>, value_type_sub,
0988         db_set_iterator<kdt, value_type_sub > >;
0989 
0990     ////////////////////////////////////////////////////////////////
0991     // Begin db_map_iterator data members.
0992     //
0993     // In order for std::map style iterator to work, we need a pair 
0994     // here to store the key-value pair this iterator currently points
0995     // to in the db_map. 
0996     //
0997     // curpair_ is always kept updated on every cursor/iterator movement
0998     // and initialized to point to the first key-value pair when
0999     // db_map<>::begin() is called.
1000     //
1001     mutable value_type_wrap curpair_;   
1002     ////////////////////////////////////////////////////////////////
1003 
1004     ////////////////////////////////////////////////////////////////
1005     // Begin internal helper functions.
1006     //
1007     // Called by ElementRef<> object when this iterator belongs to the 
1008     // object---The only situation is in db_container::operator[] which
1009     // has to return an ElementRef/Holder object A, and its iterator has
1010     // to survive until A is destructed.
1011     virtual void delete_me() const
1012     {
1013         if (!this->dead_)
1014             delete this;
1015     }
1016 
1017     // Duplicate this iterator.
1018     virtual self* dup_itr() const
1019     {
1020         self *itr = new self(*this);
1021         // The curpair_ of itr does not delete itr, the independent 
1022         // one does.
1023         //itr->curpair_.second._DB_STL_SetDelItr();
1024         return itr;
1025     }
1026 
1027     // Replace the current key/data pair's data pointed to by this 
1028     // iterator's underlying Dbc* cursor with the parameter d.
1029     //
1030     virtual int replace_current(
1031         const typename value_type_sub::content_type& d)
1032     {
1033         int ret;
1034 
1035         if (this->read_only_) {
1036             THROW(InvalidFunctionCall, (
1037 "db_map_iterator<>::replace_current can't be called via a read only iterator"));
1038         }
1039         ret = this->pcsr_->replace(d);
1040         
1041         return ret;
1042     }
1043 
1044     // Used by set iterator to store another different key : 
1045     // remove the previous one then insert the new one.
1046     // It has to be defined in this class because db_set_iterator
1047     // inherits from db_map_iterator but we have no polymorphism when
1048     // using stl because the object are always used rather the 
1049     // pointer/reference.
1050     //
1051     virtual int replace_current_key(const kdt& k)
1052     {
1053         int ret;
1054 
1055         if (this->read_only_) {
1056             THROW(InvalidFunctionCall, (
1057 "db_map_iterator<>::replace_current_key can't be called via a read only iterator"));
1058         }
1059         ret = this->pcsr_->replace_key(k);
1060 
1061         return ret;
1062     }
1063 
1064     ////////////////////////////////////////////////////////////////
1065 
1066 
1067 protected: // Do not remove this line, otherwise assign_second may be public.
1068 #ifndef DOXYGEN_CANNOT_SEE_THIS
1069 #if NO_MEMBER_FUNCTION_PARTIAL_SPECIALIZATION
1070 };// end of db_map_iterator<>
1071 
1072 template <Typename kdt, Typename datadt, Typename value_type_sub>
1073 void assign_second(pair<kdt, value_type_sub>& v, const datadt& d) 
1074 {
1075     v.second._DB_STL_CopyData(d);
1076 }
1077 
1078 template<Typename kdt, Typename value_type_sub>
1079 void assign_second(pair<kdt, value_type_sub> &v, 
1080     const _DB_STL_set_value<kdt>&
1081     /* d unused, use v.first to assign v.second */) 
1082 {
1083     v.second._DB_STL_CopyData(v.first);
1084 }
1085 #else
1086 
1087 template <Typename datadt>
1088 inline void assign_second(value_type_wrap& v, const datadt& d) const
1089 {
1090     v.second._DB_STL_CopyData(d);
1091 }
1092 
1093 template<>
1094 inline void 
1095 assign_second(value_type_wrap &v, const _DB_STL_set_value<kdt>& 
1096     /* d unused, use v.first to assign v.second */) const
1097 {
1098     v.second._DB_STL_CopyData(v.first);
1099 }
1100 
1101 };// end of db_map_iterator<>
1102 
1103 #endif
1104 #else
1105 };
1106 #endif // DOXYGEN_CANNOT_SEE_THIS
1107 u_int32_t hash_default(Db *dbp, const void *key, u_int32_t len);
1108 
1109 //////////////////////////////////////////////////////////////////////////
1110 /////////////////////////////////////////////////////////////////////////
1111 //
1112 // db_map container class definition
1113 /// \ingroup dbstl_containers
1114 //@{
1115 /// db_map has identical methods to std::map and the semantics for each
1116 /// method is identical to its std::map counterpart, except that it stores data
1117 /// into underlying Berkeley DB btree or hash database. Passing a database
1118 /// handle of btree or hash type creates a db_map equivalent to std::map and
1119 /// std::hashmap respectively.
1120 /// Database(dbp) and environment(penv) handle requirement(applies to all 
1121 /// constructors in this class template):
1122 /// 0. The dbp is opened inside the penv environment. Either one of the two 
1123 /// handles can be NULL. If dbp is NULL, an anonymous database is created 
1124 /// by dbstl. 
1125 /// 1. Database type of dbp should be DB_BTREE or DB_HASH.
1126 /// 2. No DB_DUP or DB_DUPSORT flag set in dbp.
1127 /// 3. No DB_RECNUM flag set in dbp.
1128 /// 4. No DB_TRUNCATE specified in dbp's database open flags.
1129 /// 5. DB_THREAD must be set if you are sharing the dbp across 
1130 /// multiple threads directly, or indirectly by sharing the container object 
1131 /// across multiple threads.
1132 /// \param kdt The key data type.
1133 /// \param ddt The data data type. db_map stores key/data pairs.
1134 /// \param value_type_sub Do not specify anything if ddt type is a 
1135 /// class/struct type; Otherwise, specify ElementHolder<ddt> to it.
1136 /// \param iterator_t Never specify anything to this type parameter. It is
1137 /// only used internally.
1138 /// \sa db_container db_container(Db*, DbEnv*) db_container(const db_container&)
1139 template <Typename kdt, Typename ddt, Typename value_type_sub, 
1140     Typename iterator_t>
1141 class _exported db_map : public db_container 
1142 {
1143 
1144 public:
1145     // iterator_t is default argument, see forward declaration at the
1146     // head of this file
1147     typedef iterator_t iterator;
1148     typedef typename iterator::const_version const_iterator;
1149     typedef db_reverse_iterator<iterator, const_iterator> reverse_iterator;
1150     typedef db_reverse_iterator<const_iterator, iterator>
1151         const_reverse_iterator;
1152     typedef kdt key_type;
1153     typedef ddt data_type;
1154     typedef value_type_sub data_type_wrap;
1155     typedef pair<kdt, ddt> value_type;
1156     typedef pair<kdt, value_type_sub> value_type_wrap;
1157     typedef const value_type const_value_type;
1158     typedef ptrdiff_t difference_type;
1159     typedef size_t size_type;
1160     // The following three types are not used in db_map, but we define
1161     // them to conform to stl specifications.
1162     typedef value_type_wrap& reference;
1163     typedef const value_type& const_reference;
1164     typedef value_type_wrap* pointer;
1165 protected:
1166     typedef db_map<kdt, ddt, value_type_sub, iterator> self;
1167     typedef typename value_type_sub::content_type realddt;
1168 
1169     // This constructor is for db_multimap's constructors to call, 
1170     // because other constructors of this class will verify db handles 
1171     // and create one if needed. We need a special one that don't do 
1172     // anything. The BulkRetrievalOption is randomly picked, no special
1173     // implications at all.
1174     db_map(BulkRetrievalOption& arg){ delete &arg; }
1175 public:
1176     ////////////////////////////////////////////////////////////////
1177     // Begin inner class definitions.
1178     //
1179     // key_compare class definition, it is defined as an inner class,
1180     // using underlying btree/hash db's compare function
1181     //
1182     class key_compare 
1183     {
1184     private:
1185         Db*pdb;
1186     public:
1187         key_compare(Db*pdb1)
1188         {
1189             pdb = pdb1;
1190         }
1191         bool operator()(const kdt& k1, const kdt& k2) const
1192         {
1193             return compare_keys(pdb, k1, k2, NULL);
1194         }
1195 
1196     }; // key_compare class definition
1197 
1198     // value_compare class definition, it is defined as an inner class,
1199     // using key_compare class to do comparison. 
1200     //
1201     // The difference between key_compare and value_compare is the 
1202     // parameter its operator() function accepts, see the function
1203     // signature.
1204     //
1205     class value_compare 
1206     {
1207         key_compare kc;
1208     public:
1209         value_compare(Db*pdb) : kc(pdb)
1210         {
1211         
1212         }
1213 
1214         bool operator()(const value_type& v1, 
1215             const value_type& v2) const
1216         {
1217             
1218             return kc(v1.first, v2.first);
1219         }
1220 
1221     }; // value_compare class definition
1222 
1223     class hasher
1224     {
1225     private:
1226         Db*pdb;
1227     public:
1228         hasher(Db*db){pdb = db;}
1229         size_t operator()(const kdt&k) const
1230         {
1231             DBTYPE dbtype;
1232             int ret;
1233 
1234             assert(pdb != NULL);
1235             ret = pdb->get_type(&dbtype);
1236             assert(ret == 0);
1237             if (dbtype != DB_HASH) {
1238                 THROW(InvalidFunctionCall, (
1239                     "db_map<>::hasher"));
1240             }
1241             h_hash_fcn_t hash = NULL;
1242             BDBOP(pdb->get_h_hash(&hash), ret);
1243             if (hash == NULL)
1244                 hash = hash_default;
1245             return hash(pdb, &k, sizeof(k));
1246         }
1247     }; // hasher
1248 
1249     class key_equal
1250     {
1251     private:
1252         Db*pdb;
1253     public:
1254         key_equal(Db*db){pdb = db;}
1255         bool operator()(const kdt& kk1, const kdt&kk2) const
1256         {
1257             DBTYPE dbtype;
1258             kdt k1 = kk1, k2 = kk2;
1259             int ret;
1260 
1261             dbstl_assert(pdb != NULL);
1262             ret = pdb->get_type(&dbtype);
1263             dbstl_assert(ret == 0);
1264             if (dbtype != DB_HASH) {
1265                 THROW(InvalidFunctionCall, (
1266                     "db_map<>::key_equal"));
1267             }
1268 
1269             db_compare_fcn_t comp = NULL;
1270             BDBOP(pdb->get_h_compare(&comp), ret);
1271             if (comp == NULL)
1272                 return memcmp(&kk1, &kk2, sizeof(kdt)) == 0;
1273             Dbt kd1(&k1, sizeof(k1)), kd2(&k2, sizeof(k2));
1274             
1275             return comp(pdb, &kd1, &kd2, NULL) == 0;
1276 
1277 
1278         }
1279 
1280     };// key_equal
1281     ////////////////////////////////////////////////////////////////
1282 
1283     /// Function to get key compare functor.
1284     /// Used when this container is a hash_map, hash_multimap,
1285     /// hash_set or hash_multiset equivalent.
1286     /// \return key_equal type of compare functor.
1287     /// \sa http://www.sgi.com/tech/stl/hash_map.html
1288     inline key_equal key_eq() const
1289     {
1290         key_equal ke(this->get_db_handle());
1291         return ke;
1292     }
1293 
1294     /// Function to get hash key generating functor.
1295     /// Used when this container is a hash_map, hash_multimap,
1296     /// hash_set or hash_multiset equivalent.
1297     /// \return The hash key generating functor.
1298     /// \sa http://www.sgi.com/tech/stl/hash_map.html
1299     inline hasher hash_funct() const
1300     {
1301         hasher h(this->get_db_handle());
1302         return h;
1303 
1304     }
1305 
1306     /// Function to get value compare functor. Used when this container
1307     /// is a std::map, std::multimap, std::set or std::multiset equivalent.
1308     /// \return The value compare functor.
1309     /// \sa http://www.cplusplus.com/reference/stl/map/value_comp/
1310     inline value_compare value_comp() const
1311     {
1312         value_compare vc(this->get_db_handle());
1313         return vc;
1314     }
1315     
1316     /// Function to get key compare functor. Used when this container
1317     /// is a std::map, std::multimap, std::set or std::multiset equivalent.
1318     /// \return The key compare functor.
1319     /// \sa http://www.cplusplus.com/reference/stl/map/key_comp/
1320     inline key_compare key_comp() const 
1321     {
1322         key_compare kc(this->get_db_handle());
1323         return kc;
1324     }
1325 
1326     ////////////////////////////////////////////////////////////////
1327     // Begin constructors and destructor definitions.
1328     /// \name Constructors and destructor
1329     //@{
1330     // We don't need the equal compare or allocator here, user need to 
1331     // call Db::set_bt_compare or Db::set_h_compare to set comparison
1332     // function.
1333     /// Create a std::map/hash_map equivalent associative container.
1334     /// See the handle requirement in class details to pass correct 
1335     /// database/environment handles.
1336     /// \param dbp The database handle.
1337     /// \param envp The database environment handle.
1338     /// \sa db_container(Db*, DbEnv*)
1339     explicit db_map(Db *dbp = NULL, DbEnv* envp = NULL)  : 
1340         db_container(dbp, envp)
1341     {
1342         const char *errmsg;
1343 
1344         this->open_db_handles(dbp, envp, DB_BTREE, 
1345             DB_CREATE | DB_THREAD, 0);
1346         
1347         if ((errmsg = verify_config(dbp, envp)) != NULL) {
1348             THROW(InvalidArgumentException, ("Db*", errmsg));
1349         }
1350         this->set_db_handle_int(dbp, envp);
1351     }
1352 
1353     /// Iteration constructor. Iterates between first and last, 
1354     /// setting a copy of each of the sequence of elements as the
1355     /// content of the container object. 
1356     /// Create a std::map/hash_map equivalent associative container.
1357     /// Insert a range of elements into the database. The range is
1358     /// [first, last), which contains elements that can
1359     /// be converted to type ddt automatically.
1360     /// See the handle requirement in class details to pass correct
1361     /// database/environment handles.
1362     /// This function supports auto-commit.
1363     /// \param dbp The database handle.
1364     /// \param envp The database environment handle.
1365     /// \param first The closed boundary of the range.
1366     /// \param last The open boundary of the range.
1367     /// \sa db_container(Db*, DbEnv*)
1368     template <class InputIterator> 
1369     db_map(Db *dbp, DbEnv* envp, InputIterator first, 
1370         InputIterator last) : db_container(dbp, envp)
1371     {
1372         const char *errmsg;
1373 
1374         this->open_db_handles(dbp, envp, DB_BTREE, 
1375             DB_CREATE | DB_THREAD, 0);
1376         if ((errmsg = verify_config(dbp, envp)) != NULL) {
1377             THROW(InvalidArgumentException, ("Db*", errmsg));
1378         }
1379         this->set_db_handle_int(dbp, envp);
1380 
1381         this->begin_txn();
1382         try {
1383             insert(first, last);
1384         } catch (...) {
1385             this->abort_txn();
1386             throw;
1387         }
1388         this->commit_txn();
1389     }
1390 
1391     // Copy constructor. The object is initialized to have the same 
1392     // contents as the x map object, do not copy properties because
1393     // if we copy things like pdb, we are storing to the same db, so we
1394     // create a new database, use it as the backing db, and store data 
1395     // into it.
1396     /// Copy constructor.
1397     /// Create an database and insert all key/data pairs in x into this
1398     /// container. x's data members are not copied.
1399     /// This function supports auto-commit.
1400     /// \param x The other container to initialize this container.
1401     /// \sa db_container(const db_container&)
1402     db_map(const db_map<kdt, ddt, value_type_sub, iterator>& x) : 
1403         db_container(x)
1404     {
1405         verify_db_handles(x);
1406         this->set_db_handle_int(this->clone_db_config(
1407             x.get_db_handle()), x.get_db_env_handle());
1408         assert(this->get_db_handle() != NULL);
1409         
1410         this->begin_txn();
1411         try {
1412             copy_db((db_map<kdt, ddt, value_type_sub, iterator>&)x);
1413         } catch (...) {
1414             this->abort_txn();
1415             throw;
1416         }
1417         this->commit_txn();
1418     }
1419 
1420     virtual ~db_map(){}
1421     //@}
1422     ////////////////////////////////////////////////////////////////
1423 
1424     ////////////////////////////////////////////////////////////////
1425     // Begin insert function definitions.
1426     /// Container content assignment operator.
1427     /// This function supports auto-commit.
1428     /// \param x The other container whose key/data pairs will be inserted
1429     /// into this container. Old content in this containers are discarded.
1430     /// \sa http://www.cplusplus.com/reference/stl/map/operator=/
1431     inline const self& operator=(const self& x)
1432     {
1433         ASSIGNMENT_PREDCOND(x)
1434         db_container::operator =(x);
1435         verify_db_handles(x);
1436         assert(this->get_db_handle() != NULL);
1437         this->begin_txn();
1438         try {
1439             copy_db((self &)x);
1440         } catch (...) {
1441             this->abort_txn();
1442             throw;
1443         }
1444         this->commit_txn();
1445         return x;
1446     }
1447 
1448     /// \name Insert Functions
1449     /// They have similiar usage as their C++ STL equivalents.
1450     /// Note that when secondary index is enabled, each 
1451     /// db_container can create a db_multimap secondary container, 
1452     /// but the insert function is not functional for secondary containers.
1453     /// \sa http://www.cplusplus.com/reference/stl/map/insert/
1454     //@{
1455     //
1456     // Insert functions. Note that stl requires if the entry with x.key 
1457     // already exists, insert should not overwrite that entry and the 
1458     // insert should fail; but bdb Dbc::cursor(DB_KEYLAST) will replace
1459     // existing data with new one, so we will first find whether we
1460     // have this data, if have, return false;
1461     //
1462     // Can not internally use begin/commit_txn to wrap this call because 
1463     // it returns an iterator, which is closed after commit_txn(), and
1464     // reopening it is wrong in multithreaded access.
1465     /// Insert a single key/data pair if the key is not in the container.
1466     /// \param x The key/data pair to insert.
1467     /// \return A pair P, if insert OK, i.e. the inserted key wasn't in the
1468     /// container, P.first will be the iterator sitting on the inserted
1469     /// key/data pair, and P.second is true; otherwise P.first is an 
1470     /// invalid iterator and P.second is false.
1471     pair<iterator,bool> insert (const value_type& x ) 
1472     {
1473         pair<iterator,bool> ib;
1474         iterator witr;
1475 
1476         init_itr(witr);
1477         open_itr(witr);
1478 
1479         if (witr.move_to(x.first) == 0) {// has it
1480             ib.first = witr;
1481             ib.second = false;
1482             // Cursor movements are not logged, no need to 
1483             // use transaction here.
1484             return ib;
1485         } 
1486     
1487         witr.itr_status_ = witr.pcsr_->insert(x.first, x.second, 
1488             DB_KEYLAST);
1489         assert(witr.itr_status_ == 0);
1490         witr.refresh(false);
1491         ib.first = witr;
1492         ib.second = true;
1493 
1494         return ib;
1495     }
1496 
1497     /// Insert with hint position. We ignore the hint position because 
1498     /// Berkeley DB knows better where to insert.
1499     /// \param position The hint position.
1500     /// \param x The key/data pair to insert.
1501     /// \return The iterator sitting on the inserted key/data pair, or an
1502     /// invalid iterator if the key was already in the container.
1503     inline iterator insert (iterator position, const value_type& x ) 
1504     {
1505         pair<iterator,bool> ib = insert(x);
1506         return ib.first;
1507     }
1508 
1509     // Member function template overload.
1510     /// Range insertion. Insert a range [first, last) of key/data pairs
1511     /// into this container.
1512     /// \param first The closed boundary of the range.
1513     /// \param last The open boundary of the range.
1514     void insert (const db_map_base_iterator<kdt, realddt, ddt>& first, 
1515         const db_map_base_iterator<kdt, realddt, ddt>& last) 
1516     {
1517         db_map_base_iterator<kdt, realddt, ddt> ii;
1518         iterator witr;
1519 
1520         init_itr(witr);
1521         open_itr(witr);
1522 
1523         for (ii = first; ii != last; ++ii)
1524             witr.pcsr_->insert(ii->first, ii->second, 
1525                 DB_KEYLAST);    
1526     }
1527 
1528     /// Range insertion. Insert a range [first, last) of key/data pairs
1529     /// into this container.
1530     /// \param first The closed boundary of the range.
1531     /// \param last The open boundary of the range.
1532     template<typename InputIterator>
1533     void insert (InputIterator first, InputIterator last) 
1534     {
1535         InputIterator ii;
1536         iterator witr;
1537 
1538         init_itr(witr);
1539         open_itr(witr);
1540 
1541         for (ii = first; ii != last; ++ii)
1542             witr.pcsr_->insert(ii->first, ii->second, 
1543                 DB_KEYLAST);    
1544     }
1545     //@}
1546     ////////////////////////////////////////////////////////////////
1547 
1548     ////////////////////////////////////////////////////////////////
1549     // Begin functions that create iterators.
1550     /// \name Iterator Functions
1551     /// The parameters in begin functions of this group have identical
1552     /// meaning to thoes in db_vector::begin, refer to those functions
1553     /// for details.
1554     /// \sa db_vector::begin()
1555     //@{
1556     /// Begin a read-write or readonly iterator which sits on the first
1557     /// key/data pair of the database. 
1558     /// \param rmw Same as that of 
1559     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1560     /// \param bulkretrieval Same as that of 
1561     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1562     /// \param directdb_get Same as that of
1563     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1564     /// \param readonly Same as that of 
1565     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1566     /// \return The created iterator.
1567     /// \sa db_vector::begin(ReadModifyWriteOption, bool, 
1568     /// BulkRetrievalOption, bool)
1569     //
1570     iterator begin(ReadModifyWriteOption rmw = 
1571         ReadModifyWriteOption::no_read_modify_write(),
1572         bool readonly = false, BulkRetrievalOption bulkretrieval = 
1573         BulkRetrievalOption::no_bulk_retrieval(), 
1574         bool directdb_get = true) 
1575     {
1576         bool b_rmw;
1577         u_int32_t bulk_retrieval = 0;
1578 
1579         b_rmw = (rmw == ReadModifyWriteOption::read_modify_write());
1580         // Read only cursor don't need acquire write lock.
1581         if (readonly && b_rmw)
1582             b_rmw = false;
1583         if (readonly && bulkretrieval == BulkRetrievalOption::
1584             BulkRetrieval)
1585             bulk_retrieval = bulkretrieval.bulk_buf_size();
1586 
1587         iterator itr(dynamic_cast<db_container*>(this), 
1588             bulk_retrieval, b_rmw, directdb_get, readonly);
1589 
1590         open_itr(itr, readonly);
1591         itr.first();
1592         return itr;
1593     }
1594 
1595     /// Begin a read-only iterator.
1596     /// \param bulkretrieval Same as that of 
1597     /// begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1598     /// \param directdb_get Same as that of
1599     /// begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1600     /// \return The created const iterator.
1601     /// \sa db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption,
1602     /// bool);
1603     const_iterator begin(BulkRetrievalOption bulkretrieval = 
1604         BulkRetrievalOption::no_bulk_retrieval(), 
1605         bool directdb_get = true) const 
1606     {
1607         u_int32_t b_bulk_retrieval = (bulkretrieval == 
1608             BulkRetrievalOption::BulkRetrieval ? 
1609             bulkretrieval.bulk_buf_size() : 0);
1610 
1611         const_iterator itr((db_container*)this,
1612              b_bulk_retrieval, false, directdb_get, true);
1613 
1614         open_itr(itr, true);
1615         itr.first();
1616         return itr;
1617     }
1618 
1619     /// \brief Create an open boundary iterator.
1620     /// \return Returns an invalid iterator denoting the position after 
1621     /// the last valid element of the container.
1622     /// \sa db_vector::end()
1623     inline iterator end()
1624     {
1625         iterator itr;
1626 
1627         // end() is at an invalid position. We don't know what key it 
1628         // refers, so itr_status_ and inval_pos_type are the only 
1629         // data members to identify an iterator's position.
1630         //
1631         itr.itr_status_ = INVALID_ITERATOR_POSITION;
1632         itr.inval_pos_type_ = iterator::IPT_AFTER_LAST;
1633         itr.owner_ = (db_container*)this;
1634         return itr;
1635     }
1636 
1637     /// \brief Create an open boundary iterator.
1638     /// \return Returns an invalid const iterator denoting the position 
1639     /// after the last valid element of the container.
1640     /// \sa db_vector::end() const
1641     inline const_iterator end() const
1642     {
1643         const_iterator itr;
1644 
1645         // end() is at an invalid position. We don't know what key it 
1646         // refers, so itr_status_ and inval_pos_type are the only 
1647         // data members to identify an iterator's position.
1648         //
1649         itr.itr_status_ = INVALID_ITERATOR_POSITION;
1650         itr.inval_pos_type_ = iterator::IPT_AFTER_LAST;
1651         itr.owner_ = (db_container*)this;
1652         return itr;
1653     }
1654 
1655     /// Begin a read-write or readonly reverse iterator which sits on the 
1656     /// first key/data pair of the database. 
1657     /// \param rmw Same as that of 
1658     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1659     /// \param bulkretrieval Same as that of 
1660     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1661     /// \param directdb_get Same as that of
1662     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1663     /// \param read_only Same as that of 
1664     /// db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1665     /// \return The created iterator.
1666     /// \sa db_vector::begin(ReadModifyWriteOption, bool, 
1667     /// BulkRetrievalOption, bool)
1668     /// \sa db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption,
1669     /// bool);
1670     reverse_iterator rbegin(ReadModifyWriteOption rmw = 
1671         ReadModifyWriteOption::no_read_modify_write(),
1672         bool read_only = false, BulkRetrievalOption bulkretrieval = 
1673         BulkRetrievalOption::no_bulk_retrieval(), 
1674         bool directdb_get = true) 
1675     {
1676         u_int32_t bulk_retrieval = 0;
1677 
1678         iterator itr = end();
1679         itr.rmw_csr_ = (rmw == (
1680             ReadModifyWriteOption::read_modify_write())) && !read_only;
1681         itr.directdb_get_ = directdb_get;
1682         itr.read_only_ = read_only;
1683         if (read_only && bulkretrieval == BulkRetrievalOption::
1684             BulkRetrieval)
1685             bulk_retrieval = bulkretrieval.bulk_buf_size();
1686         itr.bulk_retrieval_ = bulk_retrieval;
1687         reverse_iterator ritr(itr);
1688         
1689         return ritr;
1690     }
1691 
1692     /// Begin a read-only reverse iterator.
1693     /// \param bulkretrieval Same as that of 
1694     /// begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1695     /// \param directdb_get Same as that of
1696     /// begin(ReadModifyWrite, bool, BulkRetrievalOption, bool);
1697     /// \return The created const iterator.
1698     /// \sa db_vector::begin(ReadModifyWrite, bool, BulkRetrievalOption, 
1699     /// bool);
1700     const_reverse_iterator rbegin(BulkRetrievalOption bulkretrieval = 
1701         BulkRetrievalOption::no_bulk_retrieval(), 
1702         bool directdb_get = true) const
1703     {
1704         const_iterator itr = end();
1705         itr.bulk_retrieval_ = (bulkretrieval == 
1706             BulkRetrievalOption::BulkRetrieval ? 
1707             bulkretrieval.bulk_buf_size() : 0);
1708         itr.directdb_get_ = directdb_get;
1709         itr.read_only_ = true;
1710         const_reverse_iterator ritr(itr);
1711         
1712         return ritr;
1713     }
1714 
1715     /// \brief Create an open boundary iterator.
1716     /// \return Returns an invalid iterator denoting the position 
1717     /// before the first valid element of the container.
1718     /// \sa db_vector::rend()
1719     inline reverse_iterator rend()
1720     {
1721         reverse_iterator ritr;
1722         ritr.inval_pos_type_ = iterator::IPT_BEFORE_FIRST;
1723         return ritr;
1724     }
1725 
1726     /// \brief Create an open boundary iterator.
1727     /// \return Returns an invalid const iterator denoting the position 
1728     /// before the first valid element of the container. 
1729     /// \sa db_vector::rend() const
1730     inline const_reverse_iterator rend() const
1731     {
1732         const_reverse_iterator ritr;
1733         ritr.inval_pos_type_ = iterator::IPT_BEFORE_FIRST;
1734         return ritr;
1735     }
1736     //@} // iterator functions
1737     ////////////////////////////////////////////////////////////////
1738 
1739     ////////////////////////////////////////////////////////////////
1740     //
1741     // Begin functions that return container metadata.
1742     /// \name Metadata Functions
1743     /// These functions return metadata about the container.
1744     //@{
1745     /// Get container category.
1746     /// Determines whether this container object is a std::map<> 
1747     /// equivalent(when returns false) or that of hash_map<> 
1748     /// class(when returns true). This method is not in stl, but it
1749     /// may be called by users because some operations are not supported
1750     /// by both type(map/hash_map) of containers, you need to call this
1751     /// function to distinguish the two types. dbstl will not stop you
1752     /// from calling the wrong methods of this class.
1753     /// \return Returns true if this container is a hash container based
1754     /// on a Berkeley DB hash database; returns false if it is based on a
1755     /// Berkeley DB btree database.
1756     //
1757     inline bool is_hash() const
1758     {
1759         DBTYPE dbtype = DB_UNKNOWN;
1760         int ret;
1761 
1762         assert(this->get_db_handle() != NULL);
1763         ret = this->get_db_handle()->get_type(&dbtype);
1764         assert(ret == 0);
1765         return dbtype == DB_HASH;
1766     }
1767 
1768     /// Only for std::hash_map, return number of hash bucket in use.
1769     /// This function supports auto-commit.
1770     /// \return The number of hash buckets of the database.
1771     size_type bucket_count() const
1772     {
1773         DBTYPE dbtype;
1774         u_int32_t flags;
1775         void *sp;
1776         size_type sz;
1777         int ret;
1778         DbTxn*txn;
1779         
1780         assert(this->get_db_handle() != NULL);
1781         ret = this->get_db_handle()->get_type(&dbtype);
1782         assert(ret == 0);
1783         if (dbtype != DB_HASH) {
1784             THROW(InvalidFunctionCall, ("db_map<>::bucket_count"));
1785             
1786         }
1787         flags = DB_FAST_STAT;
1788         
1789         // Here we use current_txn(), so we will get a valid 
1790         // transaction handle if we are using explicit transactions; 
1791         // and NULL if we are using autocommit, in which case bdb 
1792         // internal auto commit will be enabled automatically.
1793         //
1794         txn = ResourceManager::instance()->
1795             current_txn(this->get_db_handle()->get_env());
1796         BDBOP(this->get_db_handle()->stat(txn, &sp, flags), ret);
1797         
1798         sz = (size_type)(((DB_HASH_STAT*)sp)->hash_buckets);
1799         free(sp);
1800         return sz;
1801     }
1802     
1803     /// Get container size.
1804     // Return size of the map, can control whether compute
1805     // accurately(slower if db is huge) or not.
1806     /// This function supports auto-commit.
1807     /// \return Return the number of key/data pairs in the container.
1808     /// \param accurate This function uses database's statistics to get
1809     /// the number of key/data pairs. The statistics mechanism will either
1810     /// scan the whole database to find the accurate number or use the
1811     /// number of last accurate scanning, and thus much faster. If there 
1812     /// are millions of key/data pairs, the scanning can take some while,
1813     /// so in that case you may want to set the "accurate" parameter to 
1814     /// false.
1815     size_type size(bool accurate = true) const
1816     {
1817         u_int32_t flags;
1818         void *sp;
1819         DBTYPE dbtype;
1820         size_t sz;
1821         int ret;
1822         DbTxn*txn;
1823 
1824         flags = accurate ? 0 : DB_FAST_STAT;
1825         BDBOP(this->get_db_handle()->get_type(&dbtype), ret);
1826 
1827         // Here we use current_txn(), so we will get a valid 
1828         // transaction handle if we are using explicit transactions; 
1829         // and NULL if we are using autocommit, in which case bdb 
1830         // internal auto commit will be enabled automatically.
1831         //
1832         txn = ResourceManager::instance()->
1833             current_txn(this->get_db_handle()->get_env());
1834         BDBOP(this->get_db_handle()->stat(txn, &sp, flags), ret);
1835 
1836         assert((dbtype == DB_BTREE) || (dbtype == DB_HASH));
1837         // dbtype is BTREE OR HASH, no others.
1838         sz = dbtype == DB_BTREE ? ((DB_BTREE_STAT*)sp)->
1839             bt_ndata : ((DB_HASH_STAT*)sp)->hash_ndata;
1840         free(sp);
1841         return sz;
1842     }
1843 
1844     /// Get max size.
1845     /// The returned size is not the actual limit of database. See the
1846     /// Berkeley DB limits to get real max size.
1847     /// \return A meaningless huge number.
1848     /// \sa db_vector::max_size()
1849     inline size_type max_size() const
1850     {
1851         return SIZE_T_MAX;
1852     }
1853 
1854     /// Returns whether this container is empty.
1855     /// This function supports auto-commit.
1856     /// \return True if empty, false otherwise.
1857     bool empty() const
1858     {
1859         // If we fail to move to the first record, the db is 
1860         // supposed to be empty.
1861         const_iterator witr;
1862         bool ret;
1863 
1864         try {
1865             this->begin_txn();
1866             init_itr(witr);
1867             open_itr(witr, true);
1868             ret = witr.first() != 0;
1869             this->commit_txn();
1870             return ret;
1871         } catch (...) {
1872             this->abort_txn();
1873             throw;
1874         }
1875     }
1876     //@}
1877     ////////////////////////////////////////////////////////////////
1878 
1879     ////////////////////////////////////////////////////////////////
1880     // Begin element accessors.
1881     //
1882     // Don't use transaction wrapper(begin/commit_txn) here because 
1883     // even insert(the only logged operation) is only part of the 
1884     // whole expression---the use case is dmmap[key] = value; 
1885     // So insert and another put call should
1886     // be atomic, so there must be an outside transaction.
1887     //
1888     // As stated in STL specification, this method can't have "const" 
1889     // modifier because it is likely to insert a new record.
1890     /// Retrieve data element by key.
1891     /// This function returns an reference to the underlying data element
1892     /// of the specified key x. The returned object can be used to read or
1893     /// write the data element of the key/data pair. 
1894     /// Do use a data_type_wrap of db_map or value_type::second_type(they 
1895     /// are the same) type of variable to hold the return value of this 
1896     /// function.
1897     /// \param x The target key to get value from.
1898     /// \return Data element reference.
1899     //
1900     data_type_wrap operator[] (const key_type& x)
1901     {
1902         iterator witr, *pitr;
1903         int ret;
1904 
1905         init_itr(witr);
1906         open_itr(witr, false);
1907         
1908         if (witr.move_to(x) != 0) {
1909             ddt d;//default value
1910             DbstlInitializeDefault<ddt> initdef(d);
1911             // Insert (x, d) as place holder.
1912             witr.pcsr_->insert(x, d, DB_KEYLAST);
1913             // Should be OK this time.
1914             ret = witr.move_to(x);
1915             assert(ret == 0);
1916             // Return the reference to the data item of x.
1917         }
1918         
1919         //witr->curpair_.second._DB_STL_SetDelItr();
1920         pitr = new iterator(witr);
1921         data_type_wrap ref(pitr->curpair_.second);
1922         ref._DB_STL_SetDelItr();
1923         return ref;
1924     }
1925 
1926     // Only returns a right-value, no left value for assignment, so 
1927     // directly return the value rather than the ElementRef/ElementHolder 
1928     // wrapper. Must use a const reference to this container to call this
1929     // const function.
1930     //
1931     /// Retrieve data element by key.
1932     /// This function returns the value of the underlying data element of
1933     /// specified key x. You can only read the element, but unable to 
1934     /// update the element via the return value of this function. And you
1935     /// need to use the container's const reference to call this method.
1936     /// \param x The target key to get value from.
1937     /// \return Data element, read only, can't be used to modify it.
1938     const ddt operator[] (const key_type& x) const
1939     {
1940         iterator witr;
1941 
1942         init_itr(witr);
1943         open_itr(witr);
1944         
1945         // x is supposed to be in this map.
1946         if (witr.move_to(x) != 0) {
1947             THROW0(NoSuchKeyException);
1948             
1949         }
1950         return witr.curpair_.second._DB_STL_value();
1951     }
1952     ////////////////////////////////////////////////////////////////
1953 
1954     ////////////////////////////////////////////////////////////////
1955     // Begin functions that erase elements from the container.
1956     //
1957     // Can not reopen external/outside iterator's cursor, pos must
1958     // already be in a transactional context.
1959     // There is identical function in db_multimap<> and db_multiset
1960     // for this function, we MUST keep the code consistent on update!
1961     // Go to db_multimap<>::erase(const key_type&) to see why.
1962     /// \name Erase Functions
1963     /// \sa http://www.cplusplus.com/reference/stl/map/erase/
1964     //@{
1965     /// Erase a key/data pair at specified position.
1966     /// \param pos An valid iterator of this container to erase.
1967     inline void erase (iterator pos) 
1968     {
1969         if (pos == end())
1970             return;
1971         pos.pcsr_->del();
1972     }
1973 
1974     /// Erase elements by key.
1975     /// All key/data pairs with specified key x will be removed from 
1976     /// underlying database.
1977     /// This function supports auto-commit.
1978     /// \param x The key to remove from the container.
1979     /// \return The number of key/data pairs removed.
1980     // There is identical function in db_multimap<> and db_multiset
1981     // for this function, we MUST keep the code consistent on update!
1982     // Go to db_multimap<>::erase(const key_type&) to see why.
1983     //
1984     size_type erase (const key_type& x) 
1985     {
1986         size_type cnt;
1987         iterator itr;
1988 
1989         this->begin_txn();
1990         try {
1991             pair<iterator, iterator> rg = equal_range(x);
1992             for (itr = rg.first, cnt = 0; itr != rg.second; ++itr) {
1993                 cnt++;
1994                 itr.pcsr_->del();
1995             }
1996         } catch (...) {
1997             this->abort_txn();
1998             throw;
1999         }
2000         this->commit_txn();
2001         return cnt;
2002     }
2003 
2004     // Can not be auto commit because first and last are already open.
2005     // There is identical function in db_multimap<> and db_multiset
2006     // for this function, we MUST keep the code consistent on update!
2007     // Go to db_multimap<>::erase(const key_type&) to see why.
2008     /// Range erase. Erase all key/data pairs within the valid range 
2009     /// [first, last).
2010     /// \param first The closed boundary of the range.
2011     /// \param last The open boundary of the range.
2012     inline void erase (iterator first, iterator last) 
2013     {
2014         iterator i;
2015 
2016         for (i = first; i != last; ++i)
2017             i.pcsr_->del();
2018     }
2019     //@}
2020     
2021     /// Swap content with container mp.
2022     /// This function supports auto-commit.
2023     /// \param mp The container to swap content with.
2024     /// \param b_truncate: See db_vector::swap() for details.
2025     /// \sa http://www.cplusplus.com/reference/stl/map/swap/ 
2026     /// db_vector::clear()
2027     void swap (db_map<kdt, ddt, value_type_sub>& mp, bool b_truncate = true)
2028     {
2029         Db *swapdb = NULL;
2030         std::string dbfname(64, '\0');
2031         
2032         verify_db_handles(mp);
2033         this->begin_txn();
2034         try {
2035             swapdb = this->clone_db_config(this->get_db_handle(), 
2036                 dbfname);
2037             db_map<kdt, ddt, value_type_sub> tmap(swapdb, 
2038                 swapdb->get_env(), begin(), end());
2039             clear(b_truncate);// Clear this db_map<> object.
2040             typename db_map<kdt, ddt, value_type_sub>::
2041                 iterator itr1, itr2;
2042             itr1 = mp.begin();
2043             itr2 = mp.end();
2044             insert(itr1, itr2);
2045             mp.clear(b_truncate);
2046             itr1 = tmap.begin();
2047             itr2 = tmap.end();
2048             mp.insert(itr1, itr2);
2049             tmap.clear();
2050             
2051             swapdb->close(0);
2052             if (dbfname[0] != '\0') {
2053                 swapdb = new Db(NULL, DB_CXX_NO_EXCEPTIONS);
2054                 swapdb->remove(dbfname.c_str(), NULL, 0);
2055                 swapdb->close(0);
2056                 delete swapdb;
2057             }
2058         } catch (...) {
2059             this->abort_txn();
2060             throw;
2061         }   
2062         this->commit_txn();
2063     }
2064 
2065     /// Clear contents in this container.
2066     /// This function supports auto-commit.
2067     /// \param b_truncate See db_vector::clear(bool) for details.
2068     /// \sa db_vector::clear(bool)
2069     void clear (bool b_truncate = true) 
2070     {
2071         int ret;
2072         u_int32_t flag;
2073         DbEnv *penv = this->get_db_handle()->get_env();
2074 
2075         if (b_truncate) {
2076             ResourceManager::instance()->close_db_cursors(
2077                 this->get_db_handle());
2078             BDBOP2(this->get_db_handle()->truncate(
2079                 ResourceManager::instance()->current_txn(penv), 
2080                 NULL, 0), ret, this->abort_txn());
2081         } else {
2082             ReadModifyWriteOption brmw(
2083                 ReadModifyWriteOption::no_read_modify_write());
2084 
2085             BDBOP(penv->get_open_flags(&flag), ret);
2086 
2087             // DB_RMW flag requires locking subsystem started.
2088             if ((flag & DB_INIT_LOCK) || (flag & DB_INIT_CDB) || 
2089                 (flag & DB_INIT_TXN))
2090                 brmw = 
2091                     ReadModifyWriteOption::read_modify_write();
2092             try {
2093                 // In if branch, truncate is capable of 
2094                 // autocommit internally.
2095                 this->begin_txn();
2096                 erase(begin(brmw, false), end());
2097                 this->commit_txn();
2098             } catch (...) {
2099                 this->abort_txn();
2100                 throw;
2101             }
2102         }
2103     }
2104     ////////////////////////////////////////////////////////////////
2105 
2106     ////////////////////////////////////////////////////////////////
2107     // Begin functions that searches a key in the map.
2108     /// \name Searching Functions
2109     /// The following functions are returning iterators, and they by 
2110     /// default return read-write iterators. If you intend to use the 
2111     /// returned iterator only to read, you should call the const version
2112     /// of each function using a const reference to this container.
2113     /// Using const iterators can potentially promote concurrency a lot.
2114     /// You can also set the readonly parameter to each non-const version
2115     /// of the functions to true if you don't use the returned iterator
2116     /// to write, which also promotes concurrency and overall performance.
2117     //@{
2118     /// Find the key/data pair with specified key x. 
2119     /// \param x The target key to find.
2120     /// \return The valid const iterator sitting on the key x, or an 
2121     /// invalid one.
2122     /// \sa http://www.cplusplus.com/reference/stl/map/find/
2123     const_iterator find (const key_type& x) const
2124     {
2125         const_iterator witr;
2126 
2127         init_itr(witr);
2128         open_itr(witr, true);
2129         if (witr.move_to(x)) 
2130             return ((self *)this)->end();
2131 
2132         return witr;
2133     }
2134 
2135     /// Find the greatest key less than or equal to x.
2136     /// \param x The target key to find.
2137     /// \return The valid const iterator sitting on the key, or an 
2138     /// invalid one.
2139     /// \sa http://www.cplusplus.com/reference/stl/map/lower_bound/
2140     const_iterator lower_bound (const key_type& x) const 
2141     {
2142         const_iterator witr;
2143 
2144         init_itr(witr);
2145         open_itr(witr, true);
2146         if (witr.move_to(x, DB_SET_RANGE)) 
2147             return ((self *)this)->end();
2148         
2149         return witr;
2150     }
2151 
2152     /// Find the range within which all keys equal to specified key x.
2153     /// \param x The target key to find.
2154     /// \return The range [first, last).
2155     /// \sa http://www.cplusplus.com/reference/stl/map/equal_range/
2156     pair<const_iterator, const_iterator>
2157     equal_range (const key_type& x) const 
2158     {
2159         pair<const_iterator,const_iterator> pr;
2160         const_iterator witr;
2161         kdt k;
2162 
2163         init_itr(witr);
2164         open_itr(witr, true);
2165         if (witr.move_to(x, DB_SET_RANGE)) {
2166             pr.first = ((self *)this)->end();
2167             pr.second = ((self *)this)->end();
2168         } else {
2169             pr.first = witr;
2170             // If no duplicate keys, move one next is sufficient.
2171             if (witr.pcsr_->get_current_key(k) == 0 && k == x)
2172                 ++witr;
2173             pr.second = witr;
2174         }
2175         
2176 
2177         return pr;
2178     }
2179 
2180     /// Find the key/data pair with specified key x. 
2181     /// \param x The target key to find.
2182     /// \param readonly Whether the returned iterator is readonly.
2183     /// \return The valid iterator sitting on the key x, or an 
2184     /// invalid one.
2185     /// \sa http://www.cplusplus.com/reference/stl/map/find/
2186     iterator find (const key_type& x, bool readonly = false) 
2187     {
2188         iterator witr;
2189 
2190         init_itr(witr);
2191         open_itr(witr, readonly);
2192         if (witr.move_to(x)) 
2193             return ((self *)this)->end();
2194 
2195         return witr;
2196     }
2197 
2198     /// Find the greatest key less than or equal to x.
2199     /// \param x The target key to find.
2200     /// \param readonly Whether the returned iterator is readonly.
2201     /// \return The valid iterator sitting on the key, or an 
2202     /// invalid one.
2203     /// \sa http://www.cplusplus.com/reference/stl/map/lower_bound/
2204     iterator lower_bound (const key_type& x, bool readonly = false) 
2205     {
2206         iterator witr;
2207 
2208         init_itr(witr);
2209         open_itr(witr, readonly);
2210         if (witr.move_to(x, DB_SET_RANGE)) 
2211             return ((self *)this)->end();
2212         
2213         return witr;
2214     }
2215 
2216     /// Find the range within which all keys equal to specified key x.
2217     /// \param x The target key to find.
2218     /// \param readonly Whether the returned iterator is readonly.
2219     /// \return The range [first, last).
2220     /// \sa http://www.cplusplus.com/reference/stl/map/equal_range/
2221     pair<iterator, iterator>
2222     equal_range (const key_type& x, bool readonly = false) 
2223     {
2224         pair<iterator,iterator> pr;
2225         iterator witr;
2226         kdt k;
2227 
2228         init_itr(witr);
2229         open_itr(witr, readonly);
2230         if (witr.move_to(x, DB_SET_RANGE)) {
2231             pr.first = ((self *)this)->end();
2232             pr.second = ((self *)this)->end();
2233         } else {
2234             pr.first = witr;
2235             // If no dup, move one next is sufficient.
2236             if (witr.pcsr_->get_current_key(k) == 0 && k == x)
2237                 ++witr;
2238             pr.second = witr;
2239         }
2240         
2241 
2242         return pr;
2243     }
2244 
2245     /// Count the number of key/data pairs having specified key x.
2246     /// \param x The key to count.
2247     /// \return The number of key/data pairs having x as key within the
2248     /// container.
2249     /// \sa http://www.cplusplus.com/reference/stl/map/count/
2250     size_type count (const key_type& x) const
2251     {
2252         int ret;
2253         const_iterator witr;
2254         try {
2255             this->begin_txn();
2256             init_itr(witr);
2257             open_itr(witr, true);
2258             ret = witr.move_to(x);
2259             this->commit_txn();
2260             if (ret != 0) 
2261                 return 0;// No such key/data pair.
2262             // No duplicates, so it must be one, we don't call
2263             // Dbc::count because we don't have to.
2264             //
2265             else
2266                 return 1;
2267         } catch (...) {
2268             this->abort_txn();
2269             throw;
2270         }
2271         
2272     }
2273 
2274     /// Find the least key greater than x.
2275     /// \param x The target key to find.
2276     /// \return The valid iterator sitting on the key, or an 
2277     /// invalid one.
2278     /// \sa http://www.cplusplus.com/reference/stl/map/upper_bound/
2279     const_iterator upper_bound (const key_type& x) const
2280     {
2281         const_iterator witr;
2282 
2283         init_itr(witr);
2284         open_itr(witr, true);
2285 
2286         if (witr.move_to(x, DB_SET_RANGE)) 
2287             return ((self *)this)->end();
2288 
2289         kdt k;
2290 
2291         // x exists in db, and witr.pcsr_ points to x in db.
2292         if (witr.pcsr_->get_current_key(k) == 0 && k == x)
2293             ++witr;// No dup, so move one next is sufficient.
2294 
2295         return witr;
2296     }
2297 
2298     /// Find the least key greater than x.
2299     /// \param x The target key to find.
2300     /// \param readonly Whether the returned iterator is readonly.
2301     /// \return The valid iterator sitting on the key, or an 
2302     /// invalid one.
2303     /// \sa http://www.cplusplus.com/reference/stl/map/upper_bound/
2304     iterator upper_bound (const key_type& x, bool readonly = false)
2305     {
2306         iterator witr;
2307 
2308         init_itr(witr);
2309         open_itr(witr, readonly);
2310 
2311         if (witr.move_to(x, DB_SET_RANGE)) 
2312             return ((self *)this)->end();
2313 
2314         kdt k;
2315 
2316         // x exists in db, and witr.pcsr_ points to x in db.
2317         if (witr.pcsr_->get_current_key(k) == 0 && k == x)
2318             ++witr;// No dup, so move one next is sufficient.
2319 
2320         return witr;
2321     }
2322     //@}
2323     ////////////////////////////////////////////////////////////////
2324 
2325     // Compare function, return true if contents in m1 and m2 are 
2326     // identical otherwise return false. 
2327     // Note that we don't require the key-data pairs' order be identical
2328     // Put into db_map<> rather than global to utilize transactional
2329     // support.
2330     /// Map content equality comparison operator.
2331     /// This function does not rely on key order. For a set of keys S1 in
2332     /// this container and another set of keys S2 of container m2, if 
2333     /// set S1 contains S2 and S2 contains S1 (S1 equals to S2) and each
2334     /// data element of a key K in S1 from this container equals the data
2335     /// element of K in m2, the two db_map<> containers equal. Otherwise
2336     /// they are not equal.
2337     /// \param m2 The other container to compare against.
2338     /// \return Returns true if they have equal content, false otherwise.
2339     bool operator==(const db_map<kdt, ddt, value_type_sub>& m2) const
2340     {
2341         bool ret;
2342         const db_map<kdt, ddt, value_type_sub>& m1 = *this;
2343         COMPARE_CHECK(m2)
2344         verify_db_handles(m2);
2345         try {
2346             this->begin_txn();
2347             if (m1.size() != m2.size())
2348                 ret = false;
2349             else {
2350                 typename db_map<kdt, ddt, value_type_sub>::
2351                     const_iterator i1, i2;
2352                 
2353                 for (i1 = m1.begin(); i1 != m1.end(); ++i1) {
2354                     if (m2.count(i1->first) == 0) {
2355                         ret = false;
2356                         goto exit;
2357                     }
2358                     i2 = m2.find(i1->first);
2359                     if ((i2->second == i1->second) == 
2360                         false) {
2361                         ret = false;
2362                         goto exit;
2363                     }
2364                 } // for
2365 
2366                 ret = true;
2367             }
2368 exit:
2369             this->commit_txn();
2370             return ret;
2371 
2372         } catch (...) {
2373             this->abort_txn();
2374             throw;
2375         }
2376     // Now that m1 and m2 has the same number of unique elements and all
2377     // elements of m1 are in m2, thus there can be no element of m2 
2378     // that dose not belong to m1, so we won't verify each element of 
2379     // m2 are in m1.
2380     //
2381     }
2382 
2383     /// Container unequality comparison operator.
2384     /// \param m2 The container to compare against.
2385     /// \return Returns false if equal, true otherwise.
2386     bool operator!=(const db_map<kdt, ddt, value_type_sub>& m2) const
2387     {
2388         return !this->operator ==(m2);
2389     }
2390 
2391     
2392 protected:
2393     
2394     virtual const char* verify_config(Db*dbp, DbEnv* envp) const
2395     {
2396         DBTYPE dbtype;
2397         u_int32_t oflags, sflags;
2398         int ret;
2399         const char *err = NULL;
2400         
2401         err = db_container::verify_config(dbp, envp);
2402         if (err)
2403             return err;
2404 
2405         BDBOP(dbp->get_type(&dbtype), ret);
2406         BDBOP(dbp->get_open_flags(&oflags), ret);
2407         BDBOP(dbp->get_flags(&sflags), ret);
2408 
2409         if (dbtype != DB_BTREE && dbtype != DB_HASH)
2410             err = 
2411 "wrong database type, only DB_BTREE and DB_HASH allowed for db_map<> class";
2412 
2413         if (oflags & DB_TRUNCATE)
2414             err = 
2415 "do not specify DB_TRUNCATE flag to create a db_map<> object";
2416         if ((sflags & DB_DUP) || (sflags & DB_DUPSORT))
2417             err = 
2418 "db_map<> can not be backed by database permitting duplicate keys";
2419         if (sflags & DB_RECNUM)
2420             err = "no DB_RECNUM flag allowed in db_map<>";
2421         
2422         
2423         return err;
2424 
2425     }
2426 
2427 
2428     typedef ddt mapped_type;
2429     typedef int (*db_compare_fcn_t)(Db *db, const Dbt *dbt1, 
2430         const Dbt *dbt2, size_t *locp);
2431     typedef u_int32_t (*h_hash_fcn_t)
2432     (Db *, const void *bytes, u_int32_t length);
2433     typedef db_set_iterator<kdt> db_multiset_iterator_t;
2434 
2435     static bool compare_keys(Db *pdb,
2436         const kdt& k1, const kdt& k2, size_t *locp) 
2437     {
2438         DBTYPE dbtype;
2439         int ret;
2440         bool bret;
2441         u_int32_t sz1, sz2;
2442 
2443         assert(pdb != NULL);
2444         ret = pdb->get_type(&dbtype);
2445         assert(ret == 0);
2446         db_compare_fcn_t comp = NULL;
2447 
2448         if (dbtype == DB_BTREE)
2449             BDBOP(pdb->get_bt_compare(&comp), ret);
2450         else // hash
2451             BDBOP(pdb->get_h_compare(&comp), ret);
2452 
2453         DataItem key1(k1, true), key2(k2, true);
2454         Dbt &kdbt1 = key1.get_dbt();
2455         Dbt &kdbt2 = key2.get_dbt();
2456         sz1 = kdbt1.get_size();
2457         sz2 = kdbt2.get_size();
2458         
2459         if (comp == NULL) {
2460             ret = memcmp(&k1, &k2, sz1 > sz2 ? sz2 : sz1);
2461             return (ret == 0) ? (sz1 < sz2) : (ret < 0);
2462         }
2463         // Return strict weak ordering.
2464         bret = (comp(pdb, &kdbt1, &kdbt2, NULL) < 0);
2465         return bret;
2466     }
2467     
2468     void open_itr(db_map_base_iterator<kdt, realddt, ddt>&itr, 
2469         bool readonly = false) const
2470     {   
2471         u_int32_t oflags = 0;
2472         int ret;
2473         DbEnv *penv = this->get_db_handle()->get_env();
2474 
2475         if (!readonly && penv != NULL) {
2476             BDBOP((penv->get_open_flags(&oflags)) , ret);
2477              if ((oflags & DB_INIT_CDB) != 0)
2478                 ((self *)this)->set_cursor_open_flags(
2479                     this->get_cursor_open_flags() | 
2480                     DB_WRITECURSOR);
2481         }
2482 
2483         itr.itr_status_ = itr.pcsr_->open((db_container*)this, 
2484             this->get_cursor_open_flags());
2485         itr.owner_ = (db_container*)this;
2486     }
2487 
2488     void open_itr(const_reverse_iterator
2489         &itr, bool readonly = false) const
2490     {   
2491         u_int32_t oflags = 0;
2492         int ret;
2493         DbEnv *penv = this->get_db_handle()->get_env();
2494 
2495         if (!readonly && penv != NULL) {
2496             BDBOP((penv->get_open_flags(&oflags)) , ret);
2497              if ((oflags & DB_INIT_CDB) != 0)
2498                 ((self *)this)->set_cursor_open_flags(
2499                     this->get_cursor_open_flags() | 
2500                     DB_WRITECURSOR);
2501         }
2502         itr.itr_status_ = itr.pcsr_->open((db_container*)this, 
2503             this->get_cursor_open_flags());
2504         itr.owner_ = (db_container*)this;
2505     }
2506 
2507     inline void init_itr(db_map_base_iterator<kdt, realddt, ddt> &
2508         witr) const {
2509         typedef DbCursor<kdt, ddt> cursor_type;
2510         witr.pcsr_.set_cursor(new cursor_type());
2511         witr.owner_ = (db_container*)this;
2512     }
2513 
2514     // Do not use begin_txn/commit_txn in non-public(internal) methods, 
2515     // only wrap in public methods.
2516     //
2517     inline void copy_db(db_map<kdt, ddt, value_type_sub, iterator> &x)
2518     {    
2519 
2520         // Make sure clear can succeed if there are cursors 
2521         // open in other threads.
2522         clear(false);
2523         insert(x.begin(), x.end());
2524         
2525     }
2526 
2527 };//db_map
2528 //@}
2529 
2530 
2531 //////////////////////////////////////////////////////////////////////////
2532 //////////////////////////////////////////////////////////////////////////
2533 //
2534 // db_multimap class template definition
2535 //
2536 // This class derives from db_map<>, using many of its methods,
2537 // it also hides some functions that should not be used in
2538 // this class, such as operator[].
2539 //
2540 // The underlying db must allow duplicate.
2541 // iterator_t is default argument, see forward declaration at the
2542 // head of this file.
2543 // iterator_t is default argument, see forward declaration at the
2544 // head of this file
2545 //
2546 /// \ingroup dbstl_containers
2547 //@{
2548 /// This class is the combination of std::multimap and hash_multimap. By 
2549 /// setting database handles as DB_BTREE or DB_HASH type respectively, you
2550 /// will be using an equivalent of std::multimap or hash_multimap respectively.
2551 /// Database(dbp) and environment(penv) handle requirement:
2552 /// The dbp handle must meet the following requirement:
2553 /// 1. Database type should be DB_BTREE or DB_HASH.
2554 /// 2. Either DB_DUP or DB_DUPSORT flag must be set. Note that so far 
2555 /// Berkeley DB does not allow DB_DUPSORT be set and the database is storing
2556 /// identical key/data pairs, i.e. we can't store two (1, 2), (1, 2) pairs 
2557 /// into a database D with DB_DUPSORT flag set, but only can do so with DB_DUP
2558 /// flag set; But we can store a (1, 2) pair and a (1, 3) pair into D with
2559 /// DB_DUPSORT flag set. So if your data set allows DB_DUPSORT flag, you
2560 /// should set it to gain a lot of performance promotion.
2561 /// 3. No DB_RECNUM flag set.
2562 /// 4. No DB_TRUNCATE specified in database open flags.
2563 /// 5. DB_THREAD must be set if you are sharing the database handle across 
2564 /// multiple threads directly, or indirectly by sharing the container object
2565 /// across multiple threads.
2566 /// \param kdt The key data type.
2567 /// \param ddt The data data type. db_multimap stores key/data pairs.
2568 /// \param value_type_sub Do not specify anything if ddt type is a 
2569 /// class/struct type; Otherwise, specify ElementHolder<ddt> to it.
2570 /// \param iterator_t Never specify anything to this type parameter. It is
2571 /// only used internally.
2572 /// \sa db_container db_map
2573 template<Typename kdt, Typename ddt, Typename value_type_sub, 
2574     Typename iterator_t>
2575 class _exported db_multimap : public db_map<kdt, ddt, 
2576     value_type_sub, iterator_t> 
2577 {
2578 protected:
2579     typedef db_multimap<kdt, ddt, value_type_sub, iterator_t> self;
2580     typedef db_map<kdt, ddt, value_type_sub, iterator_t> base;
2581 public:
2582     typedef iterator_t iterator;
2583     typedef typename iterator::const_version const_iterator;
2584     typedef db_reverse_iterator<iterator, const_iterator> reverse_iterator;
2585     typedef db_reverse_iterator<const_iterator, iterator> 
2586         const_reverse_iterator;
2587     typedef kdt key_type;
2588     typedef ddt data_type;
2589     typedef value_type_sub data_type_wrap;
2590     typedef pair<kdt, value_type_sub> value_type_wrap;
2591     typedef pair<kdt, ddt> value_type;
2592     typedef value_type_wrap* pointer;
2593     typedef value_type_wrap& reference; 
2594     typedef const value_type& const_reference; 
2595     typedef size_t size_type;
2596     typedef ptrdiff_t difference_type;
2597 
2598     ////////////////////////////////////////////////////////////////
2599     // Begin constructors and destructor
2600     /// Constructor.
2601     /// See class detail for handle requirement.
2602     /// \param dbp The database handle.
2603     /// \param envp The database environment handle.
2604     /// \sa db_map::db_map(Db*, DbEnv*) db_vector::db_vector(Db*, DbEnv*)
2605     explicit db_multimap (Db *dbp = NULL, DbEnv* envp = NULL) : 
2606         base(*(new BulkRetrievalOption(
2607         BulkRetrievalOption::BulkRetrieval)))
2608     {
2609         const char *errmsg;
2610 
2611         this->init_members(dbp, envp);
2612         this->open_db_handles(dbp, envp, DB_BTREE, DB_CREATE | 
2613             DB_THREAD, DB_DUP);
2614         // We can't call base(dbp, envp) here because it will verify 
2615         // failed and we can't call db_container directly, it is 
2616         // illegal to do so.
2617         if ((errmsg = verify_config(dbp, envp)) != NULL) {
2618             THROW(InvalidArgumentException, ("Db*", errmsg));
2619             
2620         }
2621         this->set_db_handle_int(dbp, envp);
2622         this->set_auto_commit(dbp);
2623     }
2624 
2625     /// Iteration constructor.
2626     /// Iterates between first and last, setting
2627     /// a copy of each of the sequence of elements as the content of 
2628     /// the container object. 
2629     /// This function supports auto-commit.
2630     /// See class detail for handle requirement.
2631     /// \param dbp The database handle.
2632     /// \param envp The database environment handle.
2633     /// \param first The closed boundary of the range.
2634     /// \param last The open boundary of the range.
2635     /// \sa db_map::db_map(Db*, DbEnv*, InputIterator, InputIterator)
2636     /// db_vector::db_vector(Db*, DbEnv*)
2637     //
2638     template <class InputIterator> 
2639     db_multimap (Db *dbp, DbEnv* envp, InputIterator first, 
2640         InputIterator last) : base(*(new BulkRetrievalOption(
2641         BulkRetrievalOption::BulkRetrieval)))
2642     {
2643         const char *errmsg;
2644 
2645         this->init_members(dbp, envp);
2646         this->open_db_handles(dbp, envp, DB_BTREE, DB_CREATE | 
2647             DB_THREAD, DB_DUP);
2648         // Note that we can't call base(dbp, envp) here because it 
2649         // will verify failed; And we can't call db_container 
2650         // directly because it is illegal to do so.
2651         if ((errmsg = verify_config(dbp, envp)) != NULL) {
2652             THROW(InvalidArgumentException, ("Db*", errmsg));
2653             
2654         }
2655         this->set_db_handle_int(dbp, envp);
2656         this->set_auto_commit(dbp);
2657 
2658 
2659         this->begin_txn();
2660         try {
2661             insert(first, last);
2662         } catch (...) {
2663             this->abort_txn();
2664             throw;
2665         }
2666         this->commit_txn();
2667     }
2668 
2669     /// Copy constructor.
2670     /// Create an database and insert all key/data pairs in x into this
2671     /// container. x's data members are not copied.
2672     /// This function supports auto-commit.
2673     /// \param x The other container to initialize this container.
2674     /// \sa db_container(const db_container&) db_map(const db_map&)
2675     db_multimap (const self& x) : base(*(new BulkRetrievalOption(
2676         BulkRetrievalOption::BulkRetrieval)))
2677     {
2678         this->init_members(x);
2679         this->verify_db_handles(x);
2680         this->set_db_handle_int(this->clone_db_config(
2681             x.get_db_handle()), x.get_db_env_handle());
2682         assert(this->get_db_handle() != NULL);
2683         
2684         this->begin_txn();
2685         try {
2686             copy_db((self&)x);
2687         } catch (...) {
2688             this->abort_txn();
2689             throw;
2690         }
2691         this->commit_txn();
2692     }
2693 
2694     virtual ~db_multimap(){}
2695     ////////////////////////////////////////////////////////////////
2696 
2697     ////////////////////////////////////////////////////////////////
2698     // Begin functions that modify multimap content, e.g. insert, 
2699     // erase, assignment and swap.
2700     //
2701     /// Container content assignment operator.
2702     /// This function supports auto-commit.
2703     /// \param x The other container whose key/data pairs will be inserted
2704     /// into this container. Old content in this containers are discarded.
2705     /// \sa http://www.cplusplus.com/reference/stl/multimap/operator=/
2706     inline const self& operator=(const self&x)
2707     {
2708         ASSIGNMENT_PREDCOND(x)
2709         db_container::operator =(x);
2710         this->verify_db_handles(x);
2711         assert(this->get_db_handle() != NULL);
2712         this->begin_txn();
2713         try {
2714             this->copy_db((self &)x);
2715         } catch (...) {
2716             this->abort_txn();
2717             throw;
2718         }
2719         this->commit_txn();
2720         return x;
2721         
2722     }
2723 
2724     /// \name Insert Functions
2725     /// \sa http://www.cplusplus.com/reference/stl/multimap/insert/
2726     //@{
2727     /// Range insertion. Insert a range [first, last) of key/data pairs
2728     /// into this container.
2729     /// \param first The closed boundary of the range.
2730     /// \param last The open boundary of the range.
2731     template<typename InputIterator>
2732     void insert (InputIterator first, InputIterator last) 
2733     {
2734         InputIterator ii;
2735         iterator witr;
2736 
2737         this->init_itr(witr);
2738         this->open_itr(witr);
2739 
2740         for (ii = first; ii != last; ++ii)
2741             witr.pcsr_->insert(ii->first, ii->second, 
2742                 DB_KEYLAST);    
2743     }
2744 
2745     // Compiler can't see the inherited version, unknown why.
2746     /// Range insertion. Insert a range [first, last) of key/data pairs
2747     /// into this container.
2748     /// \param first The closed boundary of the range.
2749     /// \param last The open boundary of the range.
2750     inline void insert (const_iterator& first, const_iterator& last) {
2751         base::insert(first, last);
2752     }
2753 
2754     // Insert x into this container, the other two versions are 
2755     // inherited from db_map<> class.
2756     // Methods returning an iterator or using an iterator as parameter 
2757     // can not be internally wrapped by 
2758     // begin/commit_txn because a cursor is inside its transaction, it 
2759     // must have been closed after transaction commit, and reopen is 
2760     // unsafe in multithreaded access.
2761     //
2762     /// Insert a single key/data pair if the key is not in the container.
2763     /// \param x The key/data pair to insert.
2764     /// \return A pair P, if insert OK, i.e. the inserted key wasn't in the
2765     /// container, P.first will be the iterator sitting on the inserted
2766     /// key/data pair, and P.second is true; otherwise P.first is an 
2767     /// invalid iterator and P.second is false.
2768     inline iterator insert (const value_type& x) 
2769     {
2770         iterator witr;
2771 
2772         this->init_itr(witr);
2773         this->open_itr(witr);
2774         witr.itr_status_ = witr.pcsr_->insert(x.first, x.second, 
2775             DB_KEYLAST);
2776         witr.refresh(false);
2777         return witr;
2778     }
2779     //@}
2780 
2781     /// Swap content with another multimap container.
2782     /// This function supports auto-commit.
2783     /// \param mp The other container to swap content with.
2784     /// \param b_truncate See db_map::swap() for details.
2785     /// \sa db_vector::clear()
2786     void swap (db_multimap<kdt, ddt, value_type_sub>& mp, 
2787         bool b_truncate = true)
2788     {
2789         Db *swapdb = NULL;
2790         std::string dbfname(64, '\0');
2791 
2792         this->verify_db_handles(mp);
2793         this->begin_txn();
2794         try {
2795             swapdb = this->clone_db_config(this->get_db_handle(), 
2796                 dbfname);
2797             
2798             db_multimap<kdt, ddt, value_type_sub> tmap(
2799                 swapdb, swapdb->get_env(),
2800                 this->begin(), this->end());
2801             // Clear this db_multimap<> object.
2802             this->clear(b_truncate);
2803             typename db_multimap<kdt, ddt, value_type_sub>::
2804                 iterator mpbitr, mpeitr;
2805 
2806             mpbitr = mp.begin();
2807             mpeitr = mp.end();
2808             insert(mpbitr, mpeitr);
2809             mp.clear(b_truncate);
2810             mpbitr = tmap.begin();
2811             mpeitr = tmap.end();
2812             mp.insert(mpbitr, mpeitr);
2813             tmap.clear();
2814             
2815             swapdb->close(0);
2816             if (dbfname[0] != '\0') {
2817                 swapdb = new Db(NULL, DB_CXX_NO_EXCEPTIONS);
2818                 swapdb->remove(dbfname.c_str(), NULL, 0);
2819                 swapdb->close(0);
2820                 delete swapdb;
2821             }
2822             this->commit_txn();
2823         } catch (...) {
2824             this->abort_txn();
2825             throw;
2826         }
2827         
2828     }
2829 
2830     // This method has identical code to db_map<>::erase(const key_type&), 
2831     // but we can NOT simply inherit and use 
2832     // that version because:
2833     // 1. The db_map<>::erase called equal_range which is overloaded in 
2834     //  db_multimap, so if we want the inherited erase to call the right
2835     //  version of equal_range, we have to make equal_range virtual
2836     // 2.  Making equal_range virtual will make the code not build--- The 
2837     //  default template parameter can't be replaced by real parameter, 
2838     //  unknow why.
2839     // So we have to copy the code from db_map<> to here, and keep the 
2840     // code consistent on each update.
2841     // Also, when I copy only this function, I found other erase overloaded 
2842     // functions also have to be copied from db_map<> to db_multimap and 
2843     // db_multiset, otherwise the code don't build, so I 
2844     // finally have to copy all versions of erase functions into db_multiset
2845     // and db_multimap. When updating an erase function, do update all 
2846     // three versions.
2847     /// \name Erase Functions
2848     /// \sa http://www.cplusplus.com/reference/stl/multimap/erase/
2849     //@{
2850     /// Erase elements by key.
2851     /// All key/data pairs with specified key x will be removed from 
2852     /// underlying database.
2853     /// This function supports auto-commit.
2854     /// \param x The key to remove from the container.
2855     /// \return The number of key/data pairs removed.
2856     size_type erase (const key_type& x) 
2857     {
2858         size_type cnt;
2859         iterator itr;
2860 
2861         this->begin_txn();
2862         try {
2863             pair<iterator, iterator> rg = equal_range(x);
2864             for (itr = rg.first, cnt = 0; itr != rg.second; ++itr) {
2865                 cnt++;
2866                 itr.pcsr_->del();
2867             }
2868         } catch (...) {
2869             this->abort_txn();
2870             throw;
2871         }
2872         this->commit_txn();
2873         return cnt;
2874     }
2875 
2876     // Can not reopen external/outside iterator's cursor, pos must
2877     // already be in a transactional context.
2878     // There is identical function in db_multimap<> and db_multiset
2879     // for this function, we MUST keep the code consistent on update!
2880     // Go to db_multimap<>::erase(const key_type&) to see why.
2881     //
2882     /// Erase a key/data pair at specified position.
2883     /// \param pos An valid iterator of this container to erase.
2884     inline void erase (iterator pos) 
2885     {
2886         if (pos == this->end())
2887             return;
2888         pos.pcsr_->del();
2889     }
2890 
2891     // Can not be auto commit because first and last are already open.
2892     // There is identical function in db_multimap<> and db_multiset
2893     // for this function, we MUST keep the code consistent on update!
2894     // Go to db_multimap<>::erase(const key_type&) to see why.
2895     //
2896     /// Range erase. Erase all key/data pairs within the valid range 
2897     /// [first, last).
2898     /// \param first The closed boundary of the range.
2899     /// \param last The open boundary of the range.
2900     inline void erase (iterator first, iterator last) 
2901     {
2902 
2903         for (iterator i = first; i != last; ++i)
2904             i.pcsr_->del();
2905     }
2906     //@}
2907     ////////////////////////////////////////////////////////////////
2908 
2909     ////////////////////////////////////////////////////////////////
2910     // Begin functions that searches a key in the multimap.
2911     /// \name Searching Functions
2912     /// See of db_map's searching functions group for details about 
2913     /// iterator, function version and parameters.
2914     /// \sa db_map
2915     //@{
2916     /// Find the range within which all keys equal to specified key x.
2917     /// \param x The target key to find.
2918     /// \return The range [first, last).
2919     /// \sa http://www.cplusplus.com/reference/stl/multimap/equal_range/
2920     pair<const_iterator, const_iterator>
2921     equal_range (const key_type& x) const
2922     {
2923         pair<const_iterator,const_iterator> pr;
2924         const_iterator witr;
2925         kdt k;
2926 
2927         this->init_itr(witr);
2928         this->open_itr(witr, true);
2929         // Move witr to x if this contains x and return the itr, or if 
2930         // no x, position witr to the least key greater than x.
2931         //
2932         if (witr.move_to(x, DB_SET_RANGE)) {
2933             pr.first =  ((self *)this)->end();
2934             pr.second = ((self *)this)->end();
2935         } else {
2936             pr.first = witr;
2937             
2938             // No dup, so move one next is sufficient.
2939             if (witr.pcsr_->get_current_key(k) == 0 && k == x)
2940                 witr.next(DB_NEXT_NODUP);
2941             pr.second = witr;
2942         }
2943             
2944         return pr;
2945     }
2946 
2947     /// Find the range within which all keys equal to specified key x.
2948     /// \param x The target key to find.
2949     /// \param readonly Whether the returned iterator is readonly.
2950     /// \return The range [first, last).
2951     /// \sa http://www.cplusplus.com/reference/stl/multimap/equal_range/
2952     pair<iterator,iterator>
2953     equal_range (const key_type& x, bool readonly = false) 
2954     {
2955         pair<iterator,iterator> pr;
2956         iterator witr;
2957         kdt k;
2958 
2959         this->init_itr(witr);
2960         this->open_itr(witr, readonly);
2961         // Move witr to x if this contains x and return the itr, or if 
2962         // no x, position witr to the least key greater than x.
2963         //
2964         if (witr.move_to(x, DB_SET_RANGE)) {
2965             pr.first =  ((self *)this)->end();
2966             pr.second = ((self *)this)->end();
2967         } else {
2968             pr.first = witr;
2969             
2970             // No dup, so move one next is sufficient.
2971             if (witr.pcsr_->get_current_key(k) == 0 && k == x)
2972                 witr.next(DB_NEXT_NODUP);
2973             pr.second = witr;
2974         }
2975             
2976         return pr;
2977     }
2978 
2979     /// Find equal range and number of key/data pairs in the range.
2980     /// This function also returns the number of elements within the 
2981     /// returned range via the out parameter nelem.
2982     /// \param x The target key to find.
2983     /// \param nelem The output parameter to take back the number of 
2984     /// key/data pair in the returned range.
2985     /// \sa http://www.cplusplus.com/reference/stl/multimap/equal_range/
2986     pair<const_iterator, const_iterator>
2987     equal_range_N (const key_type& x, size_t& nelem) const
2988     {
2989         int ret;
2990         pair<const_iterator,const_iterator> pr;
2991         size_t stepped;
2992         const_iterator witr;
2993         kdt k;
2994 
2995         this->init_itr(witr);
2996         this->open_itr(witr, true);
2997         // Move witr to x if this contains x and return the itr, or if 
2998         // no x, position witr to the least key greater than x.
2999         //
3000         if (witr.move_to(x, DB_SET_RANGE)) {
3001             pr.first = ((self *)this)->end();
3002             pr.second = ((self *)this)->end();
3003             nelem = 0;
3004         } else {
3005             pr.first = witr;
3006             if (witr.pcsr_->get_current_key(k) == 0 && k == x) {
3007                 for (stepped = 1, ret = 
3008                     witr.pcsr_->next(DB_NEXT_DUP); ret == 0;
3009                     ret = witr.pcsr_->next(DB_NEXT_DUP),
3010                     stepped += 1)
3011                     ;
3012                 pr.second = ++witr;
3013                 nelem = stepped;
3014             } else {
3015                 pr.second = witr;
3016                 nelem = 0;
3017             }
3018         }
3019         return pr;
3020     }
3021 
3022     /// Find equal range and number of key/data pairs in the range.
3023     /// This function also returns the number of elements within the 
3024     /// returned range via the out parameter nelem.
3025     /// \param x The target key to find.
3026     /// \param nelem The output parameter to take back the number of 
3027     /// key/data pair in the returned range.
3028     /// \param readonly Whether the returned iterator is readonly.
3029     /// \sa http://www.cplusplus.com/reference/stl/multimap/equal_range/
3030     //
3031     pair<iterator,iterator>
3032     equal_range_N (const key_type& x, size_t& nelem, 
3033         bool readonly = false)
3034     {
3035         int ret;
3036         pair<iterator,iterator> pr;
3037         size_t stepped;
3038         iterator witr;
3039         kdt k;
3040 
3041         this->init_itr(witr);
3042         this->open_itr(witr, readonly);
3043         // Move witr to x if this contains x and return the itr, or if 
3044         // no x, position witr to the least key greater than x.
3045         //
3046         if (witr.move_to(x, DB_SET_RANGE)) {
3047             pr.first = ((self *)this)->end();
3048             pr.second = ((self *)this)->end();
3049             nelem = 0;
3050         } else {
3051             pr.first = witr;
3052             if (witr.pcsr_->get_current_key(k) == 0 && k == x) {
3053                 for (stepped = 1, ret = 
3054                     witr.pcsr_->next(DB_NEXT_DUP); ret == 0;
3055                     ret = witr.pcsr_->next(DB_NEXT_DUP),
3056                     stepped += 1)
3057                     ;
3058                 pr.second = ++witr;
3059                 nelem = stepped;
3060             } else {
3061                 pr.second = witr;
3062                 nelem = 0;
3063             }
3064         }
3065         return pr;
3066     }
3067 
3068     /// Count the number of key/data pairs having specified key x.
3069     /// \param x The key to count.
3070     /// \return The number of key/data pairs having x as key within the
3071     /// container.
3072     /// \sa http://www.cplusplus.com/reference/stl/multimap/count/
3073     size_type count (const key_type& x) const
3074     {
3075         int ret;
3076         size_type cnt;
3077         iterator witr;
3078 
3079         try {
3080             this->begin_txn();
3081             this->init_itr(witr);
3082             this->open_itr(witr, true);
3083             ret = witr.move_to(x);
3084             if (ret) 
3085                 cnt = 0;
3086             else
3087                 cnt = witr.pcsr_->count();
3088             this->commit_txn();
3089         } catch (...) {
3090             this->abort_txn();
3091             throw;
3092         }
3093 
3094         return cnt;
3095     }
3096 
3097     /// Find the least key greater than x.
3098     /// \param x The target key to find.
3099     /// \return The valid iterator sitting on the key, or an 
3100     /// invalid one.
3101     /// \sa http://www.cplusplus.com/reference/stl/multimap/upper_bound/
3102     const_iterator upper_bound (
3103         const key_type& x) const
3104     {
3105         int ret;
3106         const_iterator witr;
3107 
3108         this->init_itr(witr);
3109         this->open_itr(witr, true);
3110 
3111         // No key equal to or greater than x.
3112         if (witr.move_to(x, DB_SET_RANGE)) 
3113             return ((self *)this)->end();
3114 
3115         kdt k;
3116         // x exists in db, and witr.pcsr_ points to x in db, 
3117         // need to move cursor to next different key.
3118         //
3119         if (witr.pcsr_->get_current_key(k) == 0 && k == x) 
3120             ret = witr.next(DB_NEXT_NODUP); 
3121 
3122         return witr;
3123     }
3124 
3125     /// Find the least key greater than x.
3126     /// \param x The target key to find.
3127     /// \param readonly Whether the returned iterator is readonly.
3128     /// \return The valid iterator sitting on the key, or an 
3129     /// invalid one.
3130     /// \sa http://www.cplusplus.com/reference/stl/multimap/upper_bound/
3131     iterator upper_bound (const key_type& x, bool readonly = false) 
3132     {
3133         int ret;
3134         iterator witr;
3135 
3136         this->init_itr(witr);
3137         this->open_itr(witr, readonly);
3138 
3139         // No key equal to or greater than x.
3140         if (witr.move_to(x, DB_SET_RANGE)) 
3141             return ((self *)this)->end();
3142 
3143         kdt k;
3144         // x exists in db, and witr.pcsr_ points to x in db, 
3145         // need to move cursor to next different key.
3146         //
3147         if (witr.pcsr_->get_current_key(k) == 0 && k == x) 
3148             ret = witr.next(DB_NEXT_NODUP); 
3149 
3150         return witr;
3151     }
3152     //@}
3153     ////////////////////////////////////////////////////////////////
3154 
3155     ////////////////////////////////////////////////////////////////
3156     // Begin functions that compare container content.
3157     //
3158     // In hash_multimap this function is a global compare function, 
3159     // return true if contents in m1 and m2 are identical
3160     // otherwise return false. But we have multiple reasons to make
3161     // it a member of db_multimap<>:
3162     // 1. There need to be a temporary set to store values of a range, and
3163     //   db_multimap<>  is quite likely to store huge amount of data, 
3164     //   not suitable to store into std::set, let alone std::set is not 
3165     //   completely multithread-safe, thus we store them into db_set<>, 
3166     //   thus we need a temporary db handle, and call 
3167     //   db_container::clone_db_handle() function to open the db handle.
3168     // 2. We need the transactional support. Making this function 
3169     //   autocommit is good to eliminate phantom issues.
3170     // Note that we don't require the key-data pairs' order be identical,
3171     // but we assume identical records of keys are adjacent, so that 
3172     // iteration will go through them all one by one; Also, the records'
3173     // order of identical keys are unpridictable and irrelivent, so we 
3174     // should treat values of a equal range a set, and compare two value 
3175     // sets for equality when comparing a equal range of key X.
3176     //
3177     /**
3178     Returns whether the two containers have identical content.
3179     This function does not rely on key order. For a set of keys S1 in this
3180     container and another set of keys S2 of container m2, if set S1 
3181     contains S2 and S2 contains S1 (S1 equals to S2) and each set of data
3182     elements of any key K in S1 from this container equals the set of data
3183     elements of K in m2, the two db_multimap<> containers equal. Otherwise
3184     they are not equal. Data element set comparison does not rely on order
3185     either.
3186     \param m2 The other container to compare against.
3187     \return Returns true if they are equal, false otherwise.
3188     */
3189     bool operator==(const db_multimap<kdt, ddt, value_type_sub>& m2) const
3190     {
3191         
3192         typedef typename self::const_iterator mm_itr_t;
3193         
3194         COMPARE_CHECK(m2)
3195         
3196         bool ret = false, retset = false;
3197         size_t n1, n2;
3198         int ret2;
3199         const self &m1 = *this;
3200         DbTxn *ptxn = NULL;
3201         DbEnv *penv;
3202         Db *pdb;
3203         const char *dbfilename, *dbname;
3204         const char *pname1, *pname2;
3205         string name1, name2;
3206         u_int32_t oflags;
3207 
3208         this->verify_db_handles(m2);
3209         pdb = this->get_db_handle();
3210         penv = pdb->get_env();
3211         try {
3212             this->begin_txn();
3213             if (m1.size() != m2.size()) {
3214                 ret = false;
3215                 this->commit_txn();
3216                 return ret;
3217             }
3218             BDBOP(pdb->get_dbname(&dbfilename, &dbname), ret2);
3219             if (dbfilename == NULL)
3220                 pname1 = pname2 = NULL;
3221             else {
3222 
3223                 this->construct_db_file_name(name1);
3224                 this->construct_db_file_name(name2);
3225                 // Make name2 different from name1.
3226                 name2.push_back('2');
3227                 pname1 = name1.c_str();
3228                 pname2 = name2.c_str();
3229             }
3230 
3231             Db *value_set_db = open_db(penv, 
3232                 pname1, DB_BTREE, DB_CREATE, 0);
3233 
3234             Db *value_set_db2 = open_db(penv, 
3235                 pname2, DB_BTREE, DB_CREATE, 0);
3236 
3237             db_set<ddt, value_type_sub> s1(value_set_db, penv), 
3238                 s2(value_set_db2, penv);
3239 
3240             mm_itr_t i1, i11;
3241             pair<mm_itr_t, mm_itr_t> resrg1, resrg2;
3242             for (i1 = m1.begin(); 
3243                 i1 != m1.end();
3244                 i1 = resrg1.second) {
3245                 
3246                 resrg1 = m1.equal_range_N(i1->first, n1);
3247                 resrg2 = m2.equal_range_N(i1->first, n2);
3248                 if (n1 != n2) {
3249                     ret = false;
3250                     retset = true;
3251                     break;
3252                 }
3253                     
3254                 if (n2 == 1 && !(resrg2.first->second == 
3255                     resrg1.first->second)) {
3256                     ret = false;
3257                     retset = true;
3258                     break;
3259                 }
3260                 
3261                 for (i11 = resrg1.first; i11 != resrg1.second;
3262                     ++i11) 
3263                     s1.insert(i11->second);
3264 
3265                 for (i11 = resrg2.first; i11 != resrg2.second;
3266                     ++i11)
3267                     s2.insert(i11->second);
3268                 if (!(s1 == s2)) {
3269                     ret = false;
3270                     retset = true;
3271                     break;
3272                 }
3273                 s1.clear();
3274                 s2.clear();
3275 
3276                 // Skip all equal keys in the range.
3277                 
3278                 
3279             } // for
3280 
3281             if (!retset) // Care: there are breaks in the for loop.
3282                 ret = true;
3283 
3284             close_db(value_set_db);
3285             close_db(value_set_db2);
3286 
3287             ptxn = this->current_txn();
3288             BDBOP(penv->get_open_flags(&oflags), ret2);
3289             // The transaction handle in CDS is not a real 
3290             // transaction.
3291             if (oflags & DB_INIT_CDB)
3292                 ptxn = NULL;
3293             if (name1.length() > 0)
3294                 BDBOP2(penv->dbremove(ptxn, name1.c_str(), 
3295                     NULL, 0), ret2, this->abort_txn());
3296             if (name2.length() > 0)
3297                 BDBOP2(penv->dbremove(ptxn, name2.c_str(), 
3298                     NULL, 0), ret2, this->abort_txn());
3299 
3300             this->commit_txn();
3301             return ret;
3302 
3303         } catch (...) {
3304             this->abort_txn();
3305             throw;
3306         }
3307     // Now that m1 and m2 has the same number of unique elements and all 
3308     // elements of m1 are in m2, thus there can be no element of m2 that
3309     // dose not belong to m1, so we won't verify each element of m2 are
3310     // in m1.
3311     //
3312         
3313     } // operator==
3314 
3315     /// Container unequality comparison operator.
3316     /// \param m2 The container to compare against.
3317     /// \return Returns false if equal, true otherwise.
3318     bool operator!=(const db_multimap<kdt, ddt, value_type_sub>& m2) const
3319     {
3320         return !this->operator==(m2);
3321     }
3322     ////////////////////////////////////////////////////////////////
3323     
3324 protected:
3325     typedef ddt mapped_type;
3326     typedef value_type_sub tkpair;
3327     typedef int (*bt_compare_fcn_t)(Db *db, const Dbt *dbt1, 
3328         const Dbt *dbt2, size_t *locp);
3329 
3330     friend class db_map_iterator<kdt, _DB_STL_set_value<kdt>, 
3331         value_type_sub>;
3332     friend class db_map_iterator<kdt, ddt, value_type_sub>;
3333 
3334     db_multimap(BulkRetrievalOption &opt) : base(opt){}
3335 private:
3336     value_type_sub operator[] (const key_type& x)
3337     {
3338         THROW(NotSupportedException, ("db_multimap<>::operator[]"));
3339     }
3340 
3341     value_type_sub operator[] (const key_type& x) const
3342     {
3343         THROW(NotSupportedException, ("db_multimap<>::operator[]"));
3344         
3345     }
3346     
3347     virtual const char* verify_config(Db*dbp, DbEnv* envp) const
3348     {
3349         DBTYPE dbtype;
3350         u_int32_t oflags, sflags;
3351         int ret;
3352         const char *err = NULL;
3353 
3354         err = db_container::verify_config(dbp, envp);
3355         if (err)
3356             return err;
3357 
3358         BDBOP(dbp->get_type(&dbtype), ret);
3359         BDBOP(dbp->get_open_flags(&oflags), ret);
3360         BDBOP(dbp->get_flags(&sflags), ret);
3361 
3362         if (dbtype != DB_BTREE && dbtype != DB_HASH)
3363             err = 
3364 "wrong database type, only DB_BTREE and DB_HASH allowed for db_map<> class";
3365         if (oflags & DB_TRUNCATE)
3366             err = 
3367 "do not specify DB_TRUNCATE flag to create a db_map<> object";
3368 
3369         // Can't go without no dup or dupsort flag set.
3370         if (!((sflags & DB_DUP) || (sflags & DB_DUPSORT)))
3371             err = 
3372 "db_multimap<> can not be backed by database not permitting duplicate keys";
3373         
3374         if (sflags & DB_RECNUM)
3375             err = "no DB_RECNUM flag allowed in db_map<>";
3376         
3377         return err;
3378         
3379     }
3380 
3381     inline void copy_db(db_multimap<kdt, ddt, value_type_sub> &x)
3382     {    
3383 
3384         // Make sure clear can succeed if there are cursors 
3385         // open in other threads.
3386         this->clear(false);
3387         insert(x.begin(), x.end());
3388         
3389     }
3390 
3391 };// db_multimap<>
3392 //@} //dbstl_containers
3393 END_NS
3394 
3395 #endif // !_DB_STL_DB_MAP_H_