diff options
author | Geert Bosch <geert@mongodb.com> | 2014-10-31 17:39:07 -0400 |
---|---|---|
committer | Geert Bosch <geert@mongodb.com> | 2014-11-02 15:56:38 -0500 |
commit | 0f3ef4550c44a21aa7658586789c97505adf51a6 (patch) | |
tree | 7a00a68432e440014f154ed918ed9f0165f816f3 /src/mongo/db/client.h | |
parent | 9eb7ba71ac9f3d056b7b1f41e384a9bb732078c0 (diff) | |
download | mongo-0f3ef4550c44a21aa7658586789c97505adf51a6.tar.gz |
SERVER-15888: Ensure MODE_X on implicit DB creation
Also adds new API to DBLock to allow relocking in different mode.
Diffstat (limited to 'src/mongo/db/client.h')
-rw-r--r-- | src/mongo/db/client.h | 171 |
1 files changed, 103 insertions, 68 deletions
diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index 033c6049577..ce2d50717de 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -56,11 +56,98 @@ namespace mongo { class Collection; class AbstractMessagingPort; - TSP_DECLARE(Client, currentClient) typedef long long ConnectionId; + /** + * RAII-style class, which acquires a lock on the specified database in the requested mode and + * obtains a reference to the database. Used as a shortcut for calls to dbHolder().get(). + * + * It is guaranteed that locks will be released when this object goes out of scope, therefore + * the database reference returned by this class should not be retained. + * + * TODO: This should be moved outside of client.h (maybe dbhelpers.h) + */ + class AutoGetDb { + MONGO_DISALLOW_COPYING(AutoGetDb); + public: + AutoGetDb(OperationContext* txn, const StringData& ns, LockMode mode); + + Database* getDb() const { + return _db; + } + private: + const Lock::DBLock _dbLock; + Database* const _db; + }; + + /** + * RAII-style class, which acquires a lock on the specified database in the requested mode and + * obtains a reference to the database, creating it was non-existing. Used as a shortcut for + * calls to dbHolder().openDb(), taking care of locking details. The requested mode must be + * MODE_IX or MODE_X. If the database needs to be created, the lock will automatically be + * reacquired as MODE_X. + * + * It is guaranteed that locks will be released when this object goes out of scope, therefore + * the database reference returned by this class should not be retained. + * + * TODO: This should be moved outside of client.h (maybe dbhelpers.h) + */ + class AutoGetOrCreateDb { + MONGO_DISALLOW_COPYING(AutoGetOrCreateDb); + public: + AutoGetOrCreateDb(OperationContext* txn, const StringData& ns, LockMode mode); + + Database* getDb() { + return _db; + } + + bool justCreated() { + return _justCreated; + } + private: + Lock::DBLock _dbLock; // not const, as we may need to relock for implicit create + Database* _db; + bool _justCreated; + }; + + /** + * RAII-style class, which would acquire the appropritate hierarchy of locks for obtaining + * a particular collection and would retrieve a reference to the collection. + * + * It is guaranteed that locks will be released when this object goes out of scope, therefore + * database and collection references returned by this class should not be retained. + * + * TODO: This should be moved outside of client.h (maybe dbhelpers.h) + */ + class AutoGetCollectionForRead { + MONGO_DISALLOW_COPYING(AutoGetCollectionForRead); + public: + AutoGetCollectionForRead(OperationContext* txn, const std::string& ns); + AutoGetCollectionForRead(OperationContext* txn, const NamespaceString& nss); + ~AutoGetCollectionForRead(); + + Database* getDb() const { + return _db.getDb(); + } + + Collection* getCollection() const { + return _coll; + } + + private: + void _init(); + + const Timer _timer; + OperationContext* const _txn; + const NamespaceString _nss; + const AutoGetDb _db; + const Lock::CollectionLock _collLock; + + Collection* _coll; + }; + /** the database's concept of an outside "client" */ class Client : public ClientBasic { public: @@ -155,10 +242,20 @@ namespace mongo { /** this is probably what you want */ Context(OperationContext* txn, const std::string& ns, bool doVersion = true); - /** note: this does not call finishInit -- i.e., does not call - ensureShardVersionOKOrThrow for example. - see also: reset(). - */ + /** + * Below still calls _finishInit, but assumes database has already been acquired + * or just created. + */ + Context(OperationContext* txn, + const std::string& ns, + Database* db, + bool justCreated); + + /** + * note: this does not call _finishInit -- i.e., does not call + * ensureShardVersionOKOrThrow for example. + * see also: reset(). + */ Context(OperationContext* txn, const std::string& ns, Database * db); ~Context(); @@ -209,74 +306,12 @@ namespace mongo { private: OperationContext* _txn; NamespaceString _nss; - Lock::DBLock _dblk; + AutoGetOrCreateDb _autodb; Lock::CollectionLock _collk; Context _c; }; - }; // class Client - - /** - * RAII-style class, which acquires a lock on the specified database in the requested mode and - * obtains a reference to the database. Used as a shortcut for calls to dbHolder().get(). - * - * It is guaranteed that locks will be released when this object goes out of scope, therefore - * the database reference returned by this class should not be retained. - * - * TODO: This should be moved outside of client.h (maybe dbhelpers.h) - */ - class AutoGetDb { - MONGO_DISALLOW_COPYING(AutoGetDb); - public: - AutoGetDb(OperationContext* txn, const StringData& ns, LockMode mode); - - Database* getDb() const { - return _db; - } - - private: - const Lock::DBLock _dbLock; - Database* const _db; - }; - - /** - * RAII-style class, which would acquire the appropritate hierarchy of locks for obtaining - * a particular collection and would retrieve a reference to the collection. - * - * It is guaranteed that locks will be released when this object goes out of scope, therefore - * database and collection references returned by this class should not be retained. - * - * TODO: This should be moved outside of client.h (maybe dbhelpers.h) - */ - class AutoGetCollectionForRead { - MONGO_DISALLOW_COPYING(AutoGetCollectionForRead); - public: - AutoGetCollectionForRead(OperationContext* txn, const std::string& ns); - AutoGetCollectionForRead(OperationContext* txn, const NamespaceString& nss); - ~AutoGetCollectionForRead(); - - Database* getDb() const { - return _db.getDb(); - } - - Collection* getCollection() const { - return _coll; - } - - private: - void _init(); - - const Timer _timer; - OperationContext* const _txn; - const NamespaceString _nss; - const AutoGetDb _db; - const Lock::CollectionLock _collLock; - - Collection* _coll; - }; - - /** get the Client object for this thread. */ inline Client& cc() { Client * c = currentClient.get(); |