diff options
author | Charlie Swanson <charlie.swanson@mongodb.com> | 2017-03-02 13:54:24 -0500 |
---|---|---|
committer | Charlie Swanson <charlie.swanson@mongodb.com> | 2017-03-15 11:03:44 -0400 |
commit | f05b9437fbdc53deecf55ed3c20e36af3d733953 (patch) | |
tree | 8b66acc133f83f27ef00f31600538f225ec2746a /src/mongo/db/db_raii.h | |
parent | a1f15dfd788a78da77bda6675132d4144691fce1 (diff) | |
download | mongo-f05b9437fbdc53deecf55ed3c20e36af3d733953.tar.gz |
SERVER-22541 Refactor RAII locking helpers.
Removes the class 'ScopedTransaction' and moves the responsibility of
abandoning the snapshot onto the GlobalLock class. Also renames the
AutoGetCollectionForRead class to AutoGetCollectionForReadCommand, and
adds a new AutoGetCollectionForRead class. Unlike
AutoGetCollectionForReadCommand, this new class will not update the
namespace on the CurrentOp object, nor will it add an entry to Top.
Diffstat (limited to 'src/mongo/db/db_raii.h')
-rw-r--r-- | src/mongo/db/db_raii.h | 107 |
1 files changed, 87 insertions, 20 deletions
diff --git a/src/mongo/db/db_raii.h b/src/mongo/db/db_raii.h index 04d1658b24d..8060d06f000 100644 --- a/src/mongo/db/db_raii.h +++ b/src/mongo/db/db_raii.h @@ -46,6 +46,9 @@ class Collection; * 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(). * + * Use this when you want to do a database-level operation, like read a list of all collections, or + * drop a collection. + * * It is guaranteed that the lock will be released when this object goes out of scope, therefore * the database reference returned by this class should not be retained. */ @@ -68,6 +71,10 @@ private: * RAII-style class, which acquires a locks on the specified database and collection in the * requested mode and obtains references to both. * + * Use this when you want to access something at the collection level, but do not want to do any of + * the tasks associated with the 'ForRead' variants below. For example, you can use this to access a + * Collection's CursorManager, or to remove a document. + * * It is guaranteed that locks will be released when this object goes out of scope, therefore * the database and the collection references returned by this class should not be retained. */ @@ -87,10 +94,10 @@ public: : AutoGetCollection(opCtx, nss, modeDB, modeColl, ViewMode::kViewsForbidden) {} /** - * This constructor is inteded for internal use and should not be used outside this file. - * AutoGetCollectionForRead and AutoGetCollectionOrViewForRead use ViewMode to determine whether - * or not it is permissible to obtain a handle on a view namespace. Use another constructor or - * another AutoGet class instead. + * This constructor is intended for internal use and should not be used outside this file. + * AutoGetCollectionForReadCommand and AutoGetCollectionOrViewForReadCommand use 'viewMode' to + * determine whether or not it is permissible to obtain a handle on a view namespace. Use + * another constructor or another 'AutoGet' class instead. */ AutoGetCollection(OperationContext* opCtx, const NamespaceString& nss, @@ -98,10 +105,16 @@ public: LockMode modeColl, ViewMode viewMode); + /** + * Returns nullptr if the database didn't exist. + */ Database* getDb() const { return _autoDb.getDb(); } + /** + * Returns nullptr if the collection didn't exist. + */ Collection* getCollection() const { return _coll; } @@ -115,7 +128,8 @@ private: Collection* const _coll; friend class AutoGetCollectionForRead; - friend class AutoGetCollectionOrViewForRead; + friend class AutoGetCollectionForReadCommand; + friend class AutoGetCollectionOrViewForReadCommand; }; /** @@ -125,6 +139,9 @@ private: * MODE_IX or MODE_X. If the database needs to be created, the lock will automatically be * reacquired as MODE_X. * + * Use this when you are about to perform a write, and want to create the database if it doesn't + * already exist. + * * 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. */ @@ -147,17 +164,20 @@ public: } private: - ScopedTransaction _transaction; 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 + * RAII-style class, which would acquire the appropriate hierarchy of locks for obtaining * a particular collection and would retrieve a reference to the collection. In addition, this - * utility validates the shard version for the specified namespace and sets the current operation's - * namespace for the duration while this object is alive. + * utility will ensure that the read will be performed against an appropriately committed snapshot + * if the operation is using a readConcern of 'majority'. + * + * Use this when you want to read the contents of a collection, but you are not at the top-level of + * some command. This will ensure your reads obey any requested readConcern, but will not update the + * status of CurrentOp, or add a Top entry. * * 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. @@ -169,7 +189,15 @@ public: AutoGetCollectionForRead(OperationContext* opCtx, const NamespaceString& nss) : AutoGetCollectionForRead(opCtx, nss, AutoGetCollection::ViewMode::kViewsForbidden) {} - ~AutoGetCollectionForRead(); + /** + * This constructor is intended for internal use and should not be used outside this file. + * AutoGetCollectionForReadCommand and AutoGetCollectionOrViewForReadCommand use 'viewMode' to + * determine whether or not it is permissible to obtain a handle on a view namespace. Use + * another constructor or another 'AutoGet' class instead. + */ + AutoGetCollectionForRead(OperationContext* opCtx, + const NamespaceString& nss, + AutoGetCollection::ViewMode viewMode); Database* getDb() const { return _autoColl->getDb(); @@ -180,34 +208,73 @@ public: } private: - void _ensureMajorityCommittedSnapshotIsValid(const NamespaceString& nss); + void _ensureMajorityCommittedSnapshotIsValid(const NamespaceString& nss, + OperationContext* opCtx); - const Timer _timer; + boost::optional<AutoGetCollection> _autoColl; +}; + +/** + * RAII-style class, which would acquire the appropriate hierarchy of locks for obtaining + * a particular collection and would retrieve a reference to the collection. In addition, this + * utility validates the shard version for the specified namespace and sets the current operation's + * namespace for the duration while this object is alive. + * + * Use this when you are a read-only command and you know that your target namespace is a collection + * (not a view). In addition to ensuring your read obeys any requested readConcern, this will add a + * Top entry upon destruction and ensure the CurrentOp object has the right namespace and has + * started its timer. + * + * 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. + */ +class AutoGetCollectionForReadCommand { + MONGO_DISALLOW_COPYING(AutoGetCollectionForReadCommand); + +public: + AutoGetCollectionForReadCommand(OperationContext* opCtx, const NamespaceString& nss) + : AutoGetCollectionForReadCommand( + opCtx, nss, AutoGetCollection::ViewMode::kViewsForbidden) {} + + ~AutoGetCollectionForReadCommand(); + + Database* getDb() const { + return _autoCollForRead->getDb(); + } + + Collection* getCollection() const { + return _autoCollForRead->getCollection(); + } + +private: OperationContext* const _opCtx; - const ScopedTransaction _transaction; + const Timer _timer; protected: - AutoGetCollectionForRead(OperationContext* opCtx, - const NamespaceString& nss, - AutoGetCollection::ViewMode viewMode); + AutoGetCollectionForReadCommand(OperationContext* opCtx, + const NamespaceString& nss, + AutoGetCollection::ViewMode viewMode); /** * This protected section must come after the private section because * AutoGetCollectionOrViewForRead needs access to _autoColl, but _autoColl must be initialized * after _transaction. */ - boost::optional<AutoGetCollection> _autoColl; + boost::optional<AutoGetCollectionForRead> _autoCollForRead; }; /** * RAII-style class for obtaining a collection or view for reading. The pointer to a view definition * is nullptr if it does not exist. + * + * Use this when you are a read-only command, but have not yet determined if the namespace is a view + * or a collection. */ -class AutoGetCollectionOrViewForRead final : public AutoGetCollectionForRead { - MONGO_DISALLOW_COPYING(AutoGetCollectionOrViewForRead); +class AutoGetCollectionOrViewForReadCommand final : public AutoGetCollectionForReadCommand { + MONGO_DISALLOW_COPYING(AutoGetCollectionOrViewForReadCommand); public: - AutoGetCollectionOrViewForRead(OperationContext* opCtx, const NamespaceString& nss); + AutoGetCollectionOrViewForReadCommand(OperationContext* opCtx, const NamespaceString& nss); ViewDefinition* getView() const { return _view.get(); |