|
||||
File indexing completed on 2025-01-17 09:55:17
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_CONTAINER_H__ 0010 #define _DB_STL_CONTAINER_H__ 0011 0012 #include "dbstl_common.h" 0013 #include "dbstl_resource_manager.h" 0014 #include <assert.h> 0015 0016 START_NS(dbstl) 0017 0018 class ResourceManager; 0019 0020 ////////////////////////////////////////////////////////////////////////// 0021 ////////////////////////////////////////////////////////////////////////// 0022 // 0023 // db_container class definition 0024 // 0025 // This class's begin_txn, commit/abort_txn is used to wrap each DB related 0026 // operation inside dbstl. When auto commit is enabled, each operation will 0027 // be auto committed before returning, and aborted when an exception is thrown. 0028 // 0029 // It also contains members to hold all needed parameters and flags for 0030 // transaction and cursor related calls. 0031 // 0032 // Container classes will inherit from this class. Each container will enclose 0033 // every db related operation with db_container::begin_txn and 0034 // db_container::commit_txn, and if exception is not caught, abort_txn() 0035 // should be called. 0036 0037 /** \defgroup dbstl_containers dbstl container classes 0038 A dbstl container is very much like a C++ STL container. It stores a 0039 collection of data items, or key/data pairs. 0040 Each container is backed by a Berkeley DB database created in an explicit 0041 database environment or an internal private environment; And the database 0042 itself can be created explicitly with all kinds of configurations, or 0043 by dbstl internally. For each type of container, some specific type of 0044 database and/or configurations must be used or specified to the database 0045 and its environment. dbstl will check the database and environment conform 0046 to the requirement. When users don't have a chance to specify a container's 0047 backing database and environment, like in copy constructors, dbstl will 0048 create proper databases and/or environment for it. There are two helper 0049 functions to make it easier to create/open an environment or database, they 0050 are dbstl::open_db() and dbstl::open_env(); 0051 \sa dbstl::open_db() dbstl::open_env() db_vector db_map db_multimap db_set 0052 db_multiset 0053 */ 0054 0055 /** \ingroup dbstl_containers 0056 @{ 0057 This class is the base class for all db container classes, you don't directly 0058 use this class, but all container classes inherit from this class, so you need 0059 to know the methods that can be accessed via concrete container classes. 0060 This class is also used to support auto commit transactions. Autocommit is 0061 enabled when DB_AUTO_COMMIT is set to the database or database environment 0062 handle and the environment is transactional. 0063 0064 Inside dbstl, there are transactions begun and committed/aborted if the backing 0065 database and/or environment requires auto commit, and there are cursors 0066 opened internally, and you can set the flags used by the transaction and cursor 0067 functions via set functions of this class. 0068 0069 All dbstl containers are fully multi-threaded, you should not need any 0070 synchronization to use them in the correct way, but this class is not thread 0071 safe, access to its members are not proctected by any mutex because the data 0072 members of this class are supposed to be set before they are used, 0073 and remain read only afterwards. If this is not the case, you must synchronize 0074 the access. 0075 */ 0076 class _exported db_container 0077 { 0078 private: 0079 // By default these flags are 0, users should configure these values 0080 // on container initialization. 0081 // 0082 u_int32_t txn_begin_flags_, commit_flags_; 0083 mutable u_int32_t cursor_oflags_; 0084 0085 // Berkeley DB database handle for each container. Subclasses do not 0086 // need to define it. 0087 // 0088 Db *pdb_; 0089 0090 // Berkeley DB environment handle in which the db handle is opened. 0091 DbEnv *dbenv_; 0092 0093 // db_map_iterator<> needs to know whether the container is a 0094 // db_(multi)set or not 0095 // 0096 bool is_set_; 0097 0098 // Determined automatically, by inspecting users the Berkeley DB 0099 // database and environment configuration options. 0100 // 0101 bool auto_commit_; 0102 0103 // If exisiting random temporary database name generation mechanism is 0104 // still causing name clashes, users can set this global suffix number 0105 // which will be append to each temporary database file name and by 0106 // default it is 0. there is a dbstl::set_global_dbfile_suffix_number 0107 // to do so. 0108 static u_int32_t g_db_file_suffix_; 0109 friend void set_global_dbfile_suffix_number(u_int32_t); 0110 protected: 0111 0112 // Does not clone or copy data from database parameter. 0113 // Return the db file name back in the dbfname parameter. 0114 // We construct a default database name the user can rename it using 0115 // either DbEnv::dbrename or Db::rename. 0116 // 0117 Db* clone_db_config(Db *dbp, std::string &dbfname); 0118 Db* clone_db_config(Db *dbp); 0119 0120 // Store the name into name parameter whose length is n. Return -1 if 0121 // not enough space. 0122 int construct_db_file_name(std::string &filename) const; 0123 0124 // Check that this container and cntnr are backed by different databases 0125 // and if any one of them is using transactions, both should be in the 0126 // same transactional environment. 0127 // Called by all deriving classes' methods 0128 // which have a container parameter. 0129 void verify_db_handles(const db_container &cntnr) const; 0130 0131 void open_db_handles(Db *&pdb, DbEnv *&penv, DBTYPE dbtype, 0132 u_int32_t oflags, u_int32_t sflags); 0133 0134 inline void set_is_set(bool b) 0135 { 0136 is_set_ = b; 0137 } 0138 0139 inline bool is_set() const 0140 { 0141 return is_set_; 0142 } 0143 0144 // Database and environment handles and autocommit and is_set_ are 0145 // not assigned, because they are the nature of my own db, not 0146 // that of dbctnr. 0147 inline const db_container &operator=(const db_container & dbctnr) 0148 { 0149 ASSIGNMENT_PREDCOND(dbctnr) 0150 txn_begin_flags_ = dbctnr.txn_begin_flags_; 0151 commit_flags_ = dbctnr.commit_flags_; 0152 cursor_oflags_ = dbctnr.cursor_oflags_; 0153 return dbctnr; 0154 } 0155 0156 public: 0157 /// Default constructor. 0158 db_container(); 0159 0160 /// Copy constructor. 0161 /// The new container will be backed by another database within the 0162 /// same environment unless dbctnr's backing database is in its own 0163 /// internal private environment. The name of the database is coined 0164 /// based on current time and thread id and some random number. If 0165 /// this is still causing naming clashes, you can set a suffix number 0166 /// via "set_global_dbfile_suffix_number" function; And following db 0167 /// file will suffix this number in the file name for additional 0168 /// randomness. And the suffix will be incremented after each such use. 0169 /// You can change the file name via DbEnv::rename. 0170 /// If dbctnr is using an anonymous database, the newly constructed 0171 /// container will also use an anonymous one. 0172 /// \param dbctnr The container to initialize this container. 0173 db_container(const db_container &dbctnr); 0174 0175 /** 0176 This constructor is not directly called by the user, but invoked by 0177 constructors of concrete container classes. The statement about the 0178 parameters applies to constructors of all container classes. 0179 \param dbp Database handle. dbp is supposed to be opened inside envp. 0180 Each dbstl container is backed by a Berkeley DB database, so dbstl 0181 will create an internal anonymous database if dbp is NULL. 0182 \param envp Environment handle. And envp can also be NULL, meaning the 0183 dbp handle may be created in its internal private environment. 0184 */ 0185 db_container(Db *dbp, DbEnv *envp); 0186 0187 /// The backing database is not closed in this function. It is closed 0188 /// when current thread exits and the database is no longer referenced 0189 /// by any other container instances in this process. 0190 /// In order to make the reference counting work alright, you must call 0191 /// register_db(Db*) and register_db_env(DbEnv*) correctly. 0192 /// \sa register_db(Db*) register_db_env(DbEnv*) 0193 virtual ~db_container(){} 0194 0195 /// \name Get and set functions for data members. 0196 /// Note that these functions are not thread safe, because all data 0197 /// members of db_container are supposed to be set on container 0198 /// construction and initialization, and remain read only afterwards. 0199 //@{ 0200 /// Get the backing database's open flags. 0201 /// \return The backing database's open flags. 0202 inline u_int32_t get_db_open_flags() const 0203 { 0204 u_int32_t oflags; 0205 pdb_->get_open_flags(&oflags); 0206 return oflags; 0207 } 0208 0209 /// Get the backing database's flags that are set via Db::set_flags() 0210 /// function. 0211 /// \return Flags set to this container's database handle. 0212 inline u_int32_t get_db_set_flags() const 0213 { 0214 u_int32_t oflags; 0215 pdb_->get_flags(&oflags); 0216 return oflags; 0217 } 0218 0219 /// Get the backing database's handle. 0220 /// \return The backing database handle of this container. 0221 inline Db* get_db_handle() const 0222 { 0223 return pdb_; 0224 } 0225 0226 /// Get the backing database environment's handle. 0227 /// \return The backing database environment handle of this container. 0228 inline DbEnv* get_db_env_handle() const 0229 { 0230 return dbenv_; 0231 } 0232 0233 /** 0234 Set the underlying database's handle, and optionally environment 0235 handle if the environment has also changed. That is, users can change 0236 the container object's underlying database while the object is alive. 0237 dbstl will verify that the handles set conforms to the concrete 0238 container's requirement to Berkeley DB database/environment handles. 0239 \param dbp The database handle to set. 0240 \param newenv The database environment handle to set. 0241 */ 0242 void set_db_handle(Db *dbp, DbEnv *newenv = NULL); 0243 0244 /** Set the flags required by the Berkeley DB functions 0245 DbEnv::txn_begin(), DbTxn::commit() and DbEnv::cursor(). These flags 0246 will be set to this container's auto commit member functions when 0247 auto commit transaction is used, except that cursor_oflags is set to 0248 the Dbc::cursor when creating an iterator for this container. 0249 By default the three flags are all zero. 0250 You can also set the values of the flags individually by using the 0251 appropriate set functions in this class. The corresponding get 0252 functions return the flags actually used. 0253 \param txn_begin_flags Flags to be set to DbEnv::txn_begin(). 0254 \param commit_flags Flags to be set to DbTxn::commit(). 0255 \param cursor_open_flags Flags to be set to Db::cursor(). 0256 */ 0257 inline void set_all_flags(u_int32_t txn_begin_flags, 0258 u_int32_t commit_flags, u_int32_t cursor_open_flags) 0259 { 0260 this->txn_begin_flags_ = txn_begin_flags; 0261 this->commit_flags_ = commit_flags; 0262 this->cursor_oflags_ = cursor_open_flags; 0263 } 0264 0265 /// Set flag of DbEnv::txn_begin() call. 0266 /// \param flag Flags to be set to DbEnv::txn_begin(). 0267 inline void set_txn_begin_flags(u_int32_t flag ) 0268 { 0269 txn_begin_flags_ = flag; 0270 } 0271 0272 /// Get flag of DbEnv::txn_begin() call. 0273 /// \return Flags to be set to DbEnv::txn_begin(). 0274 inline u_int32_t get_txn_begin_flags() const 0275 { 0276 return txn_begin_flags_; 0277 } 0278 0279 /// Set flag of DbTxn::commit() call. 0280 /// \param flag Flags to be set to DbTxn::commit(). 0281 inline void set_commit_flags(u_int32_t flag) 0282 { 0283 commit_flags_ = flag; 0284 } 0285 0286 /// Get flag of DbTxn::commit() call. 0287 /// \return Flags to be set to DbTxn::commit(). 0288 inline u_int32_t get_commit_flags() const 0289 { 0290 return commit_flags_; 0291 } 0292 0293 /// Get flag of Db::cursor() call. 0294 /// \return Flags to be set to Db::cursor(). 0295 inline u_int32_t get_cursor_open_flags() const 0296 { 0297 return cursor_oflags_; 0298 } 0299 0300 /// Set flag of Db::cursor() call. 0301 /// \param flag Flags to be set to Db::cursor(). 0302 inline void set_cursor_open_flags(u_int32_t flag) 0303 { 0304 cursor_oflags_ = flag; 0305 } 0306 //@} // getter_setters 0307 0308 protected: 0309 void init_members(); 0310 void init_members(Db *pdb, DbEnv *env); 0311 void init_members(const db_container&cnt); 0312 // Called internally by concrete container constructors. Verification 0313 // is done by the specialized constructors 0314 void set_db_handle_int(Db *dbp, DbEnv *envp) 0315 { 0316 this->pdb_ = dbp; 0317 this->dbenv_ = envp; 0318 } 0319 0320 // Child classes override this function to check the db and environment 0321 // handles are correctly configured. 0322 virtual const char* verify_config(Db* pdb, DbEnv* penv) const 0323 { 0324 if (pdb != NULL && ((pdb->get_create_flags() & 0325 DB_CXX_NO_EXCEPTIONS) == 0)) 0326 return 0327 "Db and DbEnv object must be constructed with DB_CXX_NO_EXCEPTIONS flag set."; 0328 0329 if (penv != NULL && ((penv->get_create_flags() & 0330 DB_CXX_NO_EXCEPTIONS) == 0)) 0331 return 0332 "Db and DbEnv object must be constructed with DB_CXX_NO_EXCEPTIONS flag set."; 0333 return NULL; 0334 } 0335 0336 // Use db and dbenv_ to determine whether to enable autocommit. If 0337 // DB_AUTOCOMMIT is set on dbenv_ or db and dbenv_ is transactional, 0338 // that db should be autocommit. 0339 // 0340 void set_auto_commit(Db* db); 0341 0342 // Begin a transaction. Used to make a container's db related 0343 // operations auto commit when the operation completes and abort 0344 // when the operation fails. If there is already a transaction for this 0345 // container's environment, then that transaction is used. If the 0346 // transaction was created by DB STL, its reference count is 0347 // incremented (user created and external transactions are not 0348 // reference counted because they can be nested.). 0349 inline DbTxn* begin_txn() const 0350 { 0351 DbTxn *txn = NULL; 0352 0353 if (this->auto_commit_) { 0354 txn = ResourceManager::instance()->begin_txn( 0355 this->txn_begin_flags_, dbenv_, 0); 0356 } 0357 return txn; 0358 } 0359 0360 inline void commit_txn() const 0361 { 0362 if (this->auto_commit_) { 0363 ResourceManager::instance()-> 0364 commit_txn(pdb_->get_env(), this->commit_flags_); 0365 } 0366 } 0367 0368 inline void abort_txn() const 0369 { 0370 if (this->auto_commit_) 0371 ResourceManager::instance()-> 0372 abort_txn(pdb_->get_env()); 0373 } 0374 0375 inline DbTxn *current_txn() const 0376 { 0377 return ResourceManager::instance()-> 0378 current_txn(pdb_->get_env()); 0379 } 0380 }; // db_container 0381 /** @} */ // dbstl_containers 0382 0383 /// \addtogroup dbstl_helper_classes 0384 //@{ 0385 /// Bulk retrieval configuration helper class. Used by the begin() function of 0386 /// a container. 0387 class _exported BulkRetrievalOption 0388 { 0389 public: 0390 enum Option {BulkRetrieval, NoBulkRetrieval}; 0391 0392 protected: 0393 Option bulk_retrieve; 0394 u_int32_t bulk_buf_sz_; 0395 0396 inline BulkRetrievalOption() 0397 { 0398 bulk_retrieve = NoBulkRetrieval; 0399 bulk_buf_sz_ = DBSTL_BULK_BUF_SIZE; 0400 } 0401 0402 public: 0403 inline BulkRetrievalOption(Option bulk_retrieve1, 0404 u_int32_t bulk_buf_sz = DBSTL_BULK_BUF_SIZE) 0405 { 0406 this->bulk_retrieve = bulk_retrieve1; 0407 this->bulk_buf_sz_ = bulk_buf_sz; 0408 } 0409 0410 // The following two static members should best be const, but this is 0411 // impossible because in C++ this definition is a function declaration: 0412 // const static BulkRetrievalOption BulkRetrieval(BulkRetrieval); 0413 // i.e. const static members can only be inited with default copy 0414 // constructor. 0415 // 0416 // Static data members can't be compiled into a .lib for a dll on 0417 // Windows, code using the static members will have link error--- 0418 // unresolved symbols, so we have to use a static function here. 0419 /// This function indicates that you need a bulk retrieval iterator, 0420 /// and it can be also used to optionally set the bulk read buffer size. 0421 inline static BulkRetrievalOption bulk_retrieval( 0422 u_int32_t bulk_buf_sz = DBSTL_BULK_BUF_SIZE) 0423 { 0424 return BulkRetrievalOption(BulkRetrieval, bulk_buf_sz); 0425 } 0426 0427 /// This function indicates that you do not need a bulk retrieval 0428 /// iterator. 0429 inline static BulkRetrievalOption no_bulk_retrieval() 0430 { 0431 return BulkRetrievalOption(NoBulkRetrieval, 0); 0432 } 0433 0434 /// Equality comparison. 0435 inline bool operator==(const BulkRetrievalOption& bro) const 0436 { 0437 return bulk_retrieve == bro.bulk_retrieve; 0438 } 0439 0440 /// Assignment operator. 0441 inline void operator=(BulkRetrievalOption::Option opt) 0442 { 0443 bulk_retrieve = opt; 0444 } 0445 0446 /// Return the buffer size set to this object. 0447 inline u_int32_t bulk_buf_size() 0448 { 0449 return bulk_buf_sz_; 0450 } 0451 }; 0452 //@} 0453 0454 /// \addtogroup dbstl_helper_classes 0455 //@{ 0456 /// Read-modify-write cursor configuration helper class. Used by each begin() 0457 /// function of all containers. 0458 class _exported ReadModifyWriteOption 0459 { 0460 protected: 0461 enum Option{ReadModifyWrite, NoReadModifyWrite}; 0462 Option rmw; 0463 0464 inline ReadModifyWriteOption(Option rmw1) 0465 { 0466 this->rmw = rmw1; 0467 } 0468 0469 inline ReadModifyWriteOption() 0470 { 0471 rmw = NoReadModifyWrite; 0472 } 0473 0474 public: 0475 /// Assignment operator. 0476 inline void operator=(ReadModifyWriteOption::Option rmw1) 0477 { 0478 this->rmw = rmw1; 0479 } 0480 0481 /// Equality comparison. 0482 inline bool operator==(const ReadModifyWriteOption &rmw1) const 0483 { 0484 return this->rmw == rmw1.rmw; 0485 } 0486 0487 /// Call this function to tell the container's begin() function that 0488 /// you need a read-modify-write iterator. 0489 inline static ReadModifyWriteOption read_modify_write() 0490 { 0491 return ReadModifyWriteOption(ReadModifyWrite); 0492 } 0493 0494 /// Call this function to tell the container's begin() function that 0495 /// you do not need a read-modify-write iterator. This is the default 0496 /// value for the parameter of any container's begin() function. 0497 inline static ReadModifyWriteOption no_read_modify_write() 0498 { 0499 return ReadModifyWriteOption(NoReadModifyWrite); 0500 } 0501 0502 }; 0503 //@} // dbstl_helper_classes 0504 0505 // The classes in the Berkeley DB C++ API do not expose data and p_ member. 0506 // Extend the class to provide this functionality, rather than altering the 0507 // internal implementations. 0508 // 0509 class _exported DbstlMultipleIterator : protected DbMultipleIterator 0510 { 0511 protected: 0512 DbstlMultipleIterator(const Dbt &dbt) : DbMultipleIterator(dbt) {} 0513 public: 0514 u_int32_t get_pointer() 0515 { 0516 u_int32_t off; 0517 off = (u_int32_t)((u_int8_t*)p_ - data_); 0518 return off; 0519 } 0520 0521 inline void set_pointer(u_int32_t offset) 0522 { 0523 p_ = (u_int32_t*)(data_ + offset); 0524 } 0525 0526 }; 0527 0528 class _exported DbstlMultipleKeyDataIterator : public DbstlMultipleIterator 0529 { 0530 public: 0531 DbstlMultipleKeyDataIterator(const Dbt &dbt) 0532 : DbstlMultipleIterator(dbt) {} 0533 bool next(Dbt &key, Dbt &data); 0534 }; 0535 0536 class _exported DbstlMultipleRecnoDataIterator : public DbstlMultipleIterator 0537 { 0538 public: 0539 DbstlMultipleRecnoDataIterator(const Dbt &dbt) 0540 : DbstlMultipleIterator(dbt) {} 0541 bool next(db_recno_t &recno, Dbt &data); 0542 }; 0543 0544 class _exported DbstlMultipleDataIterator : public DbstlMultipleIterator 0545 { 0546 public: 0547 DbstlMultipleDataIterator(const Dbt &dbt) 0548 : DbstlMultipleIterator(dbt) {} 0549 bool next(Dbt &data); 0550 }; 0551 0552 // These classes are used to give data values meaningful default 0553 // initializations. They are only necessary for types that do not have a 0554 // reasonable default constructor - explicitly char *, wchar_t * and T*. 0555 // The string types don't have a reasonable default initializer since we store 0556 // the underlying content, not a pointer. 0557 // So we fully instantiate types for T* and const T* and set the pointers to 0558 // NULL and leave other types intact. 0559 template <Typename T> 0560 class DbstlInitializeDefault 0561 { 0562 public: 0563 DbstlInitializeDefault(T&){} 0564 }; 0565 0566 template <Typename T> 0567 class DbstlInitializeDefault<T *> 0568 { 0569 public: 0570 DbstlInitializeDefault(T *& t){t = NULL;} 0571 }; 0572 0573 template <Typename T> 0574 class DbstlInitializeDefault<const T *> 0575 { 0576 public: 0577 DbstlInitializeDefault(const T *& t){t = NULL;} 0578 }; 0579 0580 END_NS 0581 0582 #endif //_DB_STL_CONTAINER_H__
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |