summaryrefslogtreecommitdiff
path: root/src/mongo/db/client.h
diff options
context:
space:
mode:
authorGeert Bosch <geert@mongodb.com>2014-10-31 17:39:07 -0400
committerGeert Bosch <geert@mongodb.com>2014-11-02 15:56:38 -0500
commit0f3ef4550c44a21aa7658586789c97505adf51a6 (patch)
tree7a00a68432e440014f154ed918ed9f0165f816f3 /src/mongo/db/client.h
parent9eb7ba71ac9f3d056b7b1f41e384a9bb732078c0 (diff)
downloadmongo-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.h171
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();