|
||||
File indexing completed on 2024-05-18 08:29:47
0001 /*- 0002 * Copyright (c) 2009, 2020 Oracle and/or its affiliates. All rights reserved. 0003 * 0004 * See the file LICENSE for license information. 0005 * 0006 * $Id$ 0007 */ 0008 0009 #ifndef _DB_STL_RESOURCE_MANAGER_H__ 0010 #define _DB_STL_RESOURCE_MANAGER_H__ 0011 0012 #include <map> 0013 #include <vector> 0014 #include <stack> 0015 #include <set> 0016 0017 #include "dbstl_common.h" 0018 #include "dbstl_inner_utility.h" 0019 0020 START_NS(dbstl) 0021 0022 class DbCursorBase; 0023 using std::map; 0024 using std::multimap; 0025 using std::set; 0026 using std::stack; 0027 0028 /////////////////////////////////////////////////////////////////////// 0029 ///////////////////////////////////////////////////////////////////////// 0030 // 0031 // ResourceManager class definition 0032 // 0033 // This class manages all the Berkeley DB handles and their mapping 0034 // relationship. When it's only thread-specific instance is destructed, 0035 // these handles are automatically closed in the correct order (the db and 0036 // dbenv handles will be closed when the last thread using the handles in 0037 // the process is destructed). 0038 // 0039 // The Db* and DbEnv* handles are process-wide global, they can be shared 0040 // among multithreads, so they are stored into a static stl map, and access 0041 // to the two map objects (open_dbs_ & open_envs_) is protected by a process 0042 // wide mutex because few stl implementations support multithreaded access. 0043 // We use reference counting in the two map objects to make sure each handle 0044 // is closed when the last thread using it exits. Each thread sharing the 0045 // handle should call ResourceManager::register_db/dbenv to tell DBSTL that 0046 // it will use the handle, otherwise the handle may be closed prematurely. 0047 // 0048 // The transaction and cursor handles are thread specific. They are stored 0049 // into stl containers and each instance of the ResourceManager is stored 0050 // into thread local storage(TLS) of each thread. Thus the DB STL containers 0051 // are thread safe. 0052 // 0053 0054 // This map contains cursors of all open databases opened in the same thread. 0055 // We can only duplicate a cursor of the same database; We don't allow sharing 0056 // Berkeley DB cursor handles across multiple threads, each thread needs to 0057 // open their own cursor handle; 0058 // 0059 typedef map<Db *, set<dbstl::DbCursorBase *> *> db_csr_map_t; 0060 0061 // The set of cursors that belong to a db handle or a transaction. 0062 typedef set<dbstl::DbCursorBase *> csrset_t; 0063 // The cursors opened in each transaction. 0064 typedef map<DbTxn *, set<DbCursorBase *> *> txncsr_t; 0065 0066 // This stack contains the transactions started in current thread. Each 0067 // transaction is the child transaction of the one under it in the stack. 0068 // 0069 // We support nested transactions for those created by the dbstl 0070 // users, but still keep reference counting for dbstl internally 0071 // created transactions so that the autocommit methods are really 0072 // autocommit with least overhead (nested transactions are overheads). The 0073 // way we keep both nested transaction and reference counting to internal 0074 // transactions in the same stack is: 0075 // 1. When creating an external transaction, look at the stack top, if there 0076 // is a transaction, it must be an external one too, so use it as the parent 0077 // transaction to create the external transaction. 0078 // 2. When creating an internal transaction, look at the stack top, if there 0079 // is one, call it T, look for its the reference counting, if there is a 0080 // reference count for it, T is an internal one, so we increment its 0081 // reference count; Otherwise, T is an external one, and according to the DB 0082 // autocommit semantics, this function should be in T's context, so we 0083 // simply use T and add it to the reference counting structure, and set its 0084 // reference count to 2. 0085 // 0086 // We don't support expanding a transaction across multiple threads, 0087 // because there are many restrictions to doing so, making it meaningless. 0088 // 0089 typedef stack<DbTxn *> txnstk_t; 0090 typedef map<DbEnv *, txnstk_t> env_txns_t; 0091 0092 #ifdef WIN32 0093 #pragma warning( push ) 0094 #pragma warning( disable:4251 ) 0095 #endif 0096 // This class is used to wrap a ResourceManager instance pointer, so that 0097 // each thread has its own ResourceManager singleton. 0098 0099 #ifdef TLS_DECL_MODIFIER 0100 template <Typename T> 0101 class TlsWrapper 0102 { 0103 public: 0104 static T *get_tls_obj() 0105 { 0106 return tinst_; 0107 } 0108 0109 static void set_tls_obj(T *objp) 0110 { 0111 tinst_ = objp; 0112 } 0113 0114 private: 0115 TlsWrapper(){} 0116 0117 // Thread local pointer to the instance of type T. 0118 static TLS_DECL_MODIFIER T *tinst_; 0119 }; // TlsWrapper<> 0120 0121 #elif defined(HAVE_PTHREAD_TLS) 0122 template <Typename T> 0123 class TlsWrapper 0124 { 0125 public: 0126 static T *get_tls_obj() 0127 { 0128 return static_cast<T*>(pthread_getspecific(tls_key_)); 0129 } 0130 0131 static void set_tls_obj(T *objp) 0132 { 0133 pthread_setspecific(tls_key_, objp); 0134 } 0135 0136 // Friend declarations don't work portably, so we have to declare 0137 // tls_key_ public. 0138 static pthread_key_t tls_key_; 0139 private: 0140 TlsWrapper(); 0141 0142 }; // TlsWrapper<> 0143 0144 #else 0145 #error "A multi-threaded build of STL for Berkeley DB requires thread local storage. None is configured." 0146 #endif 0147 0148 class _exported ResourceManager : public DbstlGlobalInnerObject 0149 { 0150 private: 0151 0152 ResourceManager(void); 0153 // open_dbs_ & open_envs_ are shared among threads, protected by 0154 // ghdl_mtx; 0155 static map<Db *, size_t> open_dbs_; 0156 static map<DbEnv *, size_t>open_envs_; 0157 0158 // Transaction stack of all environments. Use a stack to allow nested 0159 // transactions. The transaction at the top of the stack is the 0160 // current active transaction. 0161 // 0162 env_txns_t env_txns_; 0163 0164 // Cursors opened in a corresponding transaction context. When 0165 // committing or aborting a transaction, first close all open cursors. 0166 // 0167 txncsr_t txn_csrs_; 0168 0169 // If in container X, its methods X::A and X::B both call begin and 0170 // commit transaction. X::A calls X::B after it's begin transaction 0171 // call, then X::B will commit the transaction prematurally. To avoid 0172 // will commit the only transaction prematurally, to avoid this, we use 0173 // this, we use this map to record each transaction's reference count. 0174 // Each begin/commit_txn() will increment/decrement the reference 0175 // count, when reference count goes to 0, the transaction is committed. 0176 // Abort_txn will unconditionally abort the transaction. 0177 // 0178 map<DbTxn *, size_t> txn_count_; 0179 0180 // Contains the cursors opened in the current thread for each database, 0181 // So that we can close them in the right way, freeing any Berkeley DB 0182 // handles before exiting. 0183 // 0184 db_csr_map_t all_csrs_; 0185 0186 // Remove cursors opened in the transaction txn's context, should be 0187 // called before commiting or aborting a transaction. 0188 // 0189 void remove_txn_cursor(DbTxn *txn); 0190 0191 // Add a cursor to the current transaction's set of open cursors. 0192 void add_txn_cursor(DbCursorBase *dcbcsr, DbEnv *env); 0193 0194 // The environment mtx_env_ and mtx_handle_ are used for synchronizing 0195 // multiple threads' access to open_dbs_ and open_envs_ and glob_objs_. 0196 // They are discarded when program exits, no deallocation/release 0197 // is done. 0198 static DbEnv *mtx_env_; 0199 static db_mutex_t mtx_handle_; 0200 static db_mutex_t mtx_globj_; 0201 static set<DbstlGlobalInnerObject *> glob_objs_; 0202 0203 // This set stores db handles that are new'ed by open_db, and thus 0204 // should be deleted after this db is closed automatically by dbstl. 0205 // If a db is new'ed and created by user without using open_db, users 0206 // should delete it. 0207 static set<Db *> deldbs; 0208 static set<DbEnv *> delenvs; // Similar to deldbs, works with open_envs. 0209 static void set_global_callbacks(); 0210 public: 0211 0212 // This function should be called in a single thread inside a process, 0213 // before any use of dbstl. 0214 static void global_startup(); 0215 // Delete registered DbstlGlobalInnerObject objects. 0216 static void global_exit(); 0217 0218 // Delete the ResourceManager singleton of current thread, and remove it 0219 // from glob_objs. 0220 static void thread_exit(); 0221 static void register_global_object(DbstlGlobalInnerObject *gio); 0222 static DbEnv *get_mutex_env() { return mtx_env_; } 0223 // Lock mtx_handle_, if it is 0, allocate it first. 0224 static int global_lock(db_mutex_t dbcontainer_mtx); 0225 static int global_unlock(db_mutex_t dbcontainer_mtx); 0226 // Close pdb regardless of its reference count, users must make sure 0227 // pdb is not used by others before calling this method. We can't 0228 // close by reference count in this method, otherwise when the thread 0229 // exits pdb's reference count is decremented twice. 0230 void close_db(Db *pdb); 0231 0232 // Close all db handles regardless of reference count, used to clean up 0233 // the calling thread's ResourceManager singleton. 0234 void close_all_dbs(); 0235 0236 // Close specified db env handle and remove it from resource manager. 0237 void close_db_env(DbEnv *penv); 0238 0239 // Close and remove all db env registered in the resource manager. 0240 // Used to clean up the calling thread's ResourceManager singleton. 0241 void close_all_db_envs(); 0242 0243 // Begin a new transaction in the specified environment. When outtxn 0244 // is non-zero support nested transactions - the new transaction will 0245 // be started as a child of the current transaction. If outtxn is 0 0246 // we are starting an internal transaction for autocommit, no new 0247 // transaction will be started, but the current transaction's 0248 // reference count will be incremented if it already has a reference 0249 // count; otherwise, it was created by user, and we simply use this 0250 // transaction, set its reference count to 2. 0251 // 0252 // This function is called by both containers to begin an internal 0253 // transaction for autocommit, and by db stl users to begin an 0254 // external transaction. 0255 // 0256 DbTxn *begin_txn(u_int32_t flags/* flags for DbEnv::txn_begin */, 0257 DbEnv *env, int outtxn); 0258 0259 // Decrement reference count if it exists and if it goes to 0, commit 0260 // current transaction T opened in env; 0261 // If T has no reference count(outside transaction), simply find 0262 // it by popping the stack and commit it. 0263 // 0264 // This function is called by db_container to commit a transaction 0265 // for auto commit, also can be called by db stl user to commit 0266 // an external explicit transaction. 0267 // 0268 void commit_txn(DbEnv *env, u_int32_t flags = 0); 0269 0270 // Commit specified transaction txn: find it by popping the stack, 0271 // discard all its child transactions and commit it. 0272 // 0273 // This function is called by dbstl user to commit an external 0274 // explicit transaction. 0275 // 0276 void commit_txn(DbEnv *env, DbTxn *txn, u_int32_t flags = 0); 0277 0278 // Abort current transaction of the environment. 0279 // 0280 void abort_txn(DbEnv *env); 0281 0282 // Abort specified transaction: find it by popping the stack, discard 0283 // all its child transactions and abort it. 0284 // 0285 // This function is called by dbstl user to abort an external 0286 // explicit transaction. 0287 // 0288 void abort_txn(DbEnv *env, DbTxn *txn); 0289 0290 // Set env's current transaction handle. The original transaction 0291 // handle is returned without aborting or commiting. This API can be 0292 // used to share a transaction handle among multiple threads. 0293 DbTxn* set_current_txn_handle(DbEnv *env, DbTxn *newtxn); 0294 0295 // Register a Db handle. This handle and handles opened in it 0296 // will be closed by ResourceManager, so application code must not 0297 // try to close or delete it. Users can configure the handle before 0298 // opening the Db and then register it via this function. 0299 // 0300 void register_db(Db *pdb1); 0301 0302 // Register a DbEnv handle. This handle and handles opened in it 0303 // will be closed by ResourceManager, so application code must not try 0304 // to close or delete it. Users can configure the handle before 0305 // opening the Environment and then register it via this function. 0306 // 0307 void register_db_env(DbEnv *env1); 0308 0309 // Helper function to open a database and register it into 0310 // ResourceManager. 0311 // Users can set the create flags, open flags, db type, and flags 0312 // needing to be set before open. 0313 // 0314 Db* open_db (DbEnv *penv, const char *filename, DBTYPE dbtype, 0315 u_int32_t oflags, u_int32_t set_flags, int mode = 0644, 0316 DbTxn* txn = NULL, u_int32_t cflags = 0, 0317 const char *dbname = NULL); 0318 0319 // Helper function to open a dbenv and register it into 0320 // ResourceManager. 0321 // Users can set the create flags, open flags, db type, and flags 0322 // needing to be set before open. 0323 // 0324 DbEnv *open_env(const char *env_home, u_int32_t set_flags, 0325 u_int32_t oflags = DB_CREATE | DB_INIT_MPOOL, 0326 u_int32_t cachesize = 4 * 1024 * 1024, int mode = 0644, 0327 u_int32_t cflags = 0/* Flags for DbEnv constructor. */); 0328 0329 static ResourceManager *instance(); 0330 0331 // Release all registered resource in the right order. 0332 virtual ~ResourceManager(void); 0333 0334 // Return current transaction of environment env, that is, the one on 0335 // the transaction stack top, the active one. 0336 // 0337 DbTxn *current_txn(DbEnv *env); 0338 0339 // Open a Berkeley DB cursor. 0340 // 0341 int open_cursor(DbCursorBase *dcbcsr, Db *pdb, int flags = 0); 0342 0343 // Add a db-cursor mapping. 0344 void add_cursor(Db *dbp, DbCursorBase *csr); 0345 0346 // Close all cursors opened in the database. 0347 size_t close_db_cursors(Db *dbp1); 0348 0349 // Close and remove a cursor from ResourceManager. 0350 // 0351 int remove_cursor(DbCursorBase *csr, bool remove_from_txncsrs = true); 0352 0353 }; // ResourceManager 0354 0355 END_NS 0356 #ifdef WIN32 0357 #pragma warning( pop ) 0358 #endif 0359 #endif // !_DB_STL_RESOURCE_MANAGER_H__
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.5 LXR engine. The LXR team |