Back to home page

EIC code displayed by LXR

 
 

    


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

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