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