summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/auth/auth_index_d.cpp7
-rw-r--r--src/mongo/db/auth/auth_index_d.h2
-rw-r--r--src/mongo/db/auth/authorization_manager.cpp53
-rw-r--r--src/mongo/db/auth/authorization_manager.h27
-rw-r--r--src/mongo/db/auth/authorization_manager_global.cpp9
-rw-r--r--src/mongo/db/auth/authorization_manager_test.cpp50
-rw-r--r--src/mongo/db/auth/authorization_session.cpp115
-rw-r--r--src/mongo/db/auth/authorization_session.h46
-rw-r--r--src/mongo/db/auth/authorization_session_test.cpp244
-rw-r--r--src/mongo/db/auth/authz_manager_external_state.cpp8
-rw-r--r--src/mongo/db/auth/authz_manager_external_state.h18
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_d.cpp14
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_d.h6
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.cpp11
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.h9
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.cpp18
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.h9
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_s.cpp8
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_s.h8
-rw-r--r--src/mongo/db/auth/authz_session_external_state.h3
-rw-r--r--src/mongo/db/auth/authz_session_external_state_d.cpp4
-rw-r--r--src/mongo/db/auth/authz_session_external_state_d.h2
-rw-r--r--src/mongo/db/auth/authz_session_external_state_mock.h2
-rw-r--r--src/mongo/db/auth/authz_session_external_state_s.cpp4
-rw-r--r--src/mongo/db/auth/authz_session_external_state_s.h2
-rw-r--r--src/mongo/db/auth/authz_session_external_state_server_common.cpp5
-rw-r--r--src/mongo/db/auth/authz_session_external_state_server_common.h2
-rw-r--r--src/mongo/db/catalog/collection_cursor_cache.cpp34
-rw-r--r--src/mongo/db/catalog/collection_cursor_cache.h8
-rw-r--r--src/mongo/db/catalog/database_holder.cpp5
-rw-r--r--src/mongo/db/catalog/database_holder.h5
-rw-r--r--src/mongo/db/client.cpp33
-rw-r--r--src/mongo/db/client.h15
-rw-r--r--src/mongo/db/clientcursor.cpp7
-rw-r--r--src/mongo/db/cloner.cpp2
-rw-r--r--src/mongo/db/commands.cpp16
-rw-r--r--src/mongo/db/commands.h6
-rw-r--r--src/mongo/db/commands/apply_ops.cpp2
-rw-r--r--src/mongo/db/commands/auth_schema_upgrade_d.cpp2
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp14
-rw-r--r--src/mongo/db/commands/authentication_commands.h6
-rw-r--r--src/mongo/db/commands/cleanup_orphaned_cmd.cpp9
-rw-r--r--src/mongo/db/commands/clone.cpp7
-rw-r--r--src/mongo/db/commands/clone_collection.cpp5
-rw-r--r--src/mongo/db/commands/collection_to_capped.cpp2
-rw-r--r--src/mongo/db/commands/compact.cpp2
-rw-r--r--src/mongo/db/commands/copydb.cpp9
-rw-r--r--src/mongo/db/commands/copydb.h4
-rw-r--r--src/mongo/db/commands/copydb_common.cpp11
-rw-r--r--src/mongo/db/commands/create_indexes.cpp13
-rw-r--r--src/mongo/db/commands/dbhash.cpp2
-rw-r--r--src/mongo/db/commands/distinct.cpp2
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp4
-rw-r--r--src/mongo/db/commands/find_and_modify.cpp6
-rw-r--r--src/mongo/db/commands/geonear.cpp2
-rw-r--r--src/mongo/db/commands/group.cpp7
-rw-r--r--src/mongo/db/commands/index_filter_commands.cpp31
-rw-r--r--src/mongo/db/commands/index_filter_commands.h23
-rw-r--r--src/mongo/db/commands/merge_chunks_cmd.cpp4
-rw-r--r--src/mongo/db/commands/mr.cpp28
-rw-r--r--src/mongo/db/commands/oplog_note.cpp5
-rw-r--r--src/mongo/db/commands/parallel_collection_scan.cpp7
-rw-r--r--src/mongo/db/commands/parameters.cpp12
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp2
-rw-r--r--src/mongo/db/commands/plan_cache_commands.cpp26
-rw-r--r--src/mongo/db/commands/plan_cache_commands.h22
-rw-r--r--src/mongo/db/commands/rename_collection.cpp6
-rw-r--r--src/mongo/db/commands/rename_collection.h4
-rw-r--r--src/mongo/db/commands/rename_collection_common.cpp13
-rw-r--r--src/mongo/db/commands/server_status.cpp3
-rw-r--r--src/mongo/db/commands/test_commands.cpp6
-rw-r--r--src/mongo/db/commands/touch.cpp2
-rw-r--r--src/mongo/db/commands/user_management_commands.cpp199
-rw-r--r--src/mongo/db/commands/user_management_commands.h3
-rw-r--r--src/mongo/db/commands/validate.cpp2
-rw-r--r--src/mongo/db/commands/write_commands/batch_executor.cpp6
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.cpp7
-rw-r--r--src/mongo/db/commands/write_commands/write_commands.h3
-rw-r--r--src/mongo/db/commands/write_commands/write_commands_common.cpp6
-rw-r--r--src/mongo/db/commands/write_commands/write_commands_common.h6
-rw-r--r--src/mongo/db/d_concurrency.cpp4
-rw-r--r--src/mongo/db/d_concurrency.h6
-rw-r--r--src/mongo/db/db.cpp15
-rw-r--r--src/mongo/db/dbcommands.cpp41
-rw-r--r--src/mongo/db/dbhelpers.cpp21
-rw-r--r--src/mongo/db/dbhelpers.h3
-rw-r--r--src/mongo/db/dbwebserver.cpp20
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp2
-rw-r--r--src/mongo/db/fts/fts_command.cpp2
-rw-r--r--src/mongo/db/fts/fts_command.h5
-rw-r--r--src/mongo/db/fts/fts_command_mongod.cpp5
-rw-r--r--src/mongo/db/fts/fts_command_mongos.cpp3
-rw-r--r--src/mongo/db/geo/haystack.cpp2
-rw-r--r--src/mongo/db/index_builder.cpp5
-rw-r--r--src/mongo/db/index_rebuilder.cpp9
-rw-r--r--src/mongo/db/instance.cpp46
-rw-r--r--src/mongo/db/instance.h2
-rw-r--r--src/mongo/db/introspect.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_cursor.cpp4
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp2
-rw-r--r--src/mongo/db/prefetch.cpp15
-rw-r--r--src/mongo/db/prefetch.h9
-rw-r--r--src/mongo/db/query/new_find.cpp4
-rw-r--r--src/mongo/db/range_deleter.cpp15
-rw-r--r--src/mongo/db/range_deleter.h4
-rw-r--r--src/mongo/db/range_deleter_db_env.cpp5
-rw-r--r--src/mongo/db/range_deleter_db_env.h4
-rw-r--r--src/mongo/db/range_deleter_mock_env.cpp3
-rw-r--r--src/mongo/db/range_deleter_mock_env.h2
-rw-r--r--src/mongo/db/repair_database.cpp2
-rw-r--r--src/mongo/db/repl/heartbeat.cpp2
-rw-r--r--src/mongo/db/repl/master_slave.cpp17
-rw-r--r--src/mongo/db/repl/oplog.cpp6
-rw-r--r--src/mongo/db/repl/repl_set_impl.cpp19
-rw-r--r--src/mongo/db/repl/repl_settings.cpp11
-rw-r--r--src/mongo/db/repl/rs.cpp2
-rw-r--r--src/mongo/db/repl/rs_config.cpp4
-rw-r--r--src/mongo/db/repl/rs_initialsync.cpp12
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp3
-rw-r--r--src/mongo/db/repl/sync_source_feedback.cpp3
-rw-r--r--src/mongo/db/repl/sync_tail.cpp13
-rw-r--r--src/mongo/db/restapi.cpp4
-rw-r--r--src/mongo/db/restapi.h2
-rw-r--r--src/mongo/db/server_parameters.h5
-rw-r--r--src/mongo/db/server_parameters_test.cpp6
-rw-r--r--src/mongo/db/ttl.cpp8
-rw-r--r--src/mongo/dbtests/clienttests.cpp13
-rw-r--r--src/mongo/dbtests/counttests.cpp7
-rw-r--r--src/mongo/dbtests/dbhelper_tests.cpp24
-rw-r--r--src/mongo/dbtests/documentsourcetests.cpp2
-rw-r--r--src/mongo/dbtests/indexcatalogtests.cpp9
-rw-r--r--src/mongo/dbtests/indexupdatetests.cpp5
-rw-r--r--src/mongo/dbtests/matchertests.cpp5
-rw-r--r--src/mongo/dbtests/pdfiletests.cpp3
-rw-r--r--src/mongo/dbtests/plan_ranking.cpp17
-rw-r--r--src/mongo/dbtests/query_multi_plan_runner.cpp4
-rw-r--r--src/mongo/dbtests/query_single_solution_runner.cpp32
-rw-r--r--src/mongo/dbtests/query_stage_and.cpp71
-rw-r--r--src/mongo/dbtests/query_stage_collscan.cpp20
-rw-r--r--src/mongo/dbtests/query_stage_count.cpp37
-rw-r--r--src/mongo/dbtests/query_stage_distinct.cpp19
-rw-r--r--src/mongo/dbtests/query_stage_fetch.cpp6
-rw-r--r--src/mongo/dbtests/query_stage_keep.cpp3
-rw-r--r--src/mongo/dbtests/query_stage_merge_sort.cpp38
-rw-r--r--src/mongo/dbtests/query_stage_sort.cpp18
-rw-r--r--src/mongo/dbtests/query_stage_tests.cpp20
-rw-r--r--src/mongo/dbtests/querytests.cpp70
-rw-r--r--src/mongo/dbtests/replsettests.cpp15
-rw-r--r--src/mongo/dbtests/runner_registry.cpp6
-rw-r--r--src/mongo/dbtests/threadedtests.cpp55
-rw-r--r--src/mongo/dbtests/updatetests.cpp26
-rw-r--r--src/mongo/s/commands/auth_schema_upgrade_s.cpp2
-rw-r--r--src/mongo/s/commands/cluster_index_filter_cmd.cpp10
-rw-r--r--src/mongo/s/commands/cluster_merge_chunks_cmd.cpp4
-rw-r--r--src/mongo/s/commands/cluster_plan_cache_cmd.cpp9
-rw-r--r--src/mongo/s/commands/cluster_write_cmd.cpp6
-rw-r--r--src/mongo/s/commands_admin.cpp27
-rw-r--r--src/mongo/s/commands_public.cpp32
-rw-r--r--src/mongo/s/cursors.cpp7
-rw-r--r--src/mongo/s/d_merge.cpp4
-rw-r--r--src/mongo/s/d_migrate.cpp55
-rw-r--r--src/mongo/s/d_split.cpp16
-rw-r--r--src/mongo/s/d_state.cpp11
-rw-r--r--src/mongo/s/request.cpp5
-rw-r--r--src/mongo/s/request.h4
-rw-r--r--src/mongo/s/s_only.cpp2
-rw-r--r--src/mongo/s/strategy.cpp15
-rw-r--r--src/mongo/tools/dump.cpp11
-rw-r--r--src/mongo/util/admin_access.h6
169 files changed, 1446 insertions, 1036 deletions
diff --git a/src/mongo/db/auth/auth_index_d.cpp b/src/mongo/db/auth/auth_index_d.cpp
index 2b510698b60..b8ed201226e 100644
--- a/src/mongo/db/auth/auth_index_d.cpp
+++ b/src/mongo/db/auth/auth_index_d.cpp
@@ -72,9 +72,10 @@ namespace {
} // namespace
- void configureSystemIndexes(const StringData& dbname) {
+ void configureSystemIndexes(OperationContext* txn, const StringData& dbname) {
int authzVersion;
- Status status = getGlobalAuthorizationManager()->getAuthorizationVersion(&authzVersion);
+ Status status = getGlobalAuthorizationManager()->getAuthorizationVersion(
+ txn, &authzVersion);
if (!status.isOK()) {
return;
}
@@ -83,8 +84,8 @@ namespace {
NamespaceString systemUsers(dbname, "system.users");
// Make sure the old unique index from v2.4 on system.users doesn't exist.
- Client::WriteContext wctx(systemUsers);
OperationContextImpl txn;
+ Client::WriteContext wctx(&txn, systemUsers);
Collection* collection = wctx.ctx().db()->getCollection(NamespaceString(systemUsers));
if (!collection) {
return;
diff --git a/src/mongo/db/auth/auth_index_d.h b/src/mongo/db/auth/auth_index_d.h
index 3d3cf711e40..964eec9fbb0 100644
--- a/src/mongo/db/auth/auth_index_d.h
+++ b/src/mongo/db/auth/auth_index_d.h
@@ -50,7 +50,7 @@ namespace authindex {
* It is appropriate to call this function on new or existing databases, though it is
* primarily intended for use on existing databases.
*/
- void configureSystemIndexes(const StringData& dbname);
+ void configureSystemIndexes(OperationContext* txn, const StringData& dbname);
} // namespace authindex
} // namespace mongo
diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp
index 3f6e3f620b5..d7960d784ae 100644
--- a/src/mongo/db/auth/authorization_manager.cpp
+++ b/src/mongo/db/auth/authorization_manager.cpp
@@ -258,14 +258,14 @@ namespace mongo {
}
}
- Status AuthorizationManager::getAuthorizationVersion(int* version) {
+ Status AuthorizationManager::getAuthorizationVersion(OperationContext* txn, int* version) {
CacheGuard guard(this, CacheGuard::fetchSynchronizationManual);
int newVersion = _version;
if (schemaVersionInvalid == newVersion) {
while (guard.otherUpdateInFetchPhase())
guard.wait();
guard.beginFetchPhase();
- Status status = _externalState->getStoredAuthorizationVersion(&newVersion);
+ Status status = _externalState->getStoredAuthorizationVersion(txn, &newVersion);
guard.endFetchPhase();
if (!status.isOK()) {
warning() << "Problem fetching the stored schema version of authorization data: "
@@ -295,8 +295,8 @@ namespace mongo {
return _authEnabled;
}
- bool AuthorizationManager::hasAnyPrivilegeDocuments() const {
- return _externalState->hasAnyPrivilegeDocuments();
+ bool AuthorizationManager::hasAnyPrivilegeDocuments(OperationContext* txn) const {
+ return _externalState->hasAnyPrivilegeDocuments(txn);
}
Status AuthorizationManager::writeAuthSchemaVersionIfNeeded() {
@@ -528,8 +528,10 @@ namespace mongo {
return Status::OK();
}
- Status AuthorizationManager::getUserDescription(const UserName& userName, BSONObj* result) {
- return _externalState->getUserDescription(userName, result);
+ Status AuthorizationManager::getUserDescription(OperationContext* txn,
+ const UserName& userName,
+ BSONObj* result) {
+ return _externalState->getUserDescription(txn, userName, result);
}
Status AuthorizationManager::getRoleDescription(const RoleName& roleName,
@@ -548,7 +550,8 @@ namespace mongo {
result);
}
- Status AuthorizationManager::acquireUser(const UserName& userName, User** acquiredUser) {
+ Status AuthorizationManager::acquireUser(
+ OperationContext* txn, const UserName& userName, User** acquiredUser) {
if (userName == internalSecurity.user->getName()) {
*acquiredUser = internalSecurity.user;
return Status::OK();
@@ -584,7 +587,7 @@ namespace mongo {
Status status = Status::OK();
for (int i = 0; i < maxAcquireRetries; ++i) {
if (authzVersion == schemaVersionInvalid) {
- Status status = _externalState->getStoredAuthorizationVersion(&authzVersion);
+ Status status = _externalState->getStoredAuthorizationVersion(txn, &authzVersion);
if (!status.isOK())
return status;
}
@@ -597,10 +600,10 @@ namespace mongo {
break;
case schemaVersion26Final:
case schemaVersion26Upgrade:
- status = _fetchUserV2(userName, &user);
+ status = _fetchUserV2(txn, userName, &user);
break;
case schemaVersion24:
- status = _fetchUserV1(userName, &user);
+ status = _fetchUserV1(txn, userName, &user);
break;
}
if (status.isOK())
@@ -633,10 +636,11 @@ namespace mongo {
return Status::OK();
}
- Status AuthorizationManager::_fetchUserV2(const UserName& userName,
+ Status AuthorizationManager::_fetchUserV2(OperationContext* txn,
+ const UserName& userName,
std::auto_ptr<User>* acquiredUser) {
BSONObj userObj;
- Status status = getUserDescription(userName, &userObj);
+ Status status = getUserDescription(txn, userName, &userObj);
if (!status.isOK()) {
return status;
}
@@ -653,7 +657,8 @@ namespace mongo {
return Status::OK();
}
- Status AuthorizationManager::_fetchUserV1(const UserName& userName,
+ Status AuthorizationManager::_fetchUserV1(OperationContext* txn,
+ const UserName& userName,
std::auto_ptr<User>* acquiredUser) {
BSONObj privDoc;
@@ -673,7 +678,7 @@ namespace mongo {
// Users from databases other than "$external" must have an associated privilege
// document in their database.
Status status = _externalState->getPrivilegeDocumentV1(
- userName.getDB(), userName, &privDoc);
+ txn, userName.getDB(), userName, &privDoc);
if (!status.isOK())
return status;
@@ -691,7 +696,7 @@ namespace mongo {
// Users from databases other than "admin" probe the "admin" database at login, to
// ensure that the acquire any privileges derived from "otherDBRoles" fields in
// admin.system.users.
- Status status = _externalState->getPrivilegeDocumentV1("admin", userName, &privDoc);
+ Status status = _externalState->getPrivilegeDocumentV1(txn, "admin", userName, &privDoc);
if (status.isOK()) {
status = parser.initializeUserRolesFromUserDocument(user.get(), privDoc, "admin");
if (!status.isOK())
@@ -709,7 +714,7 @@ namespace mongo {
}
Status AuthorizationManager::acquireV1UserProbedForDb(
- const UserName& userName, const StringData& dbname, User** acquiredUser) {
+ OperationContext* txn, const UserName& userName, const StringData& dbname, User** acquiredUser) {
if (userName == internalSecurity.user->getName()) {
*acquiredUser = internalSecurity.user;
@@ -750,12 +755,12 @@ namespace mongo {
guard.beginFetchPhase();
if (!user.get()) {
- Status status = _fetchUserV1(userName, &user);
+ Status status = _fetchUserV1(txn, userName, &user);
if (status == ErrorCodes::AuthSchemaIncompatible) {
// Must early-return from this if block, because we end the fetch phase. Since the
// auth schema is incompatible with schemaVersion24, make a best effort to do the
// schemaVersion26(Upgrade|Final) user acquisition, and return.
- status = _fetchUserV2(userName, &user);
+ status = _fetchUserV2(txn, userName, &user);
guard.endFetchPhase();
if (status.isOK()) {
// Not safe to throw from here until the function returns.
@@ -777,7 +782,7 @@ namespace mongo {
if (!user->hasProbedV1(dbname)) {
BSONObj privDoc;
- Status status = _externalState->getPrivilegeDocumentV1(dbname, userName, &privDoc);
+ Status status = _externalState->getPrivilegeDocumentV1(txn, dbname, userName, &privDoc);
if (status.isOK()) {
V1UserDocumentParser parser;
status = parser.initializeUserRolesFromUserDocument(user.get(), privDoc, dbname);
@@ -1290,9 +1295,10 @@ namespace {
}
} // namespace
- Status AuthorizationManager::upgradeSchemaStep(const BSONObj& writeConcern, bool* isDone) {
+ Status AuthorizationManager::upgradeSchemaStep(
+ OperationContext* txn, const BSONObj& writeConcern, bool* isDone) {
int authzVersion;
- Status status = getAuthorizationVersion(&authzVersion);
+ Status status = getAuthorizationVersion(txn, &authzVersion);
if (!status.isOK()) {
return status;
}
@@ -1316,7 +1322,8 @@ namespace {
}
}
- Status AuthorizationManager::upgradeSchema(int maxSteps, const BSONObj& writeConcern) {
+ Status AuthorizationManager::upgradeSchema(
+ OperationContext* txn, int maxSteps, const BSONObj& writeConcern) {
if (maxSteps < 1) {
return Status(ErrorCodes::BadValue,
@@ -1325,7 +1332,7 @@ namespace {
invalidateUserCache();
for (int i = 0; i < maxSteps; ++i) {
bool isDone;
- Status status = upgradeSchemaStep(writeConcern, &isDone);
+ Status status = upgradeSchemaStep(txn, writeConcern, &isDone);
invalidateUserCache();
if (!status.isOK() || isDone) {
return status;
diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h
index b3a17c491c5..d6a40b3d838 100644
--- a/src/mongo/db/auth/authorization_manager.h
+++ b/src/mongo/db/auth/authorization_manager.h
@@ -53,6 +53,7 @@ namespace mongo {
class AuthzManagerExternalState;
class UserDocumentParser;
+ class OperationContext;
/**
* Internal secret key info.
@@ -164,7 +165,7 @@ namespace mongo {
* returns a non-OK status. When returning a non-OK status, *version will be set to
* schemaVersionInvalid (0).
*/
- Status getAuthorizationVersion(int* version);
+ Status getAuthorizationVersion(OperationContext* txn, int* version);
/**
* Returns the user cache generation identifier.
@@ -172,7 +173,7 @@ namespace mongo {
OID getCacheGeneration();
// Returns true if there exists at least one privilege document in the system.
- bool hasAnyPrivilegeDocuments() const;
+ bool hasAnyPrivilegeDocuments(OperationContext* txn) const;
/**
* Updates the auth schema version document to reflect that the system is upgraded to
@@ -281,7 +282,7 @@ namespace mongo {
*
* If the user does not exist, returns ErrorCodes::UserNotFound.
*/
- Status getUserDescription(const UserName& userName, BSONObj* result);
+ Status getUserDescription(OperationContext* txn, const UserName& userName, BSONObj* result);
/**
* Writes into "result" a document describing the named role and returns Status::OK(). The
@@ -324,7 +325,7 @@ namespace mongo {
* The AuthorizationManager retains ownership of the returned User object.
* On non-OK Status return values, acquiredUser will not be modified.
*/
- Status acquireUser(const UserName& userName, User** acquiredUser);
+ Status acquireUser(OperationContext* txn, const UserName& userName, User** acquiredUser);
/**
* Decrements the refcount of the given User object. If the refcount has gone to zero,
@@ -339,8 +340,9 @@ namespace mongo {
*
* Bumps the returned **acquiredUser's reference count on success.
*/
- Status acquireV1UserProbedForDb(
- const UserName& userName, const StringData& dbname, User** acquiredUser);
+ Status acquireV1UserProbedForDb(OperationContext* txn,
+ const UserName& userName,
+ const StringData& dbname, User** acquiredUser);
/**
* Marks the given user as invalid and removes it from the user cache.
@@ -399,7 +401,8 @@ namespace mongo {
* On failure, returns a status other than Status::OK(). In this case, is is typically safe
* to try again.
*/
- Status upgradeSchemaStep(const BSONObj& writeConcern, bool* isDone);
+ Status upgradeSchemaStep(
+ OperationContext* txn, const BSONObj& writeConcern, bool* isDone);
/**
* Performs up to maxSteps steps in the process of upgrading the stored authorization data
@@ -414,7 +417,7 @@ namespace mongo {
* progress performing the upgrade, and the specific code and message in the returned status
* may provide additional information.
*/
- Status upgradeSchema(int maxSteps, const BSONObj& writeConcern);
+ Status upgradeSchema(OperationContext* txn, int maxSteps, const BSONObj& writeConcern);
/**
* Hook called by replication code to let the AuthorizationManager observe changes
@@ -458,14 +461,18 @@ namespace mongo {
* Fetches user information from a v2-schema user document for the named user,
* and stores a pointer to a new user object into *acquiredUser on success.
*/
- Status _fetchUserV2(const UserName& userName, std::auto_ptr<User>* acquiredUser);
+ Status _fetchUserV2(OperationContext* txn,
+ const UserName& userName,
+ std::auto_ptr<User>* acquiredUser);
/**
* Fetches user information from a v1-schema user document for the named user, possibly
* examining system.users collections from userName.getDB() and admin.system.users in the
* process. Stores a pointer to a new user object into *acquiredUser on success.
*/
- Status _fetchUserV1(const UserName& userName, std::auto_ptr<User>* acquiredUser);
+ Status _fetchUserV1(OperationContext* txn,
+ const UserName& userName,
+ std::auto_ptr<User>* acquiredUser);
/**
* True if access control enforcement is enabled in this AuthorizationManager.
diff --git a/src/mongo/db/auth/authorization_manager_global.cpp b/src/mongo/db/auth/authorization_manager_global.cpp
index 68e5cd1e7cb..92c140c4518 100644
--- a/src/mongo/db/auth/authorization_manager_global.cpp
+++ b/src/mongo/db/auth/authorization_manager_global.cpp
@@ -33,6 +33,7 @@
#include "mongo/client/auth_helpers.h"
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_manager_global.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/server_parameters.h"
#include "mongo/util/assert_util.h"
@@ -44,7 +45,7 @@ namespace {
MONGO_DISALLOW_COPYING(AuthzVersionParameter);
public:
AuthzVersionParameter(ServerParameterSet* sps, const std::string& name);
- virtual void append(BSONObjBuilder& b, const std::string& name);
+ virtual void append(OperationContext* txn, BSONObjBuilder& b, const std::string& name);
virtual Status set(const BSONElement& newValueElement);
virtual Status setFromString(const std::string& str);
};
@@ -60,9 +61,11 @@ namespace {
AuthzVersionParameter::AuthzVersionParameter(ServerParameterSet* sps, const std::string& name) :
ServerParameter(sps, name, false, false) {}
- void AuthzVersionParameter::append(BSONObjBuilder& b, const std::string& name) {
+ void AuthzVersionParameter::append(
+ OperationContext* txn, BSONObjBuilder& b, const std::string& name) {
int authzVersion;
- uassertStatusOK(getGlobalAuthorizationManager()->getAuthorizationVersion(&authzVersion));
+ uassertStatusOK(
+ getGlobalAuthorizationManager()->getAuthorizationVersion(txn, &authzVersion));
b.append(name, authzVersion);
}
diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp
index 458a212ccb5..2686a82cc41 100644
--- a/src/mongo/db/auth/authorization_manager_test.cpp
+++ b/src/mongo/db/auth/authorization_manager_test.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/map_util.h"
@@ -164,6 +165,8 @@ namespace {
scoped_ptr<AuthorizationManager> authzManager;
AuthzManagerExternalStateMock* externalState;
+
+ OperationContextNoop _txn;
};
TEST_F(AuthorizationManagerTest, testAcquireV0User) {
@@ -183,7 +186,7 @@ namespace {
ASSERT_OK(authzManager->initialize());
User* v0RW;
- ASSERT_OK(authzManager->acquireUser(UserName("v0RW", "test"), &v0RW));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("v0RW", "test"), &v0RW));
ASSERT_EQUALS(UserName("v0RW", "test"), v0RW->getName());
ASSERT(v0RW->isValid());
ASSERT_EQUALS(1U, v0RW->getRefCount());
@@ -194,7 +197,7 @@ namespace {
authzManager->releaseUser(v0RW);
User* v0AdminRO;
- ASSERT_OK(authzManager->acquireUser(UserName("v0AdminRO", "admin"), &v0AdminRO));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("v0AdminRO", "admin"), &v0AdminRO));
ASSERT(UserName("v0AdminRO", "admin") == v0AdminRO->getName());
ASSERT(v0AdminRO->isValid());
ASSERT_EQUALS((uint32_t)1, v0AdminRO->getRefCount());
@@ -222,7 +225,7 @@ namespace {
BSONObj()));
User* v1read;
- ASSERT_OK(authzManager->acquireUser(UserName("v1read", "test"), &v1read));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("v1read", "test"), &v1read));
ASSERT_EQUALS(UserName("v1read", "test"), v1read->getName());
ASSERT(v1read->isValid());
ASSERT_EQUALS((uint32_t)1, v1read->getRefCount());
@@ -234,7 +237,7 @@ namespace {
authzManager->releaseUser(v1read);
User* v1cluster;
- ASSERT_OK(authzManager->acquireUser(UserName("v1cluster", "admin"), &v1cluster));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("v1cluster", "admin"), &v1cluster));
ASSERT_EQUALS(UserName("v1cluster", "admin"), v1cluster->getName());
ASSERT(v1cluster->isValid());
ASSERT_EQUALS((uint32_t)1, v1cluster->getRefCount());
@@ -277,7 +280,7 @@ namespace {
ASSERT_OK(status);
User* readOnly;
- ASSERT_OK(authzManager->acquireUser(UserName("readOnly", "test"), &readOnly));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("readOnly", "test"), &readOnly));
ASSERT_EQUALS(UserName("readOnly", "test"), readOnly->getName());
ASSERT(readOnly->isValid());
ASSERT_EQUALS(1U, readOnly->getRefCount());
@@ -288,7 +291,7 @@ namespace {
authzManager->releaseUser(readOnly);
User* clusterAdmin;
- ASSERT_OK(authzManager->acquireUser(UserName("clusterAdmin", "$external"), &clusterAdmin));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("clusterAdmin", "$external"), &clusterAdmin));
ASSERT_EQUALS(UserName("clusterAdmin", "$external"), clusterAdmin->getName());
ASSERT(clusterAdmin->isValid());
ASSERT_EQUALS(1U, clusterAdmin->getRefCount());
@@ -299,16 +302,17 @@ namespace {
authzManager->releaseUser(clusterAdmin);
User* multiDB;
- status = authzManager->acquireUser(UserName("readWriteMultiDB", "test2"), &multiDB);
+ status = authzManager->acquireUser(&_txn, UserName("readWriteMultiDB", "test2"), &multiDB);
ASSERT_NOT_OK(status);
ASSERT(status.code() == ErrorCodes::UserNotFound);
- ASSERT_OK(authzManager->acquireUser(UserName("readWriteMultiDB", "test"), &multiDB));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("readWriteMultiDB", "test"), &multiDB));
ASSERT_EQUALS(UserName("readWriteMultiDB", "test"), multiDB->getName());
ASSERT(multiDB->isValid());
ASSERT_EQUALS(1U, multiDB->getRefCount());
User* multiDBProbed;
ASSERT_OK(authzManager->acquireV1UserProbedForDb(
+ &_txn,
UserName("readWriteMultiDB", "test"),
"test2",
&multiDBProbed));
@@ -357,7 +361,7 @@ namespace {
BSONObj()));
User* v2read;
- ASSERT_OK(authzManager->acquireUser(UserName("v2read", "test"), &v2read));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("v2read", "test"), &v2read));
ASSERT_EQUALS(UserName("v2read", "test"), v2read->getName());
ASSERT(v2read->isValid());
ASSERT_EQUALS(1U, v2read->getRefCount());
@@ -368,7 +372,7 @@ namespace {
authzManager->releaseUser(v2read);
User* v2cluster;
- ASSERT_OK(authzManager->acquireUser(UserName("v2cluster", "admin"), &v2cluster));
+ ASSERT_OK(authzManager->acquireUser(&_txn, UserName("v2cluster", "admin"), &v2cluster));
ASSERT_EQUALS(UserName("v2cluster", "admin"), v2cluster->getName());
ASSERT(v2cluster->isValid());
ASSERT_EQUALS(1U, v2cluster->getRefCount());
@@ -459,7 +463,7 @@ namespace {
// Verify that the expected users are present.
ASSERT_EQUALS(3U, externalState->getCollectionContents(collectionName).size());
- ASSERT_OK(externalState->findOne(collectionName,
+ ASSERT_OK(externalState->findOne(&_txn, collectionName,
BSON("user" << "clusterAdmin" <<
"userSource" << "$external"),
&doc));
@@ -469,14 +473,14 @@ namespace {
ASSERT_EQUALS(1U, doc["roles"].Array().size());
ASSERT_EQUALS("clusterAdmin", doc["roles"].Array()[0].str());
- ASSERT_OK(externalState->findOne(collectionName,
+ ASSERT_OK(externalState->findOne(&_txn, collectionName,
BSON("user" << "otherdbroles" <<
"userSource" << "test"),
&doc));
ASSERT_TRUE(doc["pwd"].eoo());
ASSERT_EQUALS(0U, doc["roles"].Array().size());
- ASSERT_OK(externalState->findOne(collectionName,
+ ASSERT_OK(externalState->findOne(&_txn, collectionName,
BSON("user" << "mixedroles" <<
"userSource" << "test"),
&doc));
@@ -488,7 +492,7 @@ namespace {
BSONObj doc;
// Verify that the admin.system.version document reflects correct upgrade.
- ASSERT_OK(externalState->findOne(
+ ASSERT_OK(externalState->findOne(&_txn,
AuthorizationManager::versionCollectionNamespace,
BSON("_id" << "authSchema" <<
AuthorizationManager::schemaVersionFieldName <<
@@ -505,7 +509,7 @@ namespace {
AuthorizationManager::usersCollectionNamespace).size());
// "readOnly@test" user
- ASSERT_OK(externalState->findOne(AuthorizationManager::usersCollectionNamespace,
+ ASSERT_OK(externalState->findOne(&_txn, AuthorizationManager::usersCollectionNamespace,
BSON("user" << "readOnly" << "db" << "test"),
&doc));
ASSERT_EQUALS("readOnly", doc["user"].str());
@@ -514,7 +518,7 @@ namespace {
ASSERT_EQUALS(1U, doc["roles"].Array().size());
// "clusterAdmin@$external" user
- ASSERT_OK(externalState->findOne(
+ ASSERT_OK(externalState->findOne(&_txn,
AuthorizationManager::usersCollectionNamespace,
BSON("user" << "clusterAdmin" << "db" << "$external"),
&doc));
@@ -523,7 +527,7 @@ namespace {
ASSERT_EQUALS(1U, doc["roles"].Array().size());
// "readWriteMultiDB@test" user
- ASSERT_OK(externalState->findOne(
+ ASSERT_OK(externalState->findOne(&_txn,
AuthorizationManager::usersCollectionNamespace,
BSON("user" << "readWriteMultiDB" << "db" << "test"),
&doc));
@@ -533,7 +537,7 @@ namespace {
ASSERT_EQUALS(2U, doc["roles"].Array().size());
// "otherdbroles@test" user
- ASSERT_OK(externalState->findOne(
+ ASSERT_OK(externalState->findOne(&_txn,
AuthorizationManager::usersCollectionNamespace,
BSON("user" << "otherdbroles" << "db" << "test"),
&doc));
@@ -550,7 +554,7 @@ namespace {
ASSERT_EQUALS(1U, rolePairs.count(make_pair("readWrite", "test3")));
// "mixedroles@test" user
- ASSERT_OK(externalState->findOne(
+ ASSERT_OK(externalState->findOne(&_txn,
AuthorizationManager::usersCollectionNamespace,
BSON("user" << "mixedroles" << "db" << "test"),
&doc));
@@ -570,7 +574,7 @@ namespace {
}
void upgradeAuthCollections() {
- ASSERT_OK(authzManager->upgradeSchema(10, BSONObj()));
+ ASSERT_OK(authzManager->upgradeSchema(&_txn, 10, BSONObj()));
}
};
@@ -587,8 +591,8 @@ namespace {
externalState->setAuthzVersion(AuthorizationManager::schemaVersion24);
setUpV1UserData();
ASSERT_EQUALS(ErrorCodes::OperationIncomplete,
- authzManager->upgradeSchema(1, BSONObj()));
- ASSERT_OK(authzManager->upgradeSchema(1, BSONObj()));
+ authzManager->upgradeSchema(&_txn, 1, BSONObj()));
+ ASSERT_OK(authzManager->upgradeSchema(&_txn, 1, BSONObj()));
}
TEST_F(AuthzUpgradeTest, upgradeUserDataFromV1ToV2WithSysVerDoc) {
@@ -605,7 +609,7 @@ namespace {
setUpV1UserData();
externalState->setAuthzVersion(AuthorizationManager::schemaVersion26Final);
bool done;
- ASSERT_OK(authzManager->upgradeSchemaStep(BSONObj(), &done));
+ ASSERT_OK(authzManager->upgradeSchemaStep(&_txn, BSONObj(), &done));
ASSERT_TRUE(done);
validateV1AdminUserData(AuthorizationManager::usersCollectionNamespace);
int numRemoved;
diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp
index a934ee3aae6..fa0594b429f 100644
--- a/src/mongo/db/auth/authorization_session.cpp
+++ b/src/mongo/db/auth/authorization_session.cpp
@@ -67,14 +67,15 @@ namespace {
return _externalState->getAuthorizationManager();
}
- void AuthorizationSession::startRequest() {
- _externalState->startRequest();
- _refreshUserInfoAsNeeded();
+ void AuthorizationSession::startRequest(OperationContext* txn) {
+ _externalState->startRequest(txn);
+ _refreshUserInfoAsNeeded(txn);
}
- Status AuthorizationSession::addAndAuthorizeUser(const UserName& userName) {
+ Status AuthorizationSession::addAndAuthorizeUser(
+ OperationContext* txn, const UserName& userName) {
User* user;
- Status status = getAuthorizationManager().acquireUser(userName, &user);
+ Status status = getAuthorizationManager().acquireUser(txn, userName, &user);
if (!status.isOK()) {
return status;
}
@@ -160,29 +161,32 @@ namespace {
return defaultPrivileges;
}
- Status AuthorizationSession::checkAuthForQuery(const NamespaceString& ns,
+ Status AuthorizationSession::checkAuthForQuery(OperationContext* txn,
+ const NamespaceString& ns,
const BSONObj& query) {
if (MONGO_unlikely(ns.isCommand())) {
return Status(ErrorCodes::InternalError, mongoutils::str::stream() <<
"Checking query auth on command namespace " << ns.ns());
}
- if (!isAuthorizedForActionsOnNamespace(ns, ActionType::find)) {
+ if (!isAuthorizedForActionsOnNamespace(txn, ns, ActionType::find)) {
return Status(ErrorCodes::Unauthorized,
mongoutils::str::stream() << "not authorized for query on " << ns.ns());
}
return Status::OK();
}
- Status AuthorizationSession::checkAuthForGetMore(const NamespaceString& ns,
+ Status AuthorizationSession::checkAuthForGetMore(OperationContext* txn,
+ const NamespaceString& ns,
long long cursorID) {
- if (!isAuthorizedForActionsOnNamespace(ns, ActionType::find)) {
+ if (!isAuthorizedForActionsOnNamespace(txn, ns, ActionType::find)) {
return Status(ErrorCodes::Unauthorized,
mongoutils::str::stream() << "not authorized for getmore on " << ns.ns());
}
return Status::OK();
}
- Status AuthorizationSession::checkAuthForInsert(const NamespaceString& ns,
+ Status AuthorizationSession::checkAuthForInsert(OperationContext* txn,
+ const NamespaceString& ns,
const BSONObj& document) {
if (ns.coll() == StringData("system.indexes", StringData::LiteralTag())) {
BSONElement nsElement = document["ns"];
@@ -191,13 +195,13 @@ namespace {
"system.indexes documents without a string-typed \"ns\" field.");
}
NamespaceString indexNS(nsElement.str());
- if (!isAuthorizedForActionsOnNamespace(indexNS, ActionType::createIndex)) {
+ if (!isAuthorizedForActionsOnNamespace(txn, indexNS, ActionType::createIndex)) {
return Status(ErrorCodes::Unauthorized,
mongoutils::str::stream() << "not authorized to create index on " <<
indexNS.ns());
}
} else {
- if (!isAuthorizedForActionsOnNamespace(ns, ActionType::insert)) {
+ if (!isAuthorizedForActionsOnNamespace(txn, ns, ActionType::insert)) {
return Status(ErrorCodes::Unauthorized,
mongoutils::str::stream() << "not authorized for insert on " <<
ns.ns());
@@ -207,12 +211,13 @@ namespace {
return Status::OK();
}
- Status AuthorizationSession::checkAuthForUpdate(const NamespaceString& ns,
+ Status AuthorizationSession::checkAuthForUpdate(OperationContext* txn,
+ const NamespaceString& ns,
const BSONObj& query,
const BSONObj& update,
bool upsert) {
if (!upsert) {
- if (!isAuthorizedForActionsOnNamespace(ns, ActionType::update)) {
+ if (!isAuthorizedForActionsOnNamespace(txn, ns, ActionType::update)) {
return Status(ErrorCodes::Unauthorized,
mongoutils::str::stream() << "not authorized for update on " <<
ns.ns());
@@ -222,7 +227,7 @@ namespace {
ActionSet required;
required.addAction(ActionType::update);
required.addAction(ActionType::insert);
- if (!isAuthorizedForActionsOnNamespace(ns, required)) {
+ if (!isAuthorizedForActionsOnNamespace(txn, ns, required)) {
return Status(ErrorCodes::Unauthorized,
mongoutils::str::stream() << "not authorized for upsert on " <<
ns.ns());
@@ -231,19 +236,22 @@ namespace {
return Status::OK();
}
- Status AuthorizationSession::checkAuthForDelete(const NamespaceString& ns,
+ Status AuthorizationSession::checkAuthForDelete(OperationContext* txn,
+ const NamespaceString& ns,
const BSONObj& query) {
- if (!isAuthorizedForActionsOnNamespace(ns, ActionType::remove)) {
+ if (!isAuthorizedForActionsOnNamespace(txn, ns, ActionType::remove)) {
return Status(ErrorCodes::Unauthorized,
mongoutils::str::stream() << "not authorized to remove from " << ns.ns());
}
return Status::OK();
}
- Status AuthorizationSession::checkAuthorizedToGrantPrivilege(const Privilege& privilege) {
+ Status AuthorizationSession::checkAuthorizedToGrantPrivilege(
+ OperationContext* txn, const Privilege& privilege) {
const ResourcePattern& resource = privilege.getResourcePattern();
if (resource.isDatabasePattern() || resource.isExactNamespacePattern()) {
if (!isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(resource.databaseToMatch()),
ActionType::grantRole)) {
return Status(ErrorCodes::Unauthorized,
@@ -251,7 +259,9 @@ namespace {
<< resource.databaseToMatch() << "database");
}
} else if (!isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName("admin"), ActionType::grantRole)) {
+ txn,
+ ResourcePattern::forDatabaseName("admin"),
+ ActionType::grantRole)) {
return Status(ErrorCodes::Unauthorized,
"To grant privileges affecting multiple databases or the cluster,"
" must be authorized to grant roles from the admin database");
@@ -260,10 +270,12 @@ namespace {
}
- Status AuthorizationSession::checkAuthorizedToRevokePrivilege(const Privilege& privilege) {
+ Status AuthorizationSession::checkAuthorizedToRevokePrivilege(
+ OperationContext* txn, const Privilege& privilege) {
const ResourcePattern& resource = privilege.getResourcePattern();
if (resource.isDatabasePattern() || resource.isExactNamespacePattern()) {
if (!isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(resource.databaseToMatch()),
ActionType::revokeRole)) {
return Status(ErrorCodes::Unauthorized,
@@ -271,7 +283,9 @@ namespace {
<< resource.databaseToMatch() << "database");
}
} else if (!isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName("admin"), ActionType::revokeRole)) {
+ txn,
+ ResourcePattern::forDatabaseName("admin"),
+ ActionType::revokeRole)) {
return Status(ErrorCodes::Unauthorized,
"To revoke privileges affecting multiple databases or the cluster,"
" must be authorized to revoke roles from the admin database");
@@ -279,55 +293,62 @@ namespace {
return Status::OK();
}
- bool AuthorizationSession::isAuthorizedToGrantRole(const RoleName& role) {
+ bool AuthorizationSession::isAuthorizedToGrantRole(
+ OperationContext* txn, const RoleName& role) {
return isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(role.getDB()),
- ActionType::grantRole);
+ txn,
+ ResourcePattern::forDatabaseName(role.getDB()),
+ ActionType::grantRole);
}
- bool AuthorizationSession::isAuthorizedToRevokeRole(const RoleName& role) {
+ bool AuthorizationSession::isAuthorizedToRevokeRole(
+ OperationContext* txn, const RoleName& role) {
return isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(role.getDB()),
- ActionType::revokeRole);
+ txn,
+ ResourcePattern::forDatabaseName(role.getDB()),
+ ActionType::revokeRole);
}
- bool AuthorizationSession::isAuthorizedForPrivilege(const Privilege& privilege) {
+ bool AuthorizationSession::isAuthorizedForPrivilege(
+ OperationContext* txn, const Privilege& privilege) {
if (_externalState->shouldIgnoreAuthChecks())
return true;
- return _isAuthorizedForPrivilege(privilege);
+ return _isAuthorizedForPrivilege(txn, privilege);
}
- bool AuthorizationSession::isAuthorizedForPrivileges(const vector<Privilege>& privileges) {
+ bool AuthorizationSession::isAuthorizedForPrivileges(
+ OperationContext* txn, const vector<Privilege>& privileges) {
if (_externalState->shouldIgnoreAuthChecks())
return true;
for (size_t i = 0; i < privileges.size(); ++i) {
- if (!_isAuthorizedForPrivilege(privileges[i]))
+ if (!_isAuthorizedForPrivilege(txn, privileges[i]))
return false;
}
return true;
}
- bool AuthorizationSession::isAuthorizedForActionsOnResource(const ResourcePattern& resource,
- ActionType action) {
- return isAuthorizedForPrivilege(Privilege(resource, action));
+ bool AuthorizationSession::isAuthorizedForActionsOnResource(
+ OperationContext* txn, const ResourcePattern& resource, ActionType action) {
+ return isAuthorizedForPrivilege(txn, Privilege(resource, action));
}
- bool AuthorizationSession::isAuthorizedForActionsOnResource(const ResourcePattern& resource,
- const ActionSet& actions) {
- return isAuthorizedForPrivilege(Privilege(resource, actions));
+ bool AuthorizationSession::isAuthorizedForActionsOnResource(
+ OperationContext* txn, const ResourcePattern& resource, const ActionSet& actions) {
+ return isAuthorizedForPrivilege(txn, Privilege(resource, actions));
}
- bool AuthorizationSession::isAuthorizedForActionsOnNamespace(const NamespaceString& ns,
- ActionType action) {
- return isAuthorizedForPrivilege(Privilege(ResourcePattern::forExactNamespace(ns), action));
+ bool AuthorizationSession::isAuthorizedForActionsOnNamespace(
+ OperationContext* txn, const NamespaceString& ns, ActionType action) {
+ return isAuthorizedForPrivilege(txn, Privilege(ResourcePattern::forExactNamespace(ns), action));
}
- bool AuthorizationSession::isAuthorizedForActionsOnNamespace(const NamespaceString& ns,
- const ActionSet& actions) {
- return isAuthorizedForPrivilege(Privilege(ResourcePattern::forExactNamespace(ns), actions));
+ bool AuthorizationSession::isAuthorizedForActionsOnNamespace(
+ OperationContext* txn, const NamespaceString& ns, const ActionSet& actions) {
+ return isAuthorizedForPrivilege(
+ txn, Privilege(ResourcePattern::forExactNamespace(ns), actions));
}
static const int resourceSearchListCapacity = 5;
@@ -422,7 +443,7 @@ namespace {
return false;
}
- void AuthorizationSession::_refreshUserInfoAsNeeded() {
+ void AuthorizationSession::_refreshUserInfoAsNeeded(OperationContext* txn) {
AuthorizationManager& authMan = getAuthorizationManager();
UserSet::iterator it = _authenticatedUsers.begin();
while (it != _authenticatedUsers.end()) {
@@ -434,7 +455,7 @@ namespace {
UserName name = user->getName();
User* updatedUser;
- Status status = authMan.acquireUser(name, &updatedUser);
+ Status status = authMan.acquireUser(txn, name, &updatedUser);
switch (status.code()) {
case ErrorCodes::OK: {
// Success! Replace the old User object with the updated one.
@@ -463,7 +484,8 @@ namespace {
}
}
- bool AuthorizationSession::_isAuthorizedForPrivilege(const Privilege& privilege) {
+ bool AuthorizationSession::_isAuthorizedForPrivilege(
+ OperationContext* txn, const Privilege& privilege) {
const ResourcePattern& target(privilege.getResourcePattern());
ResourcePattern resourceSearchList[resourceSearchListCapacity];
@@ -498,6 +520,7 @@ namespace {
UserName name = user->getName();
User* updatedUser;
Status status = getAuthorizationManager().acquireV1UserProbedForDb(
+ txn,
name,
target.databaseToMatch(),
&updatedUser);
diff --git a/src/mongo/db/auth/authorization_session.h b/src/mongo/db/auth/authorization_session.h
index 1a12a0719e0..14232158266 100644
--- a/src/mongo/db/auth/authorization_session.h
+++ b/src/mongo/db/auth/authorization_session.h
@@ -71,13 +71,13 @@ namespace mongo {
// Should be called at the beginning of every new request. This performs the checks
// necessary to determine if localhost connections should be given full access.
// TODO: try to eliminate the need for this call.
- void startRequest();
+ void startRequest(OperationContext* txn);
/**
* Adds the User identified by "UserName" to the authorization session, acquiring privileges
* for it in the process.
*/
- Status addAndAuthorizeUser(const UserName& userName);
+ Status addAndAuthorizeUser(OperationContext* txn, const UserName& userName);
// Returns the authenticated user with the given name. Returns NULL
// if no such user is found.
@@ -109,15 +109,16 @@ namespace mongo {
// Checks if this connection has the privileges necessary to perform the given query on the
// given namespace.
- Status checkAuthForQuery(const NamespaceString& ns, const BSONObj& query);
+ Status checkAuthForQuery(OperationContext* txn, const NamespaceString& ns, const BSONObj& query);
// Checks if this connection has the privileges necessary to perform a getMore on the given
// cursor in the given namespace.
- Status checkAuthForGetMore(const NamespaceString& ns, long long cursorID);
+ Status checkAuthForGetMore(OperationContext* txn, const NamespaceString& ns, long long cursorID);
// Checks if this connection has the privileges necessary to perform the given update on the
// given namespace.
- Status checkAuthForUpdate(const NamespaceString& ns,
+ Status checkAuthForUpdate(OperationContext* txn,
+ const NamespaceString& ns,
const BSONObj& query,
const BSONObj& update,
bool upsert);
@@ -125,27 +126,29 @@ namespace mongo {
// Checks if this connection has the privileges necessary to insert the given document
// to the given namespace. Correctly interprets inserts to system.indexes and performs
// the proper auth checks for index building.
- Status checkAuthForInsert(const NamespaceString& ns, const BSONObj& document);
+ Status checkAuthForInsert(
+ OperationContext* txn, const NamespaceString& ns, const BSONObj& document);
// Checks if this connection has the privileges necessary to perform a delete on the given
// namespace.
- Status checkAuthForDelete(const NamespaceString& ns, const BSONObj& query);
+ Status checkAuthForDelete(
+ OperationContext* txn, const NamespaceString& ns, const BSONObj& query);
// Checks if this connection has the privileges necessary to grant the given privilege
// to a role.
- Status checkAuthorizedToGrantPrivilege(const Privilege& privilege);
+ Status checkAuthorizedToGrantPrivilege(OperationContext* txn, const Privilege& privilege);
// Checks if this connection has the privileges necessary to revoke the given privilege
// from a role.
- Status checkAuthorizedToRevokePrivilege(const Privilege& privilege);
+ Status checkAuthorizedToRevokePrivilege(OperationContext* txn, const Privilege& privilege);
// Utility function for isAuthorizedForActionsOnResource(
// ResourcePattern::forDatabaseName(role.getDB()), ActionType::grantAnyRole)
- bool isAuthorizedToGrantRole(const RoleName& role);
+ bool isAuthorizedToGrantRole(OperationContext* txn, const RoleName& role);
// Utility function for isAuthorizedForActionsOnResource(
// ResourcePattern::forDatabaseName(role.getDB()), ActionType::grantAnyRole)
- bool isAuthorizedToRevokeRole(const RoleName& role);
+ bool isAuthorizedToRevokeRole(OperationContext* txn, const RoleName& role);
// Returns true if the current session is authenticated as the given user and that user
// is allowed to change his/her own password
@@ -163,26 +166,31 @@ namespace mongo {
//
// Contains all the authorization logic including handling things like the localhost
// exception.
- bool isAuthorizedForPrivilege(const Privilege& privilege);
+ bool isAuthorizedForPrivilege(OperationContext* txn, const Privilege& privilege);
// Like isAuthorizedForPrivilege, above, except returns true if the session is authorized
// for all of the listed privileges.
- bool isAuthorizedForPrivileges(const std::vector<Privilege>& privileges);
+ bool isAuthorizedForPrivileges(
+ OperationContext* txn, const std::vector<Privilege>& privileges);
// Utility function for isAuthorizedForPrivilege(Privilege(resource, action)).
- bool isAuthorizedForActionsOnResource(const ResourcePattern& resource, ActionType action);
+ bool isAuthorizedForActionsOnResource(
+ OperationContext* txn, const ResourcePattern& resource, ActionType action);
// Utility function for isAuthorizedForPrivilege(Privilege(resource, actions)).
- bool isAuthorizedForActionsOnResource(const ResourcePattern& resource,
+ bool isAuthorizedForActionsOnResource(OperationContext* txn,
+ const ResourcePattern& resource,
const ActionSet& actions);
// Utility function for
// isAuthorizedForActionsOnResource(ResourcePattern::forExactNamespace(ns), action).
- bool isAuthorizedForActionsOnNamespace(const NamespaceString& ns, ActionType action);
+ bool isAuthorizedForActionsOnNamespace(
+ OperationContext* txn, const NamespaceString& ns, ActionType action);
// Utility function for
// isAuthorizedForActionsOnResource(ResourcePattern::forExactNamespace(ns), actions).
- bool isAuthorizedForActionsOnNamespace(const NamespaceString& ns, const ActionSet& actions);
+ bool isAuthorizedForActionsOnNamespace(
+ OperationContext* txn, const NamespaceString& ns, const ActionSet& actions);
// Replaces the vector of UserNames that a system user is impersonating with a new vector.
// The auditing system adds these to each audit record in the log.
@@ -203,12 +211,12 @@ namespace mongo {
// If any users authenticated on this session are marked as invalid this updates them with
// up-to-date information. May require a read lock on the "admin" db to read the user data.
- void _refreshUserInfoAsNeeded();
+ void _refreshUserInfoAsNeeded(OperationContext* txn);
// Checks if this connection is authorized for the given Privilege, ignoring whether or not
// we should even be doing authorization checks in general. Note: this may acquire a read
// lock on the admin database (to update out-of-date user privilege information).
- bool _isAuthorizedForPrivilege(const Privilege& privilege);
+ bool _isAuthorizedForPrivilege(OperationContext* txn, const Privilege& privilege);
scoped_ptr<AuthzSessionExternalState> _externalState;
diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp
index 078ba1cfe01..75874d76c92 100644
--- a/src/mongo/db/auth/authorization_session_test.cpp
+++ b/src/mongo/db/auth/authorization_session_test.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/map_util.h"
@@ -53,7 +54,8 @@ namespace {
void setFindsShouldFail(bool enable) { _findsShouldFail = enable; }
- virtual Status findOne(const NamespaceString& collectionName,
+ virtual Status findOne(OperationContext* txn,
+ const NamespaceString& collectionName,
const BSONObj& query,
BSONObj* result) {
if (_findsShouldFail &&
@@ -62,7 +64,7 @@ namespace {
return Status(ErrorCodes::UnknownError,
"findOne on admin.system.users set to fail in mock.");
}
- return AuthzManagerExternalStateMock::findOne(collectionName, query, result);
+ return AuthzManagerExternalStateMock::findOne(txn, collectionName, query, result);
}
private:
@@ -84,6 +86,9 @@ namespace {
authzSession.reset(new AuthorizationSession(sessionState));
authzManager->setAuthEnabled(true);
}
+
+ protected:
+ OperationContextNoop _txn;
};
const ResourcePattern testDBResource(ResourcePattern::forDatabaseName("test"));
@@ -119,17 +124,17 @@ namespace {
TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
// Check that disabling auth checks works
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
sessionState->setReturnValueForShouldIgnoreAuthChecks(true);
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
sessionState->setReturnValueForShouldIgnoreAuthChecks(false);
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
// Check that you can't authorize a user that doesn't exist.
ASSERT_EQUALS(ErrorCodes::UserNotFound,
- authzSession->addAndAuthorizeUser(UserName("spencer", "test")));
+ authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
// Add a user with readWrite and dbAdmin on the test DB
ASSERT_OK(managerState->insertPrivilegeDocument("admin",
@@ -141,14 +146,14 @@ namespace {
BSON("role" << "dbAdmin" <<
"db" << "test"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("spencer", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testDBResource, ActionType::dbStats));
+ &_txn, testDBResource, ActionType::dbStats));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
// Add an admin user with readWriteAnyDatabase
ASSERT_OK(managerState->insertPrivilegeDocument("admin",
@@ -158,36 +163,37 @@ namespace {
"roles" << BSON_ARRAY(BSON("role" << "readWriteAnyDatabase" <<
"db" << "admin"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("admin", "admin")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("admin", "admin")));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
+ &_txn,
ResourcePattern::forExactNamespace(
NamespaceString("anydb.somecollection")),
ActionType::insert));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherDBResource, ActionType::insert));
+ &_txn, otherDBResource, ActionType::insert));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::collMod));
+ &_txn, otherFooCollResource, ActionType::collMod));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
authzSession->logoutDatabase("test");
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::collMod));
+ &_txn, testFooCollResource, ActionType::collMod));
authzSession->logoutDatabase("admin");
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::collMod));
+ &_txn, testFooCollResource, ActionType::collMod));
}
TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
@@ -203,14 +209,14 @@ namespace {
BSON("role" << "readWrite" <<
"db" << "test"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("spencer", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testDBResource, ActionType::dbStats));
+ &_txn, testDBResource, ActionType::dbStats));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
}
TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
@@ -247,83 +253,83 @@ namespace {
"db" << "admin"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("rwany", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("rwany", "test")));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
+ &_txn, testUsersCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
+ &_txn, testUsersCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
+ &_txn, otherUsersCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
+ &_txn, otherUsersCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
+ &_txn, testIndexesCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
+ &_txn, testProfileCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
+ &_txn, otherIndexesCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
+ &_txn, otherProfileCollResource, ActionType::find));
// Logging in as useradminany@test implicitly logs out rwany@test.
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("useradminany", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("useradminany", "test")));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
+ &_txn, testUsersCollResource, ActionType::insert));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
+ &_txn, testUsersCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
+ &_txn, otherUsersCollResource, ActionType::insert));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
+ &_txn, otherUsersCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
+ &_txn, testIndexesCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
+ &_txn, testProfileCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
+ &_txn, otherIndexesCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
+ &_txn, otherProfileCollResource, ActionType::find));
// Logging in as rw@test implicitly logs out useradminany@test.
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("rw", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("rw", "test")));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
+ &_txn, testUsersCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
+ &_txn, testUsersCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
+ &_txn, otherUsersCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
+ &_txn, otherUsersCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
+ &_txn, testIndexesCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
+ &_txn, testProfileCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
+ &_txn, otherIndexesCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
+ &_txn, otherProfileCollResource, ActionType::find));
// Logging in as useradmin@test implicitly logs out rw@test.
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("useradmin", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("useradmin", "test")));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
+ &_txn, testUsersCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
+ &_txn, testUsersCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
+ &_txn, otherUsersCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
+ &_txn, otherUsersCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
+ &_txn, testIndexesCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
+ &_txn, testProfileCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
+ &_txn, otherIndexesCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
+ &_txn, otherProfileCollResource, ActionType::find));
}
TEST_F(AuthorizationSessionTest, InvalidateUser) {
@@ -335,12 +341,12 @@ namespace {
"roles" << BSON_ARRAY(BSON("role" << "readWrite" <<
"db" << "test"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("spencer", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
User* user = authzSession->lookupUser(UserName("spencer", "test"));
ASSERT(user->isValid());
@@ -362,11 +368,11 @@ namespace {
// Make sure that invalidating the user causes the session to reload its privileges.
authzManager->invalidateUserByName(user->getName());
- authzSession->startRequest(); // Refreshes cached data for invalid users
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
user = authzSession->lookupUser(UserName("spencer", "test"));
ASSERT(user->isValid());
@@ -379,11 +385,11 @@ namespace {
&ignored);
// Make sure that invalidating the user causes the session to reload its privileges.
authzManager->invalidateUserByName(user->getName());
- authzSession->startRequest(); // Refreshes cached data for invalid users
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->lookupUser(UserName("spencer", "test")));
}
@@ -396,12 +402,12 @@ namespace {
"roles" << BSON_ARRAY(BSON("role" << "readWrite" <<
"db" << "test"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("spencer", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
User* user = authzSession->lookupUser(UserName("spencer", "test"));
ASSERT(user->isValid());
@@ -426,20 +432,20 @@ namespace {
// document lookup to fail, the authz session should continue to use its known out-of-date
// privilege data.
authzManager->invalidateUserByName(user->getName());
- authzSession->startRequest(); // Refreshes cached data for invalid users
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
// Once we configure document lookup to succeed again, authorization checks should
// observe the new values.
managerState->setFindsShouldFail(false);
- authzSession->startRequest(); // Refreshes cached data for invalid users
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
}
@@ -465,92 +471,92 @@ namespace {
ASSERT_OK(authzManager->initialize());
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::collMod));
+ &_txn, testFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::find));
+ &_txn, otherFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::collMod));
+ &_txn, otherFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::find));
+ &_txn, thirdFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::insert));
+ &_txn, thirdFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::collMod));
+ &_txn, thirdFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::find));
+ &_txn, adminFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::insert));
+ &_txn, adminFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::collMod));
+ &_txn, adminFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::shutdown));
+ &_txn, ResourcePattern::forClusterResource(), ActionType::shutdown));
- ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("andy", "test")));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("andy", "test")));
User* user = authzSession->lookupUser(UserName("andy", "test"));
ASSERT(UserName("andy", "test") == user->getName());
ASSERT(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::collMod));
+ &_txn, testFooCollResource, ActionType::collMod));
ASSERT(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::find));
+ &_txn, otherFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::collMod));
+ &_txn, otherFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::find));
+ &_txn, thirdFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::insert));
+ &_txn, thirdFooCollResource, ActionType::insert));
ASSERT(authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::collMod));
+ &_txn, thirdFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::find));
+ &_txn, adminFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::insert));
+ &_txn, adminFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::collMod));
+ &_txn, adminFooCollResource, ActionType::collMod));
ASSERT(authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::shutdown));
+ &_txn, ResourcePattern::forClusterResource(), ActionType::shutdown));
authzSession->logoutDatabase("test");
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
+ &_txn, testFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+ &_txn, testFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::collMod));
+ &_txn, testFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::find));
+ &_txn, otherFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ &_txn, otherFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::collMod));
+ &_txn, otherFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::find));
+ &_txn, thirdFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::insert));
+ &_txn, thirdFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- thirdFooCollResource, ActionType::collMod));
+ &_txn, thirdFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::find));
+ &_txn, adminFooCollResource, ActionType::find));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::insert));
+ &_txn, adminFooCollResource, ActionType::insert));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- adminFooCollResource, ActionType::collMod));
+ &_txn, adminFooCollResource, ActionType::collMod));
ASSERT(!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::shutdown));
+ &_txn, ResourcePattern::forClusterResource(), ActionType::shutdown));
}
} // namespace
diff --git a/src/mongo/db/auth/authz_manager_external_state.cpp b/src/mongo/db/auth/authz_manager_external_state.cpp
index e5f63496799..25640191cec 100644
--- a/src/mongo/db/auth/authz_manager_external_state.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state.cpp
@@ -40,7 +40,8 @@ namespace mongo {
AuthzManagerExternalState::AuthzManagerExternalState() {}
AuthzManagerExternalState::~AuthzManagerExternalState() {}
- Status AuthzManagerExternalState::getPrivilegeDocumentV1(const StringData& dbname,
+ Status AuthzManagerExternalState::getPrivilegeDocumentV1(OperationContext* txn,
+ const StringData& dbname,
const UserName& userName,
BSONObj* result) {
if (userName == internalSecurity.user->getName()) {
@@ -69,7 +70,7 @@ namespace mongo {
// Query for the privilege document
BSONObj userBSONObj;
- Status found = findOne(usersNamespace, queryBuilder.done(), &userBSONObj);
+ Status found = findOne(txn, usersNamespace, queryBuilder.done(), &userBSONObj);
if (!found.isOK()) {
if (found.code() == ErrorCodes::NoMatchingDocument) {
// Return more detailed status that includes user name.
@@ -97,9 +98,10 @@ namespace mongo {
return Status::OK();
}
- bool AuthzManagerExternalState::hasAnyPrivilegeDocuments() {
+ bool AuthzManagerExternalState::hasAnyPrivilegeDocuments(OperationContext* txn) {
BSONObj userBSONObj;
Status status = findOne(
+ txn,
AuthorizationManager::usersCollectionNamespace,
BSONObj(),
&userBSONObj);
diff --git a/src/mongo/db/auth/authz_manager_external_state.h b/src/mongo/db/auth/authz_manager_external_state.h
index f637415ae91..7c97eb5ea38 100644
--- a/src/mongo/db/auth/authz_manager_external_state.h
+++ b/src/mongo/db/auth/authz_manager_external_state.h
@@ -41,6 +41,8 @@
namespace mongo {
+ class OperationContext;
+
/**
* Public interface for a class that encapsulates all the information related to system
* state not stored in AuthorizationManager. This is primarily to make AuthorizationManager
@@ -64,7 +66,7 @@ namespace mongo {
* Retrieves the schema version of the persistent data describing users and roles.
* Will leave *outVersion unmodified on non-OK status return values.
*/
- virtual Status getStoredAuthorizationVersion(int* outVersion) = 0;
+ virtual Status getStoredAuthorizationVersion(OperationContext* txn, int* outVersion) = 0;
/**
* Writes into "result" a document describing the named user and returns Status::OK(). The
@@ -76,7 +78,8 @@ namespace mongo {
*
* If the user does not exist, returns ErrorCodes::UserNotFound.
*/
- virtual Status getUserDescription(const UserName& userName, BSONObj* result) = 0;
+ virtual Status getUserDescription(
+ OperationContext* txn, const UserName& userName, BSONObj* result) = 0;
/**
* Writes into "result" a document describing the named role and returns Status::OK(). The
@@ -119,13 +122,15 @@ namespace mongo {
* On success, returns Status::OK() and stores a shared-ownership copy of the document into
* "result".
*/
- Status getPrivilegeDocumentV1(
- const StringData& dbname, const UserName& userName, BSONObj* result);
+ Status getPrivilegeDocumentV1(OperationContext* txn,
+ const StringData& dbname,
+ const UserName& userName,
+ BSONObj* result);
/**
* Returns true if there exists at least one privilege document in the system.
*/
- bool hasAnyPrivilegeDocuments();
+ bool hasAnyPrivilegeDocuments(OperationContext* txn);
/**
* Creates the given user object in the given database.
@@ -164,7 +169,8 @@ namespace mongo {
* Returns Status::OK() on success. If no match is found, returns
* ErrorCodes::NoMatchingDocument. Other errors returned as appropriate.
*/
- virtual Status findOne(const NamespaceString& collectionName,
+ virtual Status findOne(OperationContext* txn,
+ const NamespaceString& collectionName,
const BSONObj& query,
BSONObj* result) = 0;
diff --git a/src/mongo/db/auth/authz_manager_external_state_d.cpp b/src/mongo/db/auth/authz_manager_external_state_d.cpp
index 2c009314f48..852f6d96b71 100644
--- a/src/mongo/db/auth/authz_manager_external_state_d.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_d.cpp
@@ -47,12 +47,13 @@ namespace mongo {
AuthzManagerExternalStateMongod::AuthzManagerExternalStateMongod() {}
AuthzManagerExternalStateMongod::~AuthzManagerExternalStateMongod() {}
- Status AuthzManagerExternalStateMongod::_getUserDocument(const UserName& userName,
- BSONObj* userDoc) {
+ Status AuthzManagerExternalStateMongod::_getUserDocument(
+ OperationContext* txn, const UserName& userName, BSONObj* userDoc) {
+
+ Client::ReadContext ctx(txn, "admin");
- Client::ReadContext ctx("admin");
int authzVersion;
- Status status = getStoredAuthorizationVersion(&authzVersion);
+ Status status = getStoredAuthorizationVersion(txn, &authzVersion);
if (!status.isOK())
return status;
@@ -67,6 +68,7 @@ namespace mongo {
}
status = findOne(
+ txn,
(authzVersion == AuthorizationManager::schemaVersion26Final ?
AuthorizationManager::usersCollectionNamespace :
AuthorizationManager::usersAltCollectionNamespace),
@@ -102,11 +104,13 @@ namespace mongo {
}
Status AuthzManagerExternalStateMongod::findOne(
+ OperationContext* txn,
const NamespaceString& collectionName,
const BSONObj& query,
BSONObj* result) {
- Client::ReadContext ctx(collectionName.ns());
+ Client::ReadContext ctx(txn, collectionName.ns());
+
BSONObj found;
if (Helpers::findOne(ctx.ctx().db()->getCollection(collectionName),
query,
diff --git a/src/mongo/db/auth/authz_manager_external_state_d.h b/src/mongo/db/auth/authz_manager_external_state_d.h
index 380d4eb6bef..213fcc56152 100644
--- a/src/mongo/db/auth/authz_manager_external_state_d.h
+++ b/src/mongo/db/auth/authz_manager_external_state_d.h
@@ -52,7 +52,8 @@ namespace mongo {
virtual Status getAllDatabaseNames(std::vector<std::string>* dbnames);
- virtual Status findOne(const NamespaceString& collectionName,
+ virtual Status findOne(OperationContext* txn,
+ const NamespaceString& collectionName,
const BSONObj& query,
BSONObj* result);
virtual Status query(const NamespaceString& collectionName,
@@ -83,7 +84,8 @@ namespace mongo {
virtual void releaseAuthzUpdateLock();
private:
- virtual Status _getUserDocument(const UserName& userName, BSONObj* userDoc);
+ virtual Status _getUserDocument(
+ OperationContext* txn, const UserName& userName, BSONObj* userDoc);
boost::timed_mutex _authzDataUpdateLock;
};
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.cpp b/src/mongo/db/auth/authz_manager_external_state_local.cpp
index 099e5638020..926158bc740 100644
--- a/src/mongo/db/auth/authz_manager_external_state_local.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_local.cpp
@@ -59,9 +59,11 @@ namespace mongo {
return Status::OK();
}
- Status AuthzManagerExternalStateLocal::getStoredAuthorizationVersion(int* outVersion) {
+ Status AuthzManagerExternalStateLocal::getStoredAuthorizationVersion(
+ OperationContext* txn, int* outVersion) {
BSONObj versionDoc;
- Status status = findOne(AuthorizationManager::versionCollectionNamespace,
+ Status status = findOne(txn,
+ AuthorizationManager::versionCollectionNamespace,
AuthorizationManager::versionDocumentQuery,
&versionDoc);
if (status.isOK()) {
@@ -85,7 +87,7 @@ namespace mongo {
}
}
else if (status == ErrorCodes::NoMatchingDocument) {
- if (hasAnyPrivilegeDocuments()) {
+ if (hasAnyPrivilegeDocuments(txn)) {
*outVersion = AuthorizationManager::schemaVersion24;
}
else {
@@ -136,11 +138,12 @@ namespace {
} // namespace
Status AuthzManagerExternalStateLocal::getUserDescription(
+ OperationContext* txn,
const UserName& userName,
BSONObj* result) {
BSONObj userDoc;
- Status status = _getUserDocument(userName, &userDoc);
+ Status status = _getUserDocument(txn, userName, &userDoc);
if (!status.isOK())
return status;
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.h b/src/mongo/db/auth/authz_manager_external_state_local.h
index 2c49c4b7cc7..ba48862e277 100644
--- a/src/mongo/db/auth/authz_manager_external_state_local.h
+++ b/src/mongo/db/auth/authz_manager_external_state_local.h
@@ -53,8 +53,9 @@ namespace mongo {
virtual Status initialize();
- virtual Status getStoredAuthorizationVersion(int* outVersion);
- virtual Status getUserDescription(const UserName& userName, BSONObj* result);
+ virtual Status getStoredAuthorizationVersion(OperationContext* txn, int* outVersion);
+ virtual Status getUserDescription(
+ OperationContext* txn, const UserName& userName, BSONObj* result);
virtual Status getRoleDescription(const RoleName& roleName,
bool showPrivileges,
BSONObj* result);
@@ -88,7 +89,9 @@ namespace mongo {
/**
* Fetches the user document for "userName" from local storage, and stores it into "result".
*/
- virtual Status _getUserDocument(const UserName& userName, BSONObj* result) = 0;
+ virtual Status _getUserDocument(OperationContext* txn,
+ const UserName& userName,
+ BSONObj* result) = 0;
Status _getRoleDescription_inlock(const RoleName& roleName,
bool showPrivileges,
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.cpp b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
index 5ee19c863a5..809d4ecb747 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
@@ -97,10 +97,11 @@ namespace {
BSONObj()));
}
- Status AuthzManagerExternalStateMock::_getUserDocument(const UserName& userName,
+ Status AuthzManagerExternalStateMock::_getUserDocument(OperationContext* txn,
+ const UserName& userName,
BSONObj* userDoc) {
int authzVersion;
- Status status = getStoredAuthorizationVersion(&authzVersion);
+ Status status = getStoredAuthorizationVersion(txn, &authzVersion);
if (!status.isOK())
return status;
@@ -115,6 +116,7 @@ namespace {
}
status = findOne(
+ txn,
(authzVersion == AuthorizationManager::schemaVersion26Final ?
AuthorizationManager::usersCollectionNamespace :
AuthorizationManager::usersAltCollectionNamespace),
@@ -139,18 +141,8 @@ namespace {
return Status::OK();
}
- Status AuthzManagerExternalStateMock::_findUser(
- const std::string& usersNamespace,
- const BSONObj& query,
- BSONObj* result) {
- if (!findOne(NamespaceString(usersNamespace), query, result).isOK()) {
- return Status(ErrorCodes::UserNotFound,
- "No matching user for query " + query.toString());
- }
- return Status::OK();
- }
-
Status AuthzManagerExternalStateMock::findOne(
+ OperationContext* txn,
const NamespaceString& collectionName,
const BSONObj& query,
BSONObj* result) {
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.h b/src/mongo/db/auth/authz_manager_external_state_mock.h
index 6ec06f97692..06db6b77890 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.h
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.h
@@ -60,7 +60,8 @@ namespace mongo {
virtual Status getAllDatabaseNames(std::vector<std::string>* dbnames);
- virtual Status findOne(const NamespaceString& collectionName,
+ virtual Status findOne(OperationContext* txn,
+ const NamespaceString& collectionName,
const BSONObj& query,
BSONObj* result);
@@ -101,16 +102,14 @@ namespace mongo {
virtual bool tryAcquireAuthzUpdateLock(const StringData& why);
virtual void releaseAuthzUpdateLock();
- Status _findUser(const std::string& usersNamespace,
- const BSONObj& query,
- BSONObj* result);
std::vector<BSONObj> getCollectionContents(const NamespaceString& collectionName);
private:
typedef std::vector<BSONObj> BSONObjCollection;
typedef std::map<NamespaceString, BSONObjCollection> NamespaceDocumentMap;
- virtual Status _getUserDocument(const UserName& userName, BSONObj* userDoc);
+ virtual Status _getUserDocument(
+ OperationContext* txn, const UserName& userName, BSONObj* userDoc);
Status _findOneIter(const NamespaceString& collectionName,
const BSONObj& query,
diff --git a/src/mongo/db/auth/authz_manager_external_state_s.cpp b/src/mongo/db/auth/authz_manager_external_state_s.cpp
index 8f1dd6d1256..0cd3760258c 100644
--- a/src/mongo/db/auth/authz_manager_external_state_s.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_s.cpp
@@ -70,7 +70,8 @@ namespace mongo {
}
}
- Status AuthzManagerExternalStateMongos::getStoredAuthorizationVersion(int* outVersion) {
+ Status AuthzManagerExternalStateMongos::getStoredAuthorizationVersion(
+ OperationContext* txn, int* outVersion) {
scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(
AuthorizationManager::usersCollectionNamespace));
Status status = auth::getRemoteStoredAuthorizationVersion(conn->get(), outVersion);
@@ -78,8 +79,8 @@ namespace mongo {
return status;
}
- Status AuthzManagerExternalStateMongos::getUserDescription(const UserName& userName,
- BSONObj* result) {
+ Status AuthzManagerExternalStateMongos::getUserDescription(
+ OperationContext* txn, const UserName& userName, BSONObj* result) {
try {
scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(
AuthorizationManager::usersCollectionNamespace));
@@ -190,6 +191,7 @@ namespace mongo {
}
Status AuthzManagerExternalStateMongos::findOne(
+ OperationContext* txn,
const NamespaceString& collectionName,
const BSONObj& queryDoc,
BSONObj* result) {
diff --git a/src/mongo/db/auth/authz_manager_external_state_s.h b/src/mongo/db/auth/authz_manager_external_state_s.h
index 203ce25f5ac..c19e3ed056e 100644
--- a/src/mongo/db/auth/authz_manager_external_state_s.h
+++ b/src/mongo/db/auth/authz_manager_external_state_s.h
@@ -52,8 +52,9 @@ namespace mongo {
virtual ~AuthzManagerExternalStateMongos();
virtual Status initialize();
- virtual Status getStoredAuthorizationVersion(int* outVersion);
- virtual Status getUserDescription(const UserName& userName, BSONObj* result);
+ virtual Status getStoredAuthorizationVersion(OperationContext* txn, int* outVersion);
+ virtual Status getUserDescription(
+ OperationContext* txn, const UserName& userName, BSONObj* result);
virtual Status getRoleDescription(const RoleName& roleName,
bool showPrivileges,
BSONObj* result);
@@ -70,7 +71,8 @@ namespace mongo {
* NOTE: The data returned from this helper may be from any config server or replica set
* node. The first config server or primary node is preferred, when available.
*/
- virtual Status findOne(const NamespaceString& collectionName,
+ virtual Status findOne(OperationContext* txn,
+ const NamespaceString& collectionName,
const BSONObj& query,
BSONObj* result);
diff --git a/src/mongo/db/auth/authz_session_external_state.h b/src/mongo/db/auth/authz_session_external_state.h
index dbd838cb68f..2e1b41a0565 100644
--- a/src/mongo/db/auth/authz_session_external_state.h
+++ b/src/mongo/db/auth/authz_session_external_state.h
@@ -39,6 +39,7 @@
namespace mongo {
class Principal;
+ class OperationContext;
/**
* Public interface for a class that encapsulates all the session information related to system
@@ -68,7 +69,7 @@ namespace mongo {
// Should be called at the beginning of every new request. This performs the checks
// necessary to determine if localhost connections should be given full access.
- virtual void startRequest() = 0;
+ virtual void startRequest(OperationContext* txn) = 0;
protected:
// This class should never be instantiated directly.
diff --git a/src/mongo/db/auth/authz_session_external_state_d.cpp b/src/mongo/db/auth/authz_session_external_state_d.cpp
index 0156ccf6c9b..614b5e67505 100644
--- a/src/mongo/db/auth/authz_session_external_state_d.cpp
+++ b/src/mongo/db/auth/authz_session_external_state_d.cpp
@@ -45,9 +45,9 @@ namespace mongo {
AuthzSessionExternalStateServerCommon(authzManager) {}
AuthzSessionExternalStateMongod::~AuthzSessionExternalStateMongod() {}
- void AuthzSessionExternalStateMongod::startRequest() {
+ void AuthzSessionExternalStateMongod::startRequest(OperationContext* txn) {
if (!Lock::isLocked()) {
- _checkShouldAllowLocalhost();
+ _checkShouldAllowLocalhost(txn);
}
}
diff --git a/src/mongo/db/auth/authz_session_external_state_d.h b/src/mongo/db/auth/authz_session_external_state_d.h
index f5b2c82cd03..0df26d507c7 100644
--- a/src/mongo/db/auth/authz_session_external_state_d.h
+++ b/src/mongo/db/auth/authz_session_external_state_d.h
@@ -47,7 +47,7 @@ namespace mongo {
virtual bool shouldIgnoreAuthChecks() const;
- virtual void startRequest();
+ virtual void startRequest(OperationContext* txn);
};
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_session_external_state_mock.h b/src/mongo/db/auth/authz_session_external_state_mock.h
index c884654ac91..0acc98366ea 100644
--- a/src/mongo/db/auth/authz_session_external_state_mock.h
+++ b/src/mongo/db/auth/authz_session_external_state_mock.h
@@ -62,7 +62,7 @@ namespace mongo {
_allowLocalhostReturnValue = returnValue;
}
- virtual void startRequest() {}
+ virtual void startRequest(OperationContext* txn) {}
private:
bool _ignoreAuthChecksReturnValue;
diff --git a/src/mongo/db/auth/authz_session_external_state_s.cpp b/src/mongo/db/auth/authz_session_external_state_s.cpp
index 14801eae945..4009670c6c4 100644
--- a/src/mongo/db/auth/authz_session_external_state_s.cpp
+++ b/src/mongo/db/auth/authz_session_external_state_s.cpp
@@ -43,8 +43,8 @@ namespace mongo {
AuthzSessionExternalStateServerCommon(authzManager) {}
AuthzSessionExternalStateMongos::~AuthzSessionExternalStateMongos() {}
- void AuthzSessionExternalStateMongos::startRequest() {
- _checkShouldAllowLocalhost();
+ void AuthzSessionExternalStateMongos::startRequest(OperationContext* txn) {
+ _checkShouldAllowLocalhost(txn);
}
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_session_external_state_s.h b/src/mongo/db/auth/authz_session_external_state_s.h
index 6672957ced4..777082faadc 100644
--- a/src/mongo/db/auth/authz_session_external_state_s.h
+++ b/src/mongo/db/auth/authz_session_external_state_s.h
@@ -45,7 +45,7 @@ namespace mongo {
AuthzSessionExternalStateMongos(AuthorizationManager* authzManager);
virtual ~AuthzSessionExternalStateMongos();
- virtual void startRequest();
+ virtual void startRequest(OperationContext* txn);
};
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_session_external_state_server_common.cpp b/src/mongo/db/auth/authz_session_external_state_server_common.cpp
index b5c6f6a4bc3..debef7d3120 100644
--- a/src/mongo/db/auth/authz_session_external_state_server_common.cpp
+++ b/src/mongo/db/auth/authz_session_external_state_server_common.cpp
@@ -31,6 +31,7 @@
#include "mongo/base/status.h"
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/client.h"
+#include "mongo/db/operation_context.h"
#include "mongo/db/server_parameters.h"
#include "mongo/util/debug_util.h"
@@ -49,7 +50,7 @@ namespace {
_allowLocalhost(enableLocalhostAuthBypass) {}
AuthzSessionExternalStateServerCommon::~AuthzSessionExternalStateServerCommon() {}
- void AuthzSessionExternalStateServerCommon::_checkShouldAllowLocalhost() {
+ void AuthzSessionExternalStateServerCommon::_checkShouldAllowLocalhost(OperationContext* txn) {
if (!_authzManager->isAuthEnabled())
return;
// If we know that an admin user exists, don't re-check.
@@ -61,7 +62,7 @@ namespace {
return;
}
- _allowLocalhost = !_authzManager->hasAnyPrivilegeDocuments();
+ _allowLocalhost = !_authzManager->hasAnyPrivilegeDocuments(txn);
if (_allowLocalhost) {
ONCE {
log() << "note: no users configured in admin.system.users, allowing localhost "
diff --git a/src/mongo/db/auth/authz_session_external_state_server_common.h b/src/mongo/db/auth/authz_session_external_state_server_common.h
index f6e1a97f4a9..59599a6befd 100644
--- a/src/mongo/db/auth/authz_session_external_state_server_common.h
+++ b/src/mongo/db/auth/authz_session_external_state_server_common.h
@@ -53,7 +53,7 @@ namespace mongo {
// Checks whether or not localhost connections should be given full access and stores the
// result in _allowLocalhost. Currently localhost connections are only given full access
// if there are no users in the admin database.
- virtual void _checkShouldAllowLocalhost();
+ void _checkShouldAllowLocalhost(OperationContext* txn);
private:
diff --git a/src/mongo/db/catalog/collection_cursor_cache.cpp b/src/mongo/db/catalog/collection_cursor_cache.cpp
index 926baf7a137..d4727a17ee2 100644
--- a/src/mongo/db/catalog/collection_cursor_cache.cpp
+++ b/src/mongo/db/catalog/collection_cursor_cache.cpp
@@ -98,11 +98,11 @@ namespace mongo {
/**
* works globally
*/
- bool eraseCursor( CursorId id, bool checkAuth );
+ bool eraseCursor(OperationContext* txn, CursorId id, bool checkAuth);
void appendStats( BSONObjBuilder& builder );
- std::size_t timeoutCursors( int millisSinceLastCall );
+ std::size_t timeoutCursors(OperationContext* txn, int millisSinceLastCall);
int64_t nextSeed();
@@ -159,7 +159,7 @@ namespace mongo {
_idToNS.erase( id );
}
- bool GlobalCursorIdCache::eraseCursor(CursorId id, bool checkAuth) {
+ bool GlobalCursorIdCache::eraseCursor(OperationContext* txn, CursorId id, bool checkAuth) {
string ns;
{
SimpleMutex::scoped_lock lk( _mutex );
@@ -175,8 +175,8 @@ namespace mongo {
if ( checkAuth ) {
AuthorizationSession* as = cc().getAuthorizationSession();
- bool isAuthorized = as->isAuthorizedForActionsOnNamespace(nss,
- ActionType::killCursors);
+ bool isAuthorized = as->isAuthorizedForActionsOnNamespace(
+ txn, nss, ActionType::killCursors);
if ( !isAuthorized ) {
audit::logKillCursorsAuthzCheck( currentClient.get(),
nss,
@@ -186,8 +186,8 @@ namespace mongo {
}
}
- Lock::DBRead lock( ns );
- Database* db = dbHolder().get( ns, storageGlobalParams.dbpath );
+ Lock::DBRead lock(txn->lockState(), ns);
+ Database* db = dbHolder().get(ns, storageGlobalParams.dbpath);
if ( !db )
return false;
Client::Context context( ns, db );
@@ -204,7 +204,7 @@ namespace mongo {
return collection->cursorCache()->eraseCursor( id, checkAuth );
}
- std::size_t GlobalCursorIdCache::timeoutCursors( int millisSinceLastCall ) {
+ std::size_t GlobalCursorIdCache::timeoutCursors(OperationContext* txn, int millisSinceLastCall) {
vector<string> todo;
{
SimpleMutex::scoped_lock lk( _mutex );
@@ -216,7 +216,7 @@ namespace mongo {
for ( unsigned i = 0; i < todo.size(); i++ ) {
const string& ns = todo[i];
- Lock::DBRead lock( ns );
+ Lock::DBRead lock(txn->lockState(), ns);
Database* db = dbHolder().get( ns, storageGlobalParams.dbpath );
if ( !db )
continue;
@@ -235,25 +235,25 @@ namespace mongo {
// ---
- std::size_t CollectionCursorCache::timeoutCursorsGlobal( int millisSinceLastCall ) {
- return _globalCursorIdCache.timeoutCursors( millisSinceLastCall );
+ std::size_t CollectionCursorCache::timeoutCursorsGlobal(OperationContext* txn, int millisSinceLastCall) {;
+ return _globalCursorIdCache.timeoutCursors(txn, millisSinceLastCall);
}
- int CollectionCursorCache::eraseCursorGlobalIfAuthorized(int n, long long* ids) {
+ int CollectionCursorCache::eraseCursorGlobalIfAuthorized(OperationContext* txn, int n, long long* ids) {
int numDeleted = 0;
for ( int i = 0; i < n; i++ ) {
- if ( eraseCursorGlobalIfAuthorized( ids[i] ) )
+ if ( eraseCursorGlobalIfAuthorized(txn, ids[i] ) )
numDeleted++;
if ( inShutdown() )
break;
}
return numDeleted;
}
- bool CollectionCursorCache::eraseCursorGlobalIfAuthorized(CursorId id) {
- return _globalCursorIdCache.eraseCursor( id, true );
+ bool CollectionCursorCache::eraseCursorGlobalIfAuthorized(OperationContext* txn, CursorId id) {
+ return _globalCursorIdCache.eraseCursor(txn, id, true);
}
- bool CollectionCursorCache::eraseCursorGlobal( CursorId id ) {
- return _globalCursorIdCache.eraseCursor( id, false );
+ bool CollectionCursorCache::eraseCursorGlobal(OperationContext* txn, CursorId id) {
+ return _globalCursorIdCache.eraseCursor(txn, id, false );
}
diff --git a/src/mongo/db/catalog/collection_cursor_cache.h b/src/mongo/db/catalog/collection_cursor_cache.h
index bc057def73f..d08800d4d7b 100644
--- a/src/mongo/db/catalog/collection_cursor_cache.h
+++ b/src/mongo/db/catalog/collection_cursor_cache.h
@@ -109,15 +109,15 @@ namespace mongo {
// ----------------------
- static int eraseCursorGlobalIfAuthorized( int n, long long* ids );
- static bool eraseCursorGlobalIfAuthorized( CursorId id );
+ static int eraseCursorGlobalIfAuthorized(OperationContext* txn, int n, long long* ids);
+ static bool eraseCursorGlobalIfAuthorized(OperationContext* txn, CursorId id);
- static bool eraseCursorGlobal( CursorId id );
+ static bool eraseCursorGlobal(OperationContext* txn, CursorId id);
/**
* @return number timed out
*/
- static std::size_t timeoutCursorsGlobal( int millisSinceLastCall );
+ static std::size_t timeoutCursorsGlobal(OperationContext* txn, int millisSinceLastCall);
private:
CursorId _allocateCursorId_inlock();
diff --git a/src/mongo/db/catalog/database_holder.cpp b/src/mongo/db/catalog/database_holder.cpp
index 3516cc06a09..aeded6b196b 100644
--- a/src/mongo/db/catalog/database_holder.cpp
+++ b/src/mongo/db/catalog/database_holder.cpp
@@ -41,8 +41,7 @@
namespace mongo {
- Database* DatabaseHolder::getOrCreate( const string& ns, const string& path, bool& justCreated ) {
- OperationContextImpl txn; // TODO get rid of this once reads require transactions
+ Database* DatabaseHolder::getOrCreate(OperationContext* txn, const string& ns, const string& path, bool& justCreated) {
string dbname = _todb( ns );
{
SimpleMutex::scoped_lock lk(_m);
@@ -74,7 +73,7 @@ namespace mongo {
cc().writeHappened();
// this locks _m for defensive checks, so we don't want to be locked right here :
- Database *db = new Database( &txn, dbname.c_str() , justCreated , path );
+ Database *db = new Database(txn, dbname.c_str(), justCreated, path);
{
SimpleMutex::scoped_lock lk(_m);
diff --git a/src/mongo/db/catalog/database_holder.h b/src/mongo/db/catalog/database_holder.h
index a2901926db7..ad40b8601c4 100644
--- a/src/mongo/db/catalog/database_holder.h
+++ b/src/mongo/db/catalog/database_holder.h
@@ -82,7 +82,10 @@ namespace mongo {
return 0;
}
- Database* getOrCreate( const std::string& ns , const std::string& path , bool& justCreated );
+ Database* getOrCreate(OperationContext* txn,
+ const std::string& ns,
+ const std::string& path,
+ bool& justCreated);
void erase( const std::string& ns , const std::string& path ) {
SimpleMutex::scoped_lock lk(_m);
diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp
index 21dd08f9b92..97e5ba1c71e 100644
--- a/src/mongo/db/client.cpp
+++ b/src/mongo/db/client.cpp
@@ -55,6 +55,7 @@
#include "mongo/db/instance.h"
#include "mongo/db/json.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/repl/rs.h"
#include "mongo/db/storage_options.h"
#include "mongo/s/chunk_version.h"
@@ -191,14 +192,13 @@ namespace mongo {
/** "read lock, and set my context, all in one operation"
* This handles (if not recursively locked) opening an unopened database.
*/
- Client::ReadContext::ReadContext(const string& ns,
- const std::string& path,
- bool doVersion) {
+ Client::ReadContext::ReadContext(
+ OperationContext* txn, const string& ns, bool doVersion) {
{
- lk.reset( new Lock::DBRead(ns) );
- Database *db = dbHolder().get(ns, path);
+ _lk.reset(new Lock::DBRead(txn->lockState(), ns));
+ Database *db = dbHolder().get(ns, storageGlobalParams.dbpath);
if( db ) {
- c.reset( new Context(path, ns, db, doVersion) );
+ _c.reset(new Context(storageGlobalParams.dbpath, ns, db, doVersion));
return;
}
}
@@ -209,17 +209,18 @@ namespace mongo {
if( Lock::isW() ) {
// write locked already
DEV RARELY log() << "write locked on ReadContext construction " << ns << endl;
- c.reset(new Context(ns, path, doVersion));
+ _c.reset(new Context(ns, storageGlobalParams.dbpath, doVersion));
}
else if( !Lock::nested() ) {
- lk.reset(0);
+ _lk.reset(0);
{
Lock::GlobalWrite w;
- Context c(ns, path, doVersion);
+ Context c(ns, storageGlobalParams.dbpath, doVersion);
}
+
// db could be closed at this interim point -- that is ok, we will throw, and don't mind throwing.
- lk.reset( new Lock::DBRead(ns) );
- c.reset(new Context(ns, path, doVersion));
+ _lk.reset(new Lock::DBRead(txn->lockState(), ns));
+ _c.reset(new Context(ns, storageGlobalParams.dbpath, doVersion));
}
else {
uasserted(15928, str::stream() << "can't open a database from a nested read lock " << ns);
@@ -231,9 +232,10 @@ namespace mongo {
// it would be easy to first check that there is at least a .ns file, or something similar.
}
- Client::WriteContext::WriteContext(const string& ns, const std::string& path, bool doVersion)
- : _lk( ns ) ,
- _c(ns, path, doVersion) {
+ Client::WriteContext::WriteContext(
+ OperationContext* opCtx, const std::string& ns, bool doVersion)
+ : _lk(opCtx->lockState(), ns),
+ _c(ns, storageGlobalParams.dbpath, doVersion) {
}
@@ -279,7 +281,8 @@ namespace mongo {
uassert(14031, "Can't take a write lock while out of disk space", false);
}
- _db = dbHolderUnchecked().getOrCreate( _ns , _path , _justCreated );
+ OperationContextImpl txn; // TODO get rid of this once reads require transactions
+ _db = dbHolderUnchecked().getOrCreate(&txn, _ns, _path, _justCreated);
verify(_db);
if( _doVersion ) checkNotStale();
massert( 16107 , str::stream() << "Don't have a lock on: " << _ns , Lock::atLeastReadLocked( _ns ) );
diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h
index 6d4179c506a..17beba12098 100644
--- a/src/mongo/db/client.h
+++ b/src/mongo/db/client.h
@@ -146,13 +146,13 @@ namespace mongo {
*/
class ReadContext : boost::noncopyable {
public:
- ReadContext(const std::string& ns,
- const std::string& path=storageGlobalParams.dbpath,
+ ReadContext(OperationContext* txn,
+ const std::string& ns,
bool doVersion = true);
- Context& ctx() { return *c.get(); }
+ Context& ctx() { return *_c.get(); }
private:
- scoped_ptr<Lock::DBRead> lk;
- scoped_ptr<Context> c;
+ scoped_ptr<Lock::DBRead> _lk;
+ scoped_ptr<Context> _c;
};
/* Set database we want to use, then, restores when we finish (are out of scope)
@@ -219,10 +219,9 @@ namespace mongo {
class WriteContext : boost::noncopyable {
public:
- WriteContext(const std::string& ns,
- const std::string& path=storageGlobalParams.dbpath,
- bool doVersion = true);
+ WriteContext(OperationContext* opCtx, const std::string& ns, bool doVersion = true);
Context& ctx() { return _c; }
+
private:
Lock::DBWrite _lk;
Context _c;
diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp
index 628c4e110b7..3bac1b29535 100644
--- a/src/mongo/db/clientcursor.cpp
+++ b/src/mongo/db/clientcursor.cpp
@@ -45,6 +45,7 @@
#include "mongo/db/db.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/kill_current_op.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/repl/rs.h"
#include "mongo/db/repl/write_concern.h"
@@ -219,8 +220,10 @@ namespace mongo {
Client& client = cc();
Timer t;
const int Secs = 4;
- while ( ! inShutdown() ) {
- cursorStatsTimedOut.increment( CollectionCursorCache::timeoutCursorsGlobal( t.millisReset() ) );
+ while (!inShutdown()) {
+ OperationContextImpl txn;
+ cursorStatsTimedOut.increment(
+ CollectionCursorCache::timeoutCursorsGlobal(&txn, t.millisReset()));
sleepsecs(Secs);
}
client.shutdown();
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp
index d1b97e9be3a..519a1f6b9e8 100644
--- a/src/mongo/db/cloner.cpp
+++ b/src/mongo/db/cloner.cpp
@@ -301,7 +301,7 @@ namespace mongo {
bool copyIndexes,
bool logForRepl) {
- Client::WriteContext ctx(ns);
+ Client::WriteContext ctx(txn, ns);
// config
string temp = ctx.ctx().db()->name() + ".system.namespaces";
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp
index 524a7f916de..2d33d022da7 100644
--- a/src/mongo/db/commands.cpp
+++ b/src/mongo/db/commands.cpp
@@ -255,13 +255,15 @@ namespace mongo {
return Status(ErrorCodes::Error(code), errmsg);
}
- Status Command::checkAuthForCommand(ClientBasic* client,
+ Status Command::checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
std::vector<Privilege> privileges;
this->addRequiredPrivileges(dbname, cmdObj, &privileges);
- if (client->getAuthorizationSession()->isAuthorizedForPrivileges(privileges))
+ if (client->getAuthorizationSession()->isAuthorizedForPrivileges(txn, privileges)) {
return Status::OK();
+ }
return Status(ErrorCodes::Unauthorized, "unauthorized");
}
@@ -274,7 +276,8 @@ namespace mongo {
}
}
- static Status _checkAuthorizationImpl(Command* c,
+ static Status _checkAuthorizationImpl(OperationContext* txn,
+ Command* c,
ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj,
@@ -285,7 +288,7 @@ namespace mongo {
" may only be run against the admin database.");
}
if (client->getAuthorizationSession()->getAuthorizationManager().isAuthEnabled()) {
- Status status = c->checkAuthForCommand(client, dbname, cmdObj);
+ Status status = c->checkAuthForCommand(txn, client, dbname, cmdObj);
if (status == ErrorCodes::Unauthorized) {
mmb::Document cmdToLog(cmdObj, mmb::Document::kInPlaceDisabled);
c->redactForLogging(&cmdToLog);
@@ -307,13 +310,14 @@ namespace mongo {
return Status::OK();
}
- Status Command::_checkAuthorization(Command* c,
+ Status Command::_checkAuthorization(OperationContext* txn,
+ Command* c,
ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj,
bool fromRepl) {
namespace mmb = mutablebson;
- Status status = _checkAuthorizationImpl(c, client, dbname, cmdObj, fromRepl);
+ Status status = _checkAuthorizationImpl(txn, c, client, dbname, cmdObj, fromRepl);
if (!status.isOK()) {
log() << status << std::endl;
}
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 4446020a94c..38c79f1971f 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -141,7 +141,8 @@ namespace mutablebson {
* Checks if the given client is authorized to run this command on database "dbname"
* with the invocation described by "cmdObj".
*/
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj);
@@ -256,7 +257,8 @@ namespace mutablebson {
* ErrorCodes::Unauthorized otherwise, but any return other than Status::OK implies not
* authorized.
*/
- static Status _checkAuthorization(Command* c,
+ static Status _checkAuthorization(OperationContext* txn,
+ Command* c,
ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj,
diff --git a/src/mongo/db/commands/apply_ops.cpp b/src/mongo/db/commands/apply_ops.cpp
index ef3c2ea2ab9..37c72610627 100644
--- a/src/mongo/db/commands/apply_ops.cpp
+++ b/src/mongo/db/commands/apply_ops.cpp
@@ -127,7 +127,7 @@ namespace mongo {
// operations are applied. We are already locked globally at this point, so taking
// a DBWrite on the namespace creates a nested lock, and yields are disallowed for
// operations that hold a nested lock.
- Lock::DBWrite lk(ns);
+ Lock::DBWrite lk(txn->lockState(), ns);
invariant(Lock::nested());
Client::Context ctx(ns);
diff --git a/src/mongo/db/commands/auth_schema_upgrade_d.cpp b/src/mongo/db/commands/auth_schema_upgrade_d.cpp
index 3a52792615e..4f63bacd173 100644
--- a/src/mongo/db/commands/auth_schema_upgrade_d.cpp
+++ b/src/mongo/db/commands/auth_schema_upgrade_d.cpp
@@ -147,7 +147,7 @@ namespace {
if (!status.isOK())
return appendCommandStatus(result, status);
- status = authzManager->upgradeSchema(maxSteps, writeConcern);
+ status = authzManager->upgradeSchema(txn, maxSteps, writeConcern);
if (status.isOK())
result.append("done", true);
return appendCommandStatus(result, status);
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index 651ecb6cca9..b0210188795 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -160,7 +160,7 @@ namespace mongo {
if (mechanism.empty()) {
mechanism = "MONGODB-CR";
}
- Status status = _authenticate(mechanism, user, cmdObj);
+ Status status = _authenticate(txn, mechanism, user, cmdObj);
audit::logAuthentication(ClientBasic::getCurrent(),
mechanism,
user,
@@ -184,12 +184,13 @@ namespace mongo {
return true;
}
- Status CmdAuthenticate::_authenticate(const std::string& mechanism,
+ Status CmdAuthenticate::_authenticate(OperationContext* txn,
+ const std::string& mechanism,
const UserName& user,
const BSONObj& cmdObj) {
if (mechanism == "MONGODB-CR") {
- return _authenticateCR(user, cmdObj);
+ return _authenticateCR(txn, user, cmdObj);
}
#ifdef MONGO_SSL
if (mechanism == "MONGODB-X509") {
@@ -199,7 +200,8 @@ namespace mongo {
return Status(ErrorCodes::BadValue, "Unsupported mechanism: " + mechanism);
}
- Status CmdAuthenticate::_authenticateCR(const UserName& user, const BSONObj& cmdObj) {
+ Status CmdAuthenticate::_authenticateCR(
+ OperationContext* txn, const UserName& user, const BSONObj& cmdObj) {
if (user == internalSecurity.user->getName() &&
serverGlobalParams.clusterAuthMode.load() ==
@@ -246,7 +248,7 @@ namespace mongo {
}
User* userObj;
- Status status = getGlobalAuthorizationManager()->acquireUser(user, &userObj);
+ Status status = getGlobalAuthorizationManager()->acquireUser(txn, user, &userObj);
if (!status.isOK()) {
// Failure to find the privilege document indicates no-such-user, a fact that we do not
// wish to reveal to the client. So, we return AuthenticationFailed rather than passing
@@ -275,7 +277,7 @@ namespace mongo {
AuthorizationSession* authorizationSession =
ClientBasic::getCurrent()->getAuthorizationSession();
- status = authorizationSession->addAndAuthorizeUser(user);
+ status = authorizationSession->addAndAuthorizeUser(txn, user);
if (!status.isOK()) {
return status;
}
diff --git a/src/mongo/db/commands/authentication_commands.h b/src/mongo/db/commands/authentication_commands.h
index 4ccfb464aa7..6fa2bc6a78a 100644
--- a/src/mongo/db/commands/authentication_commands.h
+++ b/src/mongo/db/commands/authentication_commands.h
@@ -71,10 +71,12 @@ namespace mongo {
* mechanism, and ProtocolError, indicating an error in the use of the authentication
* protocol.
*/
- Status _authenticate(const std::string& mechanism,
+ Status _authenticate(OperationContext* txn,
+ const std::string& mechanism,
const UserName& user,
const BSONObj& cmdObj);
- Status _authenticateCR(const UserName& user, const BSONObj& cmdObj);
+ Status _authenticateCR(
+ OperationContext* txn, const UserName& user, const BSONObj& cmdObj);
Status _authenticateX509(const UserName& user, const BSONObj& cmdObj);
bool _clusterIdMatch(const std::string& subjectName, const std::string& srvSubjectName);
};
diff --git a/src/mongo/db/commands/cleanup_orphaned_cmd.cpp b/src/mongo/db/commands/cleanup_orphaned_cmd.cpp
index dac324345bd..0746ec9398b 100644
--- a/src/mongo/db/commands/cleanup_orphaned_cmd.cpp
+++ b/src/mongo/db/commands/cleanup_orphaned_cmd.cpp
@@ -158,11 +158,12 @@ namespace mongo {
virtual bool adminOnly() const { return true; }
virtual bool localHostOnlyIfNoAuth( const BSONObj& cmdObj ) { return false; }
- virtual Status checkAuthForCommand( ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj ) {
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj ) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::cleanupOrphaned)) {
+ txn, ResourcePattern::forClusterResource(), ActionType::cleanupOrphaned)) {
return Status(ErrorCodes::Unauthorized,
"Not authorized for cleanupOrphaned command.");
}
diff --git a/src/mongo/db/commands/clone.cpp b/src/mongo/db/commands/clone.cpp
index b75ee5ceb69..5759c4dc528 100644
--- a/src/mongo/db/commands/clone.cpp
+++ b/src/mongo/db/commands/clone.cpp
@@ -75,14 +75,15 @@ namespace mongo {
help << "{ clone : \"host13\" }";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
ActionSet actions;
actions.addAction(ActionType::insert);
actions.addAction(ActionType::createIndex);
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(dbname), actions)) {
+ txn, ResourcePattern::forDatabaseName(dbname), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
return Status::OK();
@@ -118,7 +119,7 @@ namespace mongo {
set<string> clonedColls;
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context context( dbname );
Cloner cloner;
diff --git a/src/mongo/db/commands/clone_collection.cpp b/src/mongo/db/commands/clone_collection.cpp
index c0a124adbe3..d9cfb60819f 100644
--- a/src/mongo/db/commands/clone_collection.cpp
+++ b/src/mongo/db/commands/clone_collection.cpp
@@ -71,7 +71,8 @@ namespace mongo {
return parseNsFullyQualified(dbname, cmdObj);
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
std::string ns = parseNs(dbname, cmdObj);
@@ -81,7 +82,7 @@ namespace mongo {
actions.addAction(ActionType::createIndex); // SERVER-11418
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(NamespaceString(ns)), actions)) {
+ txn, ResourcePattern::forExactNamespace(NamespaceString(ns)), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
return Status::OK();
diff --git a/src/mongo/db/commands/collection_to_capped.cpp b/src/mongo/db/commands/collection_to_capped.cpp
index d2a909f4af4..0186a17b643 100644
--- a/src/mongo/db/commands/collection_to_capped.cpp
+++ b/src/mongo/db/commands/collection_to_capped.cpp
@@ -153,7 +153,7 @@ namespace mongo {
return false;
}
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(dbname);
Status status = cloneCollectionAsCapped( txn, ctx.db(), from, to, size, temp, true );
diff --git a/src/mongo/db/commands/compact.cpp b/src/mongo/db/commands/compact.cpp
index 3355e222570..1002ec82ffd 100644
--- a/src/mongo/db/commands/compact.cpp
+++ b/src/mongo/db/commands/compact.cpp
@@ -140,7 +140,7 @@ namespace mongo {
compactOptions.validateDocuments = cmdObj["validate"].trueValue();
- Lock::DBWrite lk(ns.ns());
+ Lock::DBWrite lk(txn->lockState(), ns.ns());
BackgroundOperation::assertNoBgOpInProgForNs(ns.ns());
Client::Context ctx(ns);
diff --git a/src/mongo/db/commands/copydb.cpp b/src/mongo/db/commands/copydb.cpp
index 0db7a7950bb..b1b9b2231bc 100644
--- a/src/mongo/db/commands/copydb.cpp
+++ b/src/mongo/db/commands/copydb.cpp
@@ -108,10 +108,11 @@ namespace mongo {
virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
- return copydb::checkAuthForCopydbCommand(client, dbname, cmdObj);
+ return copydb::checkAuthForCopydbCommand(txn, client, dbname, cmdObj);
}
virtual void help( stringstream &help ) const {
@@ -155,8 +156,8 @@ namespace mongo {
// SERVER-4328 todo lock just the two db's not everything for the fromself case
scoped_ptr<Lock::ScopedLock> lk( fromSelf ?
- static_cast<Lock::ScopedLock*>( new Lock::GlobalWrite() ) :
- static_cast<Lock::ScopedLock*>( new Lock::DBWrite( todb ) ) );
+ static_cast<Lock::ScopedLock*>(new Lock::GlobalWrite()) :
+ static_cast<Lock::ScopedLock*>(new Lock::DBWrite(txn->lockState(), todb)));
Cloner cloner;
string username = cmdObj.getStringField( "username" );
diff --git a/src/mongo/db/commands/copydb.h b/src/mongo/db/commands/copydb.h
index f7b2adfbe6d..9f27244f479 100644
--- a/src/mongo/db/commands/copydb.h
+++ b/src/mongo/db/commands/copydb.h
@@ -37,10 +37,12 @@
namespace mongo {
class ClientBasic;
+ class OperationContext;
namespace copydb {
- Status checkAuthForCopydbCommand(ClientBasic* client,
+ Status checkAuthForCopydbCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj);
diff --git a/src/mongo/db/commands/copydb_common.cpp b/src/mongo/db/commands/copydb_common.cpp
index 5cebb8db021..e46cf94e4e2 100644
--- a/src/mongo/db/commands/copydb_common.cpp
+++ b/src/mongo/db/commands/copydb_common.cpp
@@ -42,7 +42,8 @@
namespace mongo {
namespace copydb {
- Status checkAuthForCopydbCommand(ClientBasic* client,
+ Status checkAuthForCopydbCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
bool fromSelf = StringData(cmdObj.getStringField("fromhost")).empty();
@@ -65,7 +66,7 @@ namespace copydb {
actions.addAction(ActionType::insert);
actions.addAction(ActionType::createIndex);
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(todb), actions)) {
+ txn, ResourcePattern::forDatabaseName(todb), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
@@ -73,7 +74,7 @@ namespace copydb {
actions.addAction(ActionType::insert);
for (size_t i = 0; i < legalClientSystemCollections.size(); ++i) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnNamespace(
- NamespaceString(todb, legalClientSystemCollections[i]), actions)) {
+ txn, NamespaceString(todb, legalClientSystemCollections[i]), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
}
@@ -83,12 +84,12 @@ namespace copydb {
actions.removeAllActions();
actions.addAction(ActionType::find);
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(fromdb), actions)) {
+ txn, ResourcePattern::forDatabaseName(fromdb), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
for (size_t i = 0; i < legalClientSystemCollections.size(); ++i) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnNamespace(
- NamespaceString(fromdb, legalClientSystemCollections[i]), actions)) {
+ txn, NamespaceString(fromdb, legalClientSystemCollections[i]), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
}
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index 2519bc75cc4..87582b75e07 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -51,13 +51,14 @@ namespace mongo {
virtual bool isWriteCommandForConfigServer() const { return false; }
virtual bool slaveOk() const { return false; } // TODO: this could be made true...
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
ActionSet actions;
actions.addAction(ActionType::createIndex);
Privilege p(parseResourcePattern(dbname, cmdObj), actions);
- if ( client->getAuthorizationSession()->isAuthorizedForPrivilege(p) )
+ if (client->getAuthorizationSession()->isAuthorizedForPrivilege(txn, p))
return Status::OK();
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
@@ -132,9 +133,7 @@ namespace mongo {
// as many calls are ensureIndex (and hence no-ops), this is good so its a shared
// lock for common calls. We only take write lock if needed.
// Note: createIndexes command does not currently respect shard versioning.
- Client::ReadContext readContext( ns,
- storageGlobalParams.dbpath,
- false /* doVersion */ );
+ Client::ReadContext readContext(txn, ns, false /* doVersion */);
const Collection* collection = readContext.ctx().db()->getCollection( ns.ns() );
if ( collection ) {
for ( size_t i = 0; i < specs.size(); i++ ) {
@@ -164,9 +163,7 @@ namespace mongo {
// now we know we have to create index(es)
// Note: createIndexes command does not currently respect shard versioning.
- Client::WriteContext writeContext( ns.ns(),
- storageGlobalParams.dbpath,
- false /* doVersion */ );
+ Client::WriteContext writeContext(txn, ns.ns(), false /* doVersion */ );
Database* db = writeContext.ctx().db();
Collection* collection = db->getCollection( txn, ns.ns() );
diff --git a/src/mongo/db/commands/dbhash.cpp b/src/mongo/db/commands/dbhash.cpp
index cddac188c94..3899e7f522d 100644
--- a/src/mongo/db/commands/dbhash.cpp
+++ b/src/mongo/db/commands/dbhash.cpp
@@ -145,7 +145,7 @@ namespace mongo {
list<string> colls;
const string ns = parseNs(dbname, cmdObj);
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Database* db = ctx.ctx().db();
if ( db )
db->getDatabaseCatalogEntry()->getCollectionNamespaces( &colls );
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index bc05c80195a..4c3a6bb5955 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -90,7 +90,7 @@ namespace mongo {
long long nscannedObjects = 0; // full objects looked at
long long n = 0; // matches
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index ab9144b7c96..c68aede5bc3 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -93,7 +93,7 @@ namespace mongo {
CmdDropIndexes() : Command("dropIndexes", false, "deleteIndexes") { }
bool run(OperationContext* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& anObjBuilder, bool fromRepl) {
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
bool ok = wrappedRun(txn, dbname, jsobj, errmsg, anObjBuilder);
if (ok && !fromRepl)
repl::logOp(txn, "c",(dbname + ".$cmd").c_str(), jsobj);
@@ -220,7 +220,7 @@ namespace mongo {
MONGO_TLOG(0) << "CMD: reIndex " << toDeleteNs << endl;
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(toDeleteNs);
Collection* collection = ctx.db()->getCollection( toDeleteNs );
diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp
index 44ca0e36609..c297d772530 100644
--- a/src/mongo/db/commands/find_and_modify.cpp
+++ b/src/mongo/db/commands/find_and_modify.cpp
@@ -93,7 +93,7 @@ namespace mongo {
return false;
}
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(ns);
return runNoDirectClient( txn, ns ,
@@ -133,7 +133,7 @@ namespace mongo {
BSONObjBuilder& result,
string& errmsg) {
- Lock::DBWrite lk( ns );
+ Lock::DBWrite lk(txn->lockState(), ns);
Client::Context cx( ns );
Collection* collection = cx.db()->getCollection( txn, ns );
@@ -325,7 +325,7 @@ namespace mongo {
}
}
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(ns);
BSONObj out = db.findOne(ns, q, fields);
diff --git a/src/mongo/db/commands/geonear.cpp b/src/mongo/db/commands/geonear.cpp
index 5976d8a4e3d..ebbdd6efd69 100644
--- a/src/mongo/db/commands/geonear.cpp
+++ b/src/mongo/db/commands/geonear.cpp
@@ -76,7 +76,7 @@ namespace mongo {
return false;
}
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Database* db = ctx.ctx().db();
if ( !db ) {
diff --git a/src/mongo/db/commands/group.cpp b/src/mongo/db/commands/group.cpp
index 6e80bbef1f6..43a1fda05fc 100644
--- a/src/mongo/db/commands/group.cpp
+++ b/src/mongo/db/commands/group.cpp
@@ -56,12 +56,13 @@ namespace mongo {
virtual void help( stringstream &help ) const {
help << "http://dochub.mongodb.org/core/aggregation";
}
- Status checkAuthForCommand(ClientBasic* client,
+ Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
std::string ns = parseNs(dbname, cmdObj);
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnNamespace(
- NamespaceString(ns), ActionType::find)) {
+ txn, NamespaceString(ns), ActionType::find)) {
return Status(ErrorCodes::Unauthorized, "unauthorized");
}
return Status::OK();
@@ -254,7 +255,7 @@ namespace mongo {
finalize = p["finalize"]._asCode();
const string ns = parseNs(dbname, jsobj);
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
return group( ctx.ctx().db() , ns , q ,
key , keyf , reduce._asCode() , reduce.type() != CodeWScope ? 0 : reduce.codeWScopeScopeDataUnsafe() ,
diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp
index 60346f782c4..776dad23792 100644
--- a/src/mongo/db/commands/index_filter_commands.cpp
+++ b/src/mongo/db/commands/index_filter_commands.cpp
@@ -124,7 +124,7 @@ namespace mongo {
string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string ns = parseNs(dbname, cmdObj);
- Status status = runIndexFilterCommand(ns, cmdObj, &result);
+ Status status = runIndexFilterCommand(txn, ns, cmdObj, &result);
if (!status.isOK()) {
addStatus(status, result);
@@ -144,12 +144,14 @@ namespace mongo {
ss << helpText;
}
- Status IndexFilterCommand::checkAuthForCommand(ClientBasic* client, const std::string& dbname,
- const BSONObj& cmdObj) {
+ Status IndexFilterCommand::checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
ResourcePattern pattern = parseResourcePattern(dbname, cmdObj);
- if (authzSession->isAuthorizedForActionsOnResource(pattern, ActionType::planCacheIndexFilter)) {
+ if (authzSession->isAuthorizedForActionsOnResource(txn, pattern, ActionType::planCacheIndexFilter)) {
return Status::OK();
}
@@ -159,9 +161,12 @@ namespace mongo {
ListFilters::ListFilters() : IndexFilterCommand("planCacheListFilters",
"Displays index filters for all query shapes in a collection.") { }
- Status ListFilters::runIndexFilterCommand(const string& ns, BSONObj& cmdObj, BSONObjBuilder* bob) {
+ Status ListFilters::runIndexFilterCommand(OperationContext* txn,
+ const string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob) {
// This is a read lock. The query settings is owned by the collection.
- Client::ReadContext readCtx(ns);
+ Client::ReadContext readCtx(txn, ns);
Client::Context& ctx = readCtx.ctx();
QuerySettings* querySettings;
PlanCache* unused;
@@ -218,9 +223,12 @@ namespace mongo {
"Clears index filter for a single query shape or, "
"if the query shape is omitted, all filters for the collection.") { }
- Status ClearFilters::runIndexFilterCommand(const string& ns, BSONObj& cmdObj, BSONObjBuilder* bob) {
+ Status ClearFilters::runIndexFilterCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob) {
// This is a read lock. The query settings is owned by the collection.
- Client::ReadContext readCtx(ns);
+ Client::ReadContext readCtx(txn, ns);
Client::Context& ctx = readCtx.ctx();
QuerySettings* querySettings;
PlanCache* planCache;
@@ -306,9 +314,12 @@ namespace mongo {
SetFilter::SetFilter() : IndexFilterCommand("planCacheSetFilter",
"Sets index filter for a query shape. Overrides existing filter.") { }
- Status SetFilter::runIndexFilterCommand(const string& ns, BSONObj& cmdObj, BSONObjBuilder* bob) {
+ Status SetFilter::runIndexFilterCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob) {
// This is a read lock. The query settings is owned by the collection.
- Client::ReadContext readCtx(ns);
+ Client::ReadContext readCtx(txn, ns);
Client::Context& ctx = readCtx.ctx();
QuerySettings* querySettings;
PlanCache* planCache;
diff --git a/src/mongo/db/commands/index_filter_commands.h b/src/mongo/db/commands/index_filter_commands.h
index a08ddd816db..4ae6824162f 100644
--- a/src/mongo/db/commands/index_filter_commands.h
+++ b/src/mongo/db/commands/index_filter_commands.h
@@ -76,7 +76,9 @@ namespace mongo {
* One action type defined for index filter commands:
* - planCacheIndexFilter
*/
- virtual Status checkAuthForCommand(ClientBasic* client, const std::string& dbname,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
const BSONObj& cmdObj);
/**
@@ -85,7 +87,9 @@ namespace mongo {
* Should contain just enough logic to invoke run*Command() function
* in query_settings.h
*/
- virtual Status runIndexFilterCommand(const std::string& ns, BSONObj& cmdObj,
+ virtual Status runIndexFilterCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
BSONObjBuilder* bob) = 0;
private:
@@ -102,7 +106,10 @@ namespace mongo {
public:
ListFilters();
- virtual Status runIndexFilterCommand(const std::string& ns, BSONObj& cmdObj, BSONObjBuilder* bob);
+ virtual Status runIndexFilterCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob);
/**
* Looks up index filters from collection's query settings.
@@ -121,7 +128,10 @@ namespace mongo {
public:
ClearFilters();
- virtual Status runIndexFilterCommand(const std::string& ns, BSONObj& cmdObj, BSONObjBuilder* bob);
+ virtual Status runIndexFilterCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob);
/**
* If query shape is provided, clears index filter for a query.
@@ -149,7 +159,10 @@ namespace mongo {
public:
SetFilter();
- virtual Status runIndexFilterCommand(const std::string& ns, BSONObj& cmdObj, BSONObjBuilder* bob);
+ virtual Status runIndexFilterCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob);
/**
* Sets index filter for a query shape.
diff --git a/src/mongo/db/commands/merge_chunks_cmd.cpp b/src/mongo/db/commands/merge_chunks_cmd.cpp
index 24d2bf6dc39..f22689b89df 100644
--- a/src/mongo/db/commands/merge_chunks_cmd.cpp
+++ b/src/mongo/db/commands/merge_chunks_cmd.cpp
@@ -52,10 +52,12 @@ namespace mongo {
<< " (opt) shardName : <shard name> }";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
ActionType::splitChunk)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index af99dfa6818..97c5d1fb9b5 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -342,7 +342,7 @@ namespace mongo {
if (_useIncremental) {
// Create the inc collection and make sure we have index on "0" key.
// Intentionally not replicating the inc collection to secondaries.
- Client::WriteContext incCtx( _config.incLong );
+ Client::WriteContext incCtx(_txn, _config.incLong);
Collection* incColl = incCtx.ctx().db()->getCollection( _txn, _config.incLong );
if ( !incColl ) {
CollectionOptions options;
@@ -364,7 +364,7 @@ namespace mongo {
{
// copy indexes into temporary storage
- Client::WriteContext finalCtx( _config.outputOptions.finalNamespace );
+ Client::WriteContext finalCtx(_txn, _config.outputOptions.finalNamespace);
Collection* finalColl =
finalCtx.ctx().db()->getCollection( _config.outputOptions.finalNamespace );
if ( finalColl ) {
@@ -392,7 +392,7 @@ namespace mongo {
{
// create temp collection and insert the indexes from temporary storage
- Client::WriteContext tempCtx( _config.tempNamespace );
+ Client::WriteContext tempCtx(_txn, _config.tempNamespace);
Collection* tempColl = tempCtx.ctx().db()->getCollection( _txn, _config.tempNamespace );
if ( !tempColl ) {
CollectionOptions options;
@@ -559,7 +559,7 @@ namespace mongo {
_safeCount(_db, _config.tempNamespace, BSONObj()));
auto_ptr<DBClientCursor> cursor = _db.query( _config.tempNamespace , BSONObj() );
while ( cursor->more() ) {
- Lock::DBWrite lock( _config.outputOptions.finalNamespace );
+ Lock::DBWrite lock(_txn->lockState(), _config.outputOptions.finalNamespace);
BSONObj o = cursor->nextSafe();
Helpers::upsert( _txn, _config.outputOptions.finalNamespace , o );
_txn->recoveryUnit()->commitIfNeeded();
@@ -619,7 +619,7 @@ namespace mongo {
void State::insert( const string& ns , const BSONObj& o ) {
verify( _onDisk );
- Client::WriteContext ctx( ns );
+ Client::WriteContext ctx(_txn, ns );
Collection* coll = ctx.ctx().db()->getCollection( ns );
if ( !coll )
uasserted(13630, str::stream() << "attempted to insert into nonexistent" <<
@@ -645,7 +645,7 @@ namespace mongo {
void State::_insertToInc( BSONObj& o ) {
verify( _onDisk );
- Client::WriteContext ctx( _config.incLong );
+ Client::WriteContext ctx(_txn, _config.incLong );
Collection* coll = ctx.ctx().db()->getCollection( _config.incLong );
if ( !coll )
uasserted(13631, str::stream() << "attempted to insert into nonexistent"
@@ -921,7 +921,7 @@ namespace mongo {
BSONObj sortKey = BSON( "0" << 1 );
{
- Client::WriteContext incCtx( _config.incLong );
+ Client::WriteContext incCtx(_txn, _config.incLong );
Collection* incColl = incCtx.ctx().db()->getCollection( _config.incLong );
bool foundIndex = false;
@@ -940,7 +940,7 @@ namespace mongo {
verify( foundIndex );
}
- scoped_ptr<Client::ReadContext> ctx(new Client::ReadContext(_config.incLong));
+ scoped_ptr<Client::ReadContext> ctx(new Client::ReadContext(_txn, _config.incLong));
BSONObj prev;
BSONList all;
@@ -989,7 +989,7 @@ namespace mongo {
// reduce a finalize array
finalReduce( all );
- ctx.reset(new Client::ReadContext(_config.incLong));
+ ctx.reset(new Client::ReadContext(_txn, _config.incLong));
all.clear();
prev = o;
@@ -1005,7 +1005,7 @@ namespace mongo {
ctx.reset();
// reduce and finalize last array
finalReduce( all );
- ctx.reset(new Client::ReadContext(_config.incLong));
+ ctx.reset(new Client::ReadContext(_txn, _config.incLong));
pm.finished();
}
@@ -1060,7 +1060,7 @@ namespace mongo {
if ( ! _onDisk )
return;
- Lock::DBWrite kl(_config.incLong);
+ Lock::DBWrite kl(_txn->lockState(), _config.incLong);
for ( InMemory::iterator i=_temp->begin(); i!=_temp->end(); i++ ) {
BSONList& all = i->second;
@@ -1216,7 +1216,7 @@ namespace mongo {
// Prevent sharding state from changing during the MR.
auto_ptr<RangePreserver> rangePreserver;
{
- Client::ReadContext ctx(config.ns);
+ Client::ReadContext ctx(txn, config.ns);
Collection* collection = ctx.ctx().db()->getCollection( config.ns );
if ( collection )
rangePreserver.reset(new RangePreserver(collection));
@@ -1278,7 +1278,7 @@ namespace mongo {
// We've got a cursor preventing migrations off, now re-establish our useful cursor
// Need lock and context to use it
- scoped_ptr<Lock::DBRead> lock(new Lock::DBRead(config.ns));
+ scoped_ptr<Lock::DBRead> lock(new Lock::DBRead(txn->lockState(), config.ns));
// This context does no version check, safe b/c we checked earlier and have an
// open cursor
@@ -1340,7 +1340,7 @@ namespace mongo {
ctx.reset();
lock.reset();
state.reduceAndSpillInMemoryStateIfNeeded();
- lock.reset(new Lock::DBRead(config.ns));
+ lock.reset(new Lock::DBRead(txn->lockState(), config.ns));
ctx.reset(new Client::Context(config.ns, storageGlobalParams.dbpath, false));
reduceTime += t.micros();
diff --git a/src/mongo/db/commands/oplog_note.cpp b/src/mongo/db/commands/oplog_note.cpp
index 92ce1ebcd14..d59666dc461 100644
--- a/src/mongo/db/commands/oplog_note.cpp
+++ b/src/mongo/db/commands/oplog_note.cpp
@@ -47,11 +47,12 @@ namespace mongo {
virtual void help( stringstream &help ) const {
help << "Adds a no-op entry to the oplog";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::appendOplogNote)) {
+ txn, ResourcePattern::forClusterResource(), ActionType::appendOplogNote)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
return Status::OK();
diff --git a/src/mongo/db/commands/parallel_collection_scan.cpp b/src/mongo/db/commands/parallel_collection_scan.cpp
index 061175638cd..136e3095591 100644
--- a/src/mongo/db/commands/parallel_collection_scan.cpp
+++ b/src/mongo/db/commands/parallel_collection_scan.cpp
@@ -148,13 +148,14 @@ namespace mongo {
virtual bool isWriteCommandForConfigServer() const { return false; }
virtual bool slaveOk() const { return true; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
ActionSet actions;
actions.addAction(ActionType::find);
Privilege p(parseResourcePattern(dbname, cmdObj), actions);
- if ( client->getAuthorizationSession()->isAuthorizedForPrivilege(p) )
+ if ( client->getAuthorizationSession()->isAuthorizedForPrivilege(txn, p) )
return Status::OK();
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
@@ -165,7 +166,7 @@ namespace mongo {
NamespaceString ns( dbname, cmdObj[name].String() );
- Client::ReadContext ctx(ns.ns());
+ Client::ReadContext ctx(txn, ns.ns());
Database* db = ctx.ctx().db();
Collection* collection = db->getCollection( ns );
diff --git a/src/mongo/db/commands/parameters.cpp b/src/mongo/db/commands/parameters.cpp
index 981e04c26a5..a600be68787 100644
--- a/src/mongo/db/commands/parameters.cpp
+++ b/src/mongo/db/commands/parameters.cpp
@@ -96,7 +96,7 @@ namespace mongo {
const ServerParameter::Map& m = ServerParameterSet::getGlobal()->getMap();
for ( ServerParameter::Map::const_iterator i = m.begin(); i != m.end(); ++i ) {
if ( all || cmdObj.hasElement( i->first.c_str() ) ) {
- i->second->append( result, i->second->name() );
+ i->second->append(txn, result, i->second->name() );
}
}
@@ -177,7 +177,7 @@ namespace mongo {
}
if ( s == 0 )
- j->second->append( result, "was" );
+ j->second->append(txn, result, "was" );
Status status = j->second->set( e );
if ( status.isOK() ) {
@@ -203,7 +203,7 @@ namespace mongo {
public:
LogLevelSetting() : ServerParameter(ServerParameterSet::getGlobal(), "logLevel") {}
- virtual void append(BSONObjBuilder& b, const std::string& name) {
+ virtual void append(OperationContext* txn, BSONObjBuilder& b, const std::string& name) {
b << name << logger::globalLogDomain()->getMinimumLogSeverity().toInt();
}
@@ -257,7 +257,8 @@ namespace mongo {
}
}
- virtual void append(BSONObjBuilder& b, const std::string& name) {
+ virtual void append(
+ OperationContext* txn, BSONObjBuilder& b, const std::string& name) {
b << name << sslModeStr();
}
@@ -324,7 +325,8 @@ namespace mongo {
}
}
- virtual void append(BSONObjBuilder& b, const std::string& name) {
+ virtual void append(
+ OperationContext* txn, BSONObjBuilder& b, const std::string& name) {
b << name << clusterAuthModeStr();
}
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index ea373a92d1c..a43d77eeda0 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -317,7 +317,7 @@ namespace {
// sharding version that we synchronize on here. This is also why we always need to
// create a ClientCursor even when we aren't outputting to a cursor. See the comment
// on ShardFilterStage for more details.
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection(ns);
diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp
index f7e97c68072..f1a308504a2 100644
--- a/src/mongo/db/commands/plan_cache_commands.cpp
+++ b/src/mongo/db/commands/plan_cache_commands.cpp
@@ -118,7 +118,7 @@ namespace mongo {
string& errmsg, BSONObjBuilder& result, bool fromRepl) {
string ns = parseNs(dbname, cmdObj);
- Status status = runPlanCacheCommand(ns, cmdObj, &result);
+ Status status = runPlanCacheCommand(txn, ns, cmdObj, &result);
if (!status.isOK()) {
addStatus(status, result);
@@ -138,12 +138,14 @@ namespace mongo {
ss << helpText;
}
- Status PlanCacheCommand::checkAuthForCommand(ClientBasic* client, const std::string& dbname,
+ Status PlanCacheCommand::checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
ResourcePattern pattern = parseResourcePattern(dbname, cmdObj);
- if (authzSession->isAuthorizedForActionsOnResource(pattern, actionType)) {
+ if (authzSession->isAuthorizedForActionsOnResource(txn, pattern, actionType)) {
return Status::OK();
}
@@ -206,10 +208,12 @@ namespace mongo {
"Displays all query shapes in a collection.",
ActionType::planCacheRead) { }
- Status PlanCacheListQueryShapes::runPlanCacheCommand(const string& ns, BSONObj& cmdObj,
+ Status PlanCacheListQueryShapes::runPlanCacheCommand(OperationContext* txn,
+ const string& ns,
+ BSONObj& cmdObj,
BSONObjBuilder* bob) {
// This is a read lock. The query cache is owned by the collection.
- Client::ReadContext readCtx(ns);
+ Client::ReadContext readCtx(txn, ns);
Client::Context& ctx = readCtx.ctx();
PlanCache* planCache;
Status status = getPlanCache(ctx.db(), ns, &planCache);
@@ -252,10 +256,12 @@ namespace mongo {
"Drops one or all cached queries in a collection.",
ActionType::planCacheWrite) { }
- Status PlanCacheClear::runPlanCacheCommand(const string& ns, BSONObj& cmdObj,
+ Status PlanCacheClear::runPlanCacheCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
BSONObjBuilder* bob) {
// This is a read lock. The query cache is owned by the collection.
- Client::ReadContext readCtx(ns);
+ Client::ReadContext readCtx(txn, ns);
Client::Context& ctx = readCtx.ctx();
PlanCache* planCache;
Status status = getPlanCache(ctx.db(), ns, &planCache);
@@ -322,9 +328,11 @@ namespace mongo {
"Displays the cached plans for a query shape.",
ActionType::planCacheRead) { }
- Status PlanCacheListPlans::runPlanCacheCommand(const string& ns, BSONObj& cmdObj,
+ Status PlanCacheListPlans::runPlanCacheCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
BSONObjBuilder* bob) {
- Client::ReadContext readCtx(ns);
+ Client::ReadContext readCtx(txn, ns);
Client::Context& ctx = readCtx.ctx();
PlanCache* planCache;
Status status = getPlanCache(ctx.db(), ns, &planCache);
diff --git a/src/mongo/db/commands/plan_cache_commands.h b/src/mongo/db/commands/plan_cache_commands.h
index 8e7eb9667a4..e78429509fd 100644
--- a/src/mongo/db/commands/plan_cache_commands.h
+++ b/src/mongo/db/commands/plan_cache_commands.h
@@ -72,7 +72,9 @@ namespace mongo {
* - planCacheRead
* - planCacheWrite
*/
- virtual Status checkAuthForCommand(ClientBasic* client, const std::string& dbname,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
const BSONObj& cmdObj);
/**
* Subset of command arguments used by plan cache commands
@@ -80,7 +82,9 @@ namespace mongo {
* Should contain just enough logic to invoke run*Command() function
* in plan_cache.h
*/
- virtual Status runPlanCacheCommand(const std::string& ns, BSONObj& cmdObj,
+ virtual Status runPlanCacheCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
BSONObjBuilder* bob) = 0;
/**
@@ -103,7 +107,10 @@ namespace mongo {
class PlanCacheListQueryShapes : public PlanCacheCommand {
public:
PlanCacheListQueryShapes();
- virtual Status runPlanCacheCommand(const std::string& ns, BSONObj& cmdObj, BSONObjBuilder* bob);
+ virtual Status runPlanCacheCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob);
/**
* Looks up cache keys for collection's plan cache.
@@ -126,7 +133,10 @@ namespace mongo {
class PlanCacheClear : public PlanCacheCommand {
public:
PlanCacheClear();
- virtual Status runPlanCacheCommand(const std::string& ns, BSONObj& cmdObj, BSONObjBuilder* bob);
+ virtual Status runPlanCacheCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
+ BSONObjBuilder* bob);
/**
* Clears collection's plan cache.
@@ -149,7 +159,9 @@ namespace mongo {
class PlanCacheListPlans : public PlanCacheCommand {
public:
PlanCacheListPlans();
- virtual Status runPlanCacheCommand(const std::string& ns, BSONObj& cmdObj,
+ virtual Status runPlanCacheCommand(OperationContext* txn,
+ const std::string& ns,
+ BSONObj& cmdObj,
BSONObjBuilder* bob);
/**
diff --git a/src/mongo/db/commands/rename_collection.cpp b/src/mongo/db/commands/rename_collection.cpp
index 851b783aa99..946686719fd 100644
--- a/src/mongo/db/commands/rename_collection.cpp
+++ b/src/mongo/db/commands/rename_collection.cpp
@@ -54,10 +54,12 @@ namespace mongo {
return false;
}
virtual bool isWriteCommandForConfigServer() const { return true; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
- return rename_collection::checkAuthForRenameCollectionCommand(client, dbname, cmdObj);
+ return rename_collection::checkAuthForRenameCollectionCommand(
+ txn, client, dbname, cmdObj);
}
virtual void help( stringstream &help ) const {
help << " example: { renameCollection: foo.a, to: bar.b }";
diff --git a/src/mongo/db/commands/rename_collection.h b/src/mongo/db/commands/rename_collection.h
index f8651bccd4c..8ec1f7cc9b8 100644
--- a/src/mongo/db/commands/rename_collection.h
+++ b/src/mongo/db/commands/rename_collection.h
@@ -37,10 +37,12 @@
namespace mongo {
class ClientBasic;
+ class OperationContext;
namespace rename_collection {
- Status checkAuthForRenameCollectionCommand(ClientBasic* client,
+ Status checkAuthForRenameCollectionCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj);
diff --git a/src/mongo/db/commands/rename_collection_common.cpp b/src/mongo/db/commands/rename_collection_common.cpp
index fba1daffc0b..4af10ce0f9d 100644
--- a/src/mongo/db/commands/rename_collection_common.cpp
+++ b/src/mongo/db/commands/rename_collection_common.cpp
@@ -42,7 +42,8 @@
namespace mongo {
namespace rename_collection {
- Status checkAuthForRenameCollectionCommand(ClientBasic* client,
+ Status checkAuthForRenameCollectionCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
NamespaceString sourceNS = NamespaceString(cmdObj.getStringField("renameCollection"));
@@ -55,6 +56,7 @@ namespace rename_collection {
// or dest collection, then you get can do the rename, even without insert on the
// destination collection.
bool canRename = client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(sourceNS.db()),
ActionType::renameCollectionSameDB);
@@ -62,14 +64,15 @@ namespace rename_collection {
if (dropTarget) {
canDropTargetIfNeeded =
client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(targetNS),
ActionType::dropCollection);
}
bool canReadSrc = client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(sourceNS), ActionType::find);
+ txn, ResourcePattern::forExactNamespace(sourceNS), ActionType::find);
bool canReadDest = client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(targetNS), ActionType::find);
+ txn, ResourcePattern::forExactNamespace(targetNS), ActionType::find);
if (canRename && canDropTargetIfNeeded && (canReadSrc || !canReadDest)) {
return Status::OK();
@@ -81,7 +84,7 @@ namespace rename_collection {
actions.addAction(ActionType::find);
actions.addAction(ActionType::dropCollection);
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(sourceNS), actions)) {
+ txn, ResourcePattern::forExactNamespace(sourceNS), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
@@ -93,7 +96,7 @@ namespace rename_collection {
actions.addAction(ActionType::dropCollection);
}
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(targetNS), actions)) {
+ txn, ResourcePattern::forExactNamespace(targetNS), actions)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
diff --git a/src/mongo/db/commands/server_status.cpp b/src/mongo/db/commands/server_status.cpp
index e5d9a791589..ab9567cba95 100644
--- a/src/mongo/db/commands/server_status.cpp
+++ b/src/mongo/db/commands/server_status.cpp
@@ -101,8 +101,9 @@ namespace mongo {
std::vector<Privilege> requiredPrivileges;
section->addRequiredPrivileges(&requiredPrivileges);
- if (!authSession->isAuthorizedForPrivileges(requiredPrivileges))
+ if (!authSession->isAuthorizedForPrivileges(txn, requiredPrivileges)) {
continue;
+ }
bool include = section->includeByDefault();
diff --git a/src/mongo/db/commands/test_commands.cpp b/src/mongo/db/commands/test_commands.cpp
index 006a86d3677..7265270beef 100644
--- a/src/mongo/db/commands/test_commands.cpp
+++ b/src/mongo/db/commands/test_commands.cpp
@@ -62,7 +62,7 @@ namespace mongo {
string ns = dbname + "." + coll;
BSONObj obj = cmdObj[ "obj" ].embeddedObjectUserCheck();
- Lock::DBWrite lk(ns);
+ Lock::DBWrite lk(txn->lockState(), ns);
Client::Context ctx( ns );
Database* db = ctx.db();
Collection* collection = db->getCollection( ns );
@@ -140,7 +140,7 @@ namespace mongo {
int n = cmdObj.getIntField( "n" );
bool inc = cmdObj.getBoolField( "inc" ); // inclusive range?
- Client::WriteContext ctx( nss.ns() );
+ Client::WriteContext ctx(txn, nss.ns() );
Collection* collection = ctx.ctx().db()->getCollection( nss.ns() );
massert( 13417, "captrunc collection not found or empty", collection);
@@ -185,7 +185,7 @@ namespace mongo {
uassert( 13428, "emptycapped must specify a collection", !coll.empty() );
NamespaceString nss( dbname, coll );
- Client::WriteContext ctx( nss.ns() );
+ Client::WriteContext ctx(txn, nss.ns() );
Database* db = ctx.ctx().db();
Collection* collection = db->getCollection( nss.ns() );
massert( 13429, "emptycapped no such collection", collection );
diff --git a/src/mongo/db/commands/touch.cpp b/src/mongo/db/commands/touch.cpp
index 841a738abf2..ec2fc972659 100644
--- a/src/mongo/db/commands/touch.cpp
+++ b/src/mongo/db/commands/touch.cpp
@@ -104,7 +104,7 @@ namespace mongo {
return false;
}
- Client::ReadContext context( nss.ns() );
+ Client::ReadContext context(txn, nss.ns());
Database* db = context.ctx().db();
Collection* collection = db->getCollection( nss.ns() );
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp
index 40999d0cbe5..21b97074545 100644
--- a/src/mongo/db/commands/user_management_commands.cpp
+++ b/src/mongo/db/commands/user_management_commands.cpp
@@ -118,12 +118,13 @@ namespace mongo {
return Status::OK();
}
- static Status getCurrentUserRoles(AuthorizationManager* authzManager,
+ static Status getCurrentUserRoles(OperationContext* txn,
+ AuthorizationManager* authzManager,
const UserName& userName,
unordered_set<RoleName>* roles) {
User* user;
authzManager->invalidateUserByName(userName); // Need to make sure cache entry is up to date
- Status status = authzManager->acquireUser(userName, &user);
+ Status status = authzManager->acquireUser(txn, userName, &user);
if (!status.isOK()) {
return status;
}
@@ -135,10 +136,11 @@ namespace mongo {
return Status::OK();
}
- static Status checkAuthorizedToGrantRoles(AuthorizationSession* authzSession,
+ static Status checkAuthorizedToGrantRoles(OperationContext* txn,
+ AuthorizationSession* authzSession,
const std::vector<RoleName>& roles) {
for (size_t i = 0; i < roles.size(); ++i) {
- if (!authzSession->isAuthorizedToGrantRole(roles[i])) {
+ if (!authzSession->isAuthorizedToGrantRole(txn, roles[i])) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to grant role: " <<
roles[i].getFullName());
@@ -147,10 +149,11 @@ namespace mongo {
return Status::OK();
}
- static Status checkAuthorizedToRevokeRoles(AuthorizationSession* authzSession,
+ static Status checkAuthorizedToRevokeRoles(OperationContext* txn,
+ AuthorizationSession* authzSession,
const std::vector<RoleName>& roles) {
for (size_t i = 0; i < roles.size(); ++i) {
- if (!authzSession->isAuthorizedToRevokeRole(roles[i])) {
+ if (!authzSession->isAuthorizedToRevokeRole(txn, roles[i])) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to revoke role: " <<
roles[i].getFullName());
@@ -159,11 +162,12 @@ namespace mongo {
return Status::OK();
}
- static Status checkAuthorizedToGrantPrivileges(AuthorizationSession* authzSession,
+ static Status checkAuthorizedToGrantPrivileges(OperationContext* txn,
+ AuthorizationSession* authzSession,
const PrivilegeVector& privileges) {
for (PrivilegeVector::const_iterator it = privileges.begin();
it != privileges.end(); ++it) {
- Status status = authzSession->checkAuthorizedToGrantPrivilege(*it);
+ Status status = authzSession->checkAuthorizedToGrantPrivilege(txn, *it);
if (!status.isOK()) {
return status;
}
@@ -172,11 +176,12 @@ namespace mongo {
return Status::OK();
}
- static Status checkAuthorizedToRevokePrivileges(AuthorizationSession* authzSession,
+ static Status checkAuthorizedToRevokePrivileges(OperationContext* txn,
+ AuthorizationSession* authzSession,
const PrivilegeVector& privileges) {
for (PrivilegeVector::const_iterator it = privileges.begin();
it != privileges.end(); ++it) {
- Status status = authzSession->checkAuthorizedToRevokePrivilege(*it);
+ Status status = authzSession->checkAuthorizedToRevokePrivilege(txn, *it);
if (!status.isOK()) {
return status;
}
@@ -265,9 +270,10 @@ namespace mongo {
return Status::OK();
}
- static Status requireAuthSchemaVersion26Final(AuthorizationManager* authzManager) {
+ static Status requireAuthSchemaVersion26Final(
+ OperationContext* txn, AuthorizationManager* authzManager) {
int foundSchemaVersion;
- Status status = authzManager->getAuthorizationVersion(&foundSchemaVersion);
+ Status status = authzManager->getAuthorizationVersion(txn, &foundSchemaVersion);
if (!status.isOK()) {
return status;
}
@@ -282,9 +288,10 @@ namespace mongo {
return authzManager->writeAuthSchemaVersionIfNeeded();
}
- static Status requireAuthSchemaVersion26UpgradeOrFinal(AuthorizationManager* authzManager) {
+ static Status requireAuthSchemaVersion26UpgradeOrFinal(OperationContext* txn,
+ AuthorizationManager* authzManager) {
int foundSchemaVersion;
- Status status = authzManager->getAuthorizationVersion(&foundSchemaVersion);
+ Status status = authzManager->getAuthorizationVersion(txn, &foundSchemaVersion);
if (!status.isOK()) {
return status;
}
@@ -320,7 +327,8 @@ namespace mongo {
ss << "Adds a user to the system" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -334,6 +342,7 @@ namespace mongo {
}
if (!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(args.userName.getDB()),
ActionType::createUser)) {
return Status(ErrorCodes::Unauthorized,
@@ -341,7 +350,7 @@ namespace mongo {
args.userName.getDB());
}
- return checkAuthorizedToGrantRoles(authzSession, args.roles);
+ return checkAuthorizedToGrantRoles(txn, authzSession, args.roles);
}
bool run(OperationContext* txn, const string& dbname,
@@ -434,7 +443,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = requireAuthSchemaVersion26Final(authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -480,7 +489,8 @@ namespace mongo {
ss << "Used to update a user, for example to change its password" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -496,6 +506,7 @@ namespace mongo {
if (args.hasHashedPassword) {
if (!authzSession->isAuthorizedToChangeOwnPasswordAsUser(args.userName) &&
!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(args.userName.getDB()),
ActionType::changePassword)) {
return Status(ErrorCodes::Unauthorized,
@@ -507,6 +518,7 @@ namespace mongo {
if (args.hasCustomData) {
if (!authzSession->isAuthorizedToChangeOwnCustomDataAsUser(args.userName) &&
!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(args.userName.getDB()),
ActionType::changeCustomData)) {
return Status(ErrorCodes::Unauthorized,
@@ -519,13 +531,13 @@ namespace mongo {
// You don't know what roles you might be revoking, so require the ability to
// revoke any role in the system.
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forAnyNormalResource(), ActionType::revokeRole)) {
+ txn, ResourcePattern::forAnyNormalResource(), ActionType::revokeRole)) {
return Status(ErrorCodes::Unauthorized,
"In order to use updateUser to set roles array, must be "
"authorized to revoke any role in the system");
}
- return checkAuthorizedToGrantRoles(authzSession, args.roles);
+ return checkAuthorizedToGrantRoles(txn, authzSession, args.roles);
}
return Status::OK();
}
@@ -579,7 +591,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = requireAuthSchemaVersion26Final(authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -631,7 +643,8 @@ namespace mongo {
ss << "Drops a single user." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -646,7 +659,7 @@ namespace mongo {
}
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(userName.getDB()), ActionType::dropUser)) {
+ txn, ResourcePattern::forDatabaseName(userName.getDB()), ActionType::dropUser)) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to drop users from the " <<
userName.getDB() << " database");
@@ -668,7 +681,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -727,12 +740,13 @@ namespace mongo {
ss << "Drops all users for a single database." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(dbname), ActionType::dropUser)) {
+ txn, ResourcePattern::forDatabaseName(dbname), ActionType::dropUser)) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to drop users from the " <<
dbname << " database");
@@ -754,7 +768,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -802,7 +816,8 @@ namespace mongo {
ss << "Grants roles to a user." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -819,7 +834,7 @@ namespace mongo {
return status;
}
- return checkAuthorizedToGrantRoles(authzSession, roles);
+ return checkAuthorizedToGrantRoles(txn, authzSession, roles);
}
bool run(OperationContext* txn, const string& dbname,
@@ -836,7 +851,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -856,7 +871,7 @@ namespace mongo {
UserName userName(userNameString, dbname);
unordered_set<RoleName> userRoles;
- status = getCurrentUserRoles(authzManager, userName, &userRoles);
+ status = getCurrentUserRoles(txn, authzManager, userName, &userRoles);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -900,7 +915,8 @@ namespace mongo {
ss << "Revokes roles from a user." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -917,7 +933,7 @@ namespace mongo {
return status;
}
- return checkAuthorizedToRevokeRoles(authzSession, roles);
+ return checkAuthorizedToRevokeRoles(txn, authzSession, roles);
}
bool run(OperationContext* txn, const string& dbname,
@@ -934,7 +950,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -954,7 +970,7 @@ namespace mongo {
UserName userName(userNameString, dbname);
unordered_set<RoleName> userRoles;
- status = getCurrentUserRoles(authzManager, userName, &userRoles);
+ status = getCurrentUserRoles(txn, authzManager, userName, &userRoles);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1002,7 +1018,8 @@ namespace mongo {
ss << "Returns information about users." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1014,7 +1031,7 @@ namespace mongo {
if (args.allForDB) {
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(dbname), ActionType::viewUser)) {
+ txn, ResourcePattern::forDatabaseName(dbname), ActionType::viewUser)) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to view users from the " <<
dbname << " database");
@@ -1025,6 +1042,7 @@ namespace mongo {
continue; // Can always view users you are logged in as
}
if (!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(args.userNames[i].getDB()),
ActionType::viewUser)) {
return Status(ErrorCodes::Unauthorized,
@@ -1049,7 +1067,8 @@ namespace mongo {
return appendCommandStatus(result, status);
}
- status = requireAuthSchemaVersion26UpgradeOrFinal(getGlobalAuthorizationManager());
+ status = requireAuthSchemaVersion26UpgradeOrFinal(
+ txn, getGlobalAuthorizationManager());
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1068,7 +1087,7 @@ namespace mongo {
for (size_t i = 0; i < args.userNames.size(); ++i) {
BSONObj userDetails;
status = getGlobalAuthorizationManager()->getUserDescription(
- args.userNames[i], &userDetails);
+ txn, args.userNames[i], &userDetails);
if (status.code() == ErrorCodes::UserNotFound) {
continue;
}
@@ -1107,7 +1126,7 @@ namespace mongo {
AuthorizationManager* authzManager = getGlobalAuthorizationManager();
int authzVersion;
- Status status = authzManager->getAuthorizationVersion(&authzVersion);
+ Status status = authzManager->getAuthorizationVersion(txn, &authzVersion);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1149,7 +1168,8 @@ namespace mongo {
ss << "Adds a role to the system" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1163,6 +1183,7 @@ namespace mongo {
}
if (!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(args.roleName.getDB()),
ActionType::createRole)) {
return Status(ErrorCodes::Unauthorized,
@@ -1170,12 +1191,12 @@ namespace mongo {
args.roleName.getDB());
}
- status = checkAuthorizedToGrantRoles(authzSession, args.roles);
+ status = checkAuthorizedToGrantRoles(txn, authzSession, args.roles);
if (!status.isOK()) {
return status;
}
- return checkAuthorizedToGrantPrivileges(authzSession, args.privileges);
+ return checkAuthorizedToGrantPrivileges(txn, authzSession, args.privileges);
}
bool run(OperationContext* txn, const string& dbname,
@@ -1252,7 +1273,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = requireAuthSchemaVersion26Final(authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1294,7 +1315,8 @@ namespace mongo {
ss << "Used to update a role" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1310,18 +1332,18 @@ namespace mongo {
// You don't know what roles or privileges you might be revoking, so require the ability
// to revoke any role (or privilege) in the system.
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forAnyNormalResource(), ActionType::revokeRole)) {
+ txn, ResourcePattern::forAnyNormalResource(), ActionType::revokeRole)) {
return Status(ErrorCodes::Unauthorized,
"updateRole command required the ability to revoke any role in the "
"system");
}
- status = checkAuthorizedToGrantRoles(authzSession, args.roles);
+ status = checkAuthorizedToGrantRoles(txn, authzSession, args.roles);
if (!status.isOK()) {
return status;
}
- return checkAuthorizedToGrantPrivileges(authzSession, args.privileges);
+ return checkAuthorizedToGrantPrivileges(txn, authzSession, args.privileges);
}
bool run(OperationContext* txn, const string& dbname,
@@ -1369,7 +1391,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = requireAuthSchemaVersion26Final(authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1424,7 +1446,8 @@ namespace mongo {
ss << "Grants privileges to a role" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1442,7 +1465,7 @@ namespace mongo {
return status;
}
- return checkAuthorizedToGrantPrivileges(authzSession, privileges);
+ return checkAuthorizedToGrantPrivileges(txn, authzSession, privileges);
}
bool run(OperationContext* txn, const string& dbname,
@@ -1459,7 +1482,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1560,7 +1583,8 @@ namespace mongo {
ss << "Revokes privileges from a role" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1578,7 +1602,7 @@ namespace mongo {
return status;
}
- return checkAuthorizedToRevokePrivileges(authzSession, privileges);
+ return checkAuthorizedToRevokePrivileges(txn, authzSession, privileges);
}
bool run(OperationContext* txn, const string& dbname,
@@ -1595,7 +1619,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1698,7 +1722,8 @@ namespace mongo {
ss << "Grants roles to another role." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1715,7 +1740,7 @@ namespace mongo {
return status;
}
- return checkAuthorizedToGrantRoles(authzSession, roles);
+ return checkAuthorizedToGrantRoles(txn, authzSession, roles);
}
bool run(OperationContext* txn, const string& dbname,
@@ -1755,7 +1780,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = requireAuthSchemaVersion26Final(authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1817,7 +1842,8 @@ namespace mongo {
ss << "Revokes roles from another role." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1834,7 +1860,7 @@ namespace mongo {
return status;
}
- return checkAuthorizedToRevokeRoles(authzSession, roles);
+ return checkAuthorizedToRevokeRoles(txn, authzSession, roles);
}
bool run(OperationContext* txn, const string& dbname,
@@ -1851,7 +1877,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1933,7 +1959,8 @@ namespace mongo {
"removed from some user/roles but otherwise still exists."<< endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -1948,7 +1975,7 @@ namespace mongo {
}
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(roleName.getDB()), ActionType::dropRole)) {
+ txn, ResourcePattern::forDatabaseName(roleName.getDB()), ActionType::dropRole)) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to drop roles from the " <<
roleName.getDB() << " database");
@@ -1970,7 +1997,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- Status status = requireAuthSchemaVersion26Final(authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -2111,12 +2138,13 @@ namespace mongo {
"exist." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(dbname), ActionType::dropRole)) {
+ txn, ResourcePattern::forDatabaseName(dbname), ActionType::dropRole)) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to drop roles from the " <<
dbname << " database");
@@ -2146,7 +2174,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = requireAuthSchemaVersion26Final(authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -2243,7 +2271,8 @@ namespace mongo {
ss << "Returns information about roles." << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -2255,7 +2284,7 @@ namespace mongo {
if (args.allForDB) {
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(dbname), ActionType::viewRole)) {
+ txn, ResourcePattern::forDatabaseName(dbname), ActionType::viewRole)) {
return Status(ErrorCodes::Unauthorized,
str::stream() << "Not authorized to view roles from the " <<
dbname << " database");
@@ -2267,6 +2296,7 @@ namespace mongo {
}
if (!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(args.roleNames[i].getDB()),
ActionType::viewRole)) {
return Status(ErrorCodes::Unauthorized,
@@ -2292,7 +2322,8 @@ namespace mongo {
return appendCommandStatus(result, status);
}
- status = requireAuthSchemaVersion26UpgradeOrFinal(getGlobalAuthorizationManager());
+ status = requireAuthSchemaVersion26UpgradeOrFinal(
+ txn, getGlobalAuthorizationManager());
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -2348,12 +2379,13 @@ namespace mongo {
ss << "Invalidates the in-memory cache of user information" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::invalidateUserCache)) {
+ txn, ResourcePattern::forClusterResource(), ActionType::invalidateUserCache)) {
return Status(ErrorCodes::Unauthorized, "Not authorized to invalidate user cache");
}
return Status::OK();
@@ -2392,12 +2424,13 @@ namespace mongo {
ss << "internal" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::internal)) {
+ txn, ResourcePattern::forClusterResource(), ActionType::internal)) {
return Status(ErrorCodes::Unauthorized, "Not authorized to get cache generation");
}
return Status::OK();
@@ -2447,7 +2480,8 @@ namespace mongo {
ss << "Internal command used by mongorestore for updating user/role data" << endl;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
auth::MergeAuthzCollectionsArgs args;
@@ -2467,13 +2501,14 @@ namespace mongo {
actions.addAction(ActionType::dropRole);
}
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forAnyNormalResource(), actions)) {
+ txn, ResourcePattern::forAnyNormalResource(), actions)) {
return Status(ErrorCodes::Unauthorized,
"Not authorized to update user/role data using _mergeAuthzCollections"
" command");
}
if (!args.usersCollName.empty() &&
!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(args.usersCollName)),
ActionType::find)) {
return Status(ErrorCodes::Unauthorized,
@@ -2482,6 +2517,7 @@ namespace mongo {
}
if (!args.rolesCollName.empty() &&
!authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(args.rolesCollName)),
ActionType::find)) {
return Status(ErrorCodes::Unauthorized,
@@ -2840,7 +2876,7 @@ namespace mongo {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = requireAuthSchemaVersion26Final(authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -2881,13 +2917,14 @@ namespace mongo {
ss << "Upgrades the auth data storage schema";
}
- Status CmdAuthSchemaUpgrade::checkAuthForCommand(ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj) {
+ Status CmdAuthSchemaUpgrade::checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
if (!authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::authSchemaUpgrade)) {
+ txn, ResourcePattern::forClusterResource(), ActionType::authSchemaUpgrade)) {
return Status(ErrorCodes::Unauthorized,
"Not authorized to run authSchemaUpgrade command.");
}
diff --git a/src/mongo/db/commands/user_management_commands.h b/src/mongo/db/commands/user_management_commands.h
index f9350f768ca..448950eb5ed 100644
--- a/src/mongo/db/commands/user_management_commands.h
+++ b/src/mongo/db/commands/user_management_commands.h
@@ -42,7 +42,8 @@ namespace mongo {
virtual bool adminOnly() const;
virtual void help(std::stringstream& ss) const;
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj);
};
diff --git a/src/mongo/db/commands/validate.cpp b/src/mongo/db/commands/validate.cpp
index 28d06c9ae05..9b539a8b954 100644
--- a/src/mongo/db/commands/validate.cpp
+++ b/src/mongo/db/commands/validate.cpp
@@ -75,7 +75,7 @@ namespace mongo {
MONGO_TLOG(0) << "CMD: validate " << ns << endl;
}
- Client::ReadContext ctx(ns_string.ns());
+ Client::ReadContext ctx(txn, ns_string.ns());
Database* db = ctx.ctx().db();
if ( !db ) {
diff --git a/src/mongo/db/commands/write_commands/batch_executor.cpp b/src/mongo/db/commands/write_commands/batch_executor.cpp
index a6332a50288..b147446a93d 100644
--- a/src/mongo/db/commands/write_commands/batch_executor.cpp
+++ b/src/mongo/db/commands/write_commands/batch_executor.cpp
@@ -902,7 +902,7 @@ namespace mongo {
}
invariant(!_context.get());
- _writeLock.reset(new Lock::DBWrite(request->getNS()));
+ _writeLock.reset(new Lock::DBWrite(txn->lockState(), request->getNS()));
if (!checkIsMasterForCollection(request->getNS(), result)) {
return false;
}
@@ -1087,7 +1087,7 @@ namespace mongo {
}
///////////////////////////////////////////
- Lock::DBWrite writeLock( nsString.ns() );
+ Lock::DBWrite writeLock(txn->lockState(), nsString.ns());
///////////////////////////////////////////
if ( !checkShardVersion( &shardingState, *updateItem.getRequest(), result ) )
@@ -1144,7 +1144,7 @@ namespace mongo {
}
///////////////////////////////////////////
- Lock::DBWrite writeLock( nss.ns() );
+ Lock::DBWrite writeLock(txn->lockState(), nss.ns());
///////////////////////////////////////////
// Check version once we're locked
diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp
index c9b77e1b831..9f14dec2bb2 100644
--- a/src/mongo/db/commands/write_commands/write_commands.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands.cpp
@@ -82,11 +82,14 @@ namespace mongo {
bool WriteCmd::isWriteCommandForConfigServer() const { return false; }
- Status WriteCmd::checkAuthForCommand( ClientBasic* client,
+ Status WriteCmd::checkAuthForCommand( OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj ) {
- Status status( auth::checkAuthForWriteCommand( client->getAuthorizationSession(),
+ Status status( auth::checkAuthForWriteCommand(
+ txn,
+ client->getAuthorizationSession(),
_writeType,
NamespaceString( parseNs( dbname, cmdObj ) ),
cmdObj ));
diff --git a/src/mongo/db/commands/write_commands/write_commands.h b/src/mongo/db/commands/write_commands/write_commands.h
index c5f5da37cac..570eca9ba4d 100644
--- a/src/mongo/db/commands/write_commands/write_commands.h
+++ b/src/mongo/db/commands/write_commands/write_commands.h
@@ -65,7 +65,8 @@ namespace mongo {
virtual bool isWriteCommandForConfigServer() const;
- virtual Status checkAuthForCommand( ClientBasic* client,
+ virtual Status checkAuthForCommand( OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj );
diff --git a/src/mongo/db/commands/write_commands/write_commands_common.cpp b/src/mongo/db/commands/write_commands/write_commands_common.cpp
index 72c132ae1c0..e2a77d85863 100644
--- a/src/mongo/db/commands/write_commands/write_commands_common.cpp
+++ b/src/mongo/db/commands/write_commands/write_commands_common.cpp
@@ -44,7 +44,8 @@ namespace auth {
using std::string;
using std::vector;
- Status checkAuthForWriteCommand( AuthorizationSession* authzSession,
+ Status checkAuthForWriteCommand( OperationContext* txn,
+ AuthorizationSession* authzSession,
BatchedCommandRequest::BatchType cmdType,
const NamespaceString& cmdNSS,
const BSONObj& cmdObj ) {
@@ -89,8 +90,9 @@ namespace auth {
ActionType::remove ) );
}
- if ( authzSession->isAuthorizedForPrivileges( privileges ) )
+ if (authzSession->isAuthorizedForPrivileges(txn, privileges)) {
return Status::OK();
+ }
return Status( ErrorCodes::Unauthorized, "unauthorized" );
}
diff --git a/src/mongo/db/commands/write_commands/write_commands_common.h b/src/mongo/db/commands/write_commands/write_commands_common.h
index a1fe6bc9772..bc0e1f0be8e 100644
--- a/src/mongo/db/commands/write_commands/write_commands_common.h
+++ b/src/mongo/db/commands/write_commands/write_commands_common.h
@@ -38,9 +38,13 @@
*/
namespace mongo {
+
+ class OperationContext;
+
namespace auth {
- Status checkAuthForWriteCommand( AuthorizationSession* authzSession,
+ Status checkAuthForWriteCommand( OperationContext* txn,
+ AuthorizationSession* authzSession,
BatchedCommandRequest::BatchType cmdType,
const NamespaceString& cmdNSS,
const BSONObj& cmdObj );
diff --git a/src/mongo/db/d_concurrency.cpp b/src/mongo/db/d_concurrency.cpp
index 7f84d776bb1..15ab51528fe 100644
--- a/src/mongo/db/d_concurrency.cpp
+++ b/src/mongo/db/d_concurrency.cpp
@@ -583,12 +583,12 @@ namespace mongo {
lockNestable(nested);
}
- Lock::DBWrite::DBWrite( const StringData& ns )
+ Lock::DBWrite::DBWrite(LockState* lockState, const StringData& ns)
: ScopedLock( 'w' ), _what(ns.toString()), _nested(false) {
lockDB( _what );
}
- Lock::DBRead::DBRead( const StringData& ns )
+ Lock::DBRead::DBRead(LockState* lockState, const StringData& ns)
: ScopedLock( 'r' ), _what(ns.toString()), _nested(false) {
lockDB( _what );
}
diff --git a/src/mongo/db/d_concurrency.h b/src/mongo/db/d_concurrency.h
index f99cb46184f..8359f23614d 100644
--- a/src/mongo/db/d_concurrency.h
+++ b/src/mongo/db/d_concurrency.h
@@ -112,6 +112,8 @@ namespace mongo {
virtual void _tempRelease() = 0;
virtual void _relock() = 0;
+ LockState* _lockState;
+
private:
class ParallelBatchWriterSupport : boost::noncopyable {
@@ -183,7 +185,7 @@ namespace mongo {
void _relock();
public:
- DBWrite(const StringData& dbOrNs);
+ DBWrite(LockState* lockState, const StringData& dbOrNs);
virtual ~DBWrite();
private:
@@ -207,7 +209,7 @@ namespace mongo {
void _relock();
public:
- DBRead(const StringData& dbOrNs);
+ DBRead(LockState* lockState, const StringData& dbOrNs);
virtual ~DBRead();
private:
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index cd9a98b3a7c..93408e92a23 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -752,14 +752,17 @@ namespace mongo {
#ifndef _WIN32
mongo::signalForkSuccess();
#endif
+ {
+ OperationContextImpl txn;
- if(getGlobalAuthorizationManager()->isAuthEnabled()) {
- // open admin db in case we need to use it later. TODO this is not the right way to
- // resolve this.
- Client::WriteContext c("admin", storageGlobalParams.dbpath);
- }
+ if (getGlobalAuthorizationManager()->isAuthEnabled()) {
+ // open admin db in case we need to use it later. TODO this is not the right way to
+ // resolve this.
+ Client::WriteContext ctx(&txn, "admin");
+ }
- authindex::configureSystemIndexes("admin");
+ authindex::configureSystemIndexes(&txn, "admin");
+ }
getDeleter()->startWorkers();
diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp
index 3fa6918ad50..fa14f002391 100644
--- a/src/mongo/db/dbcommands.cpp
+++ b/src/mongo/db/dbcommands.cpp
@@ -321,7 +321,8 @@ namespace mongo {
virtual bool isWriteCommandForConfigServer() const { return true; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
@@ -330,6 +331,7 @@ namespace mongo {
// If you just want to get the current profiling level you can do so with just
// read access to system.profile, even if you can't change the profiling level.
if (authzSession->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(dbname,
"system.profile")),
ActionType::find)) {
@@ -338,7 +340,7 @@ namespace mongo {
}
if (authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forDatabaseName(dbname), ActionType::enableProfiler)) {
+ txn, ResourcePattern::forDatabaseName(dbname), ActionType::enableProfiler)) {
return Status::OK();
}
@@ -353,7 +355,7 @@ namespace mongo {
// Needs to be locked exclusively, because creates the system.profile collection
// in the local database.
//
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(dbname);
BSONElement e = cmdObj.firstElement();
@@ -403,7 +405,7 @@ namespace mongo {
// This doesn't look like it requires exclusive DB lock, because it uses its own diag
// locking, but originally the lock was set to be WRITE, so preserving the behaviour.
//
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(dbname);
int was = _diaglog.setLevel( cmdObj.firstElement().numberInt() );
@@ -457,7 +459,7 @@ namespace mongo {
return false;
}
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(nsToDrop);
Database* db = ctx.db();
@@ -528,7 +530,7 @@ namespace mongo {
// This acquires the DB read lock
//
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
string err;
int errCode;
@@ -572,22 +574,23 @@ namespace mongo {
help << "create a collection explicitly\n"
"{ create: <ns>[, capped: <bool>, size: <collSizeInBytes>, max: <nDocs>] }";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
if (cmdObj["capped"].trueValue()) {
if (!authzSession->isAuthorizedForActionsOnResource(
- parseResourcePattern(dbname, cmdObj), ActionType::convertToCapped)) {
+ txn, parseResourcePattern(dbname, cmdObj), ActionType::convertToCapped)) {
return Status(ErrorCodes::Unauthorized, "unauthorized");
}
}
// ActionType::createCollection or ActionType::insert are both acceptable
if (authzSession->isAuthorizedForActionsOnResource(
- parseResourcePattern(dbname, cmdObj), ActionType::createCollection) ||
+ txn, parseResourcePattern(dbname, cmdObj), ActionType::createCollection) ||
authzSession->isAuthorizedForActionsOnResource(
- parseResourcePattern(dbname, cmdObj), ActionType::insert)) {
+ txn, parseResourcePattern(dbname, cmdObj), ActionType::insert)) {
return Status::OK();
}
@@ -621,7 +624,7 @@ namespace mongo {
!options["capped"].trueValue() || options["size"].isNumber() ||
options.hasField("$nExtents"));
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(ns);
// Create collection.
@@ -667,7 +670,7 @@ namespace mongo {
totalSize += size;
{
- Client::ReadContext rc( *i + ".system.namespaces" );
+ Client::ReadContext rc(txn, *i + ".system.namespaces");
b.appendBool( "empty", rc.ctx().db()->isEmpty() );
}
@@ -695,7 +698,7 @@ namespace mongo {
b.append( "sizeOnDisk" , (double)1.0 );
{
- Client::ReadContext ctx( name );
+ Client::ReadContext ctx(txn, name);
b.appendBool( "empty", ctx.ctx().db()->isEmpty() );
}
@@ -812,7 +815,7 @@ namespace mongo {
// Check shard version at startup.
// This will throw before we've done any work if shard version is outdated
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Collection* coll = ctx.ctx().db()->getCollection(ns);
CanonicalQuery* cq;
@@ -920,7 +923,7 @@ namespace mongo {
BSONObj keyPattern = jsobj.getObjectField( "keyPattern" );
bool estimate = jsobj["estimate"].trueValue();
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
@@ -1037,7 +1040,7 @@ namespace mongo {
bool run(OperationContext* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
const string ns = dbname + "." + jsobj.firstElement().valuestr();
- Client::ReadContext cx( ns );
+ Client::ReadContext cx(txn, ns);
Database* db = cx.ctx().db();
Collection* collection = db->getCollection( ns );
if ( !collection ) {
@@ -1114,7 +1117,7 @@ namespace mongo {
bool run(OperationContext* txn, const string& dbname, BSONObj& jsobj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
const string ns = dbname + "." + jsobj.firstElement().valuestr();
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx( ns );
Collection* coll = ctx.db()->getCollection( ns );
@@ -1244,7 +1247,7 @@ namespace mongo {
const string ns = parseNs(dbname, jsobj);
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Database* d = ctx.ctx().db();
d->getStats( &result, scale );
@@ -1401,7 +1404,7 @@ namespace mongo {
fieldIsPresent,
parsedUserNames);
- Status status = _checkAuthorization(c, &client, dbname, cmdObj, fromRepl);
+ Status status = _checkAuthorization(txn, c, &client, dbname, cmdObj, fromRepl);
if (!status.isOK()) {
appendCommandStatus(result, status);
return;
diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp
index 767bf537d1f..1a2e0c4652f 100644
--- a/src/mongo/db/dbhelpers.cpp
+++ b/src/mongo/db/dbhelpers.cpp
@@ -297,10 +297,12 @@ namespace mongo {
return kpBuilder.obj();
}
- bool findShardKeyIndexPattern( const string& ns,
- const BSONObj& shardKeyPattern,
- BSONObj* indexPattern ) {
- Client::ReadContext context( ns );
+ static bool findShardKeyIndexPattern(OperationContext* txn,
+ const string& ns,
+ const BSONObj& shardKeyPattern,
+ BSONObj* indexPattern ) {
+
+ Client::ReadContext context(txn, ns);
Collection* collection = context.ctx().db()->getCollection( ns );
if ( !collection )
return false;
@@ -332,7 +334,8 @@ namespace mongo {
// The IndexChunk has a keyPattern that may apply to more than one index - we need to
// select the index and get the full index keyPattern here.
BSONObj indexKeyPatternDoc;
- if ( !findShardKeyIndexPattern( ns,
+ if ( !findShardKeyIndexPattern( txn,
+ ns,
range.keyPattern,
&indexKeyPatternDoc ) )
{
@@ -366,7 +369,7 @@ namespace mongo {
while ( 1 ) {
// Scoping for write lock.
{
- Client::WriteContext ctx(ns);
+ Client::WriteContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( txn, ns );
if ( !collection )
break;
@@ -476,7 +479,9 @@ namespace mongo {
// Used by migration clone step
// TODO: Cannot hook up quite yet due to _trackerLocks in shared migration code.
- Status Helpers::getLocsInRange( const KeyRange& range,
+ // TODO: This function is not used outside of tests
+ Status Helpers::getLocsInRange( OperationContext* txn,
+ const KeyRange& range,
long long maxChunkSizeBytes,
set<DiskLoc>* locs,
long long* numDocs,
@@ -486,7 +491,7 @@ namespace mongo {
*estChunkSizeBytes = 0;
*numDocs = 0;
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
if ( !collection ) return Status( ErrorCodes::NamespaceNotFound, ns );
diff --git a/src/mongo/db/dbhelpers.h b/src/mongo/db/dbhelpers.h
index a5e9947f918..2cba18345d5 100644
--- a/src/mongo/db/dbhelpers.h
+++ b/src/mongo/db/dbhelpers.h
@@ -188,7 +188,8 @@ namespace mongo {
* @return IndexNotFound if the index pattern doesn't match any indexes
* @return InvalidLength if the estimated size exceeds maxChunkSizeBytes
*/
- static Status getLocsInRange( const KeyRange& range,
+ static Status getLocsInRange( OperationContext* txn,
+ const KeyRange& range,
long long maxChunkSizeBytes,
std::set<DiskLoc>* locs,
long long* numDocs,
diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp
index 26a0758ed67..66fbfeeebcd 100644
--- a/src/mongo/db/dbwebserver.cpp
+++ b/src/mongo/db/dbwebserver.cpp
@@ -99,13 +99,17 @@ namespace mongo {
ss << "</pre>";
}
- void _authorizePrincipal(const UserName& userName) {
- Status status = cc().getAuthorizationSession()->addAndAuthorizeUser(userName);
+ void _authorizePrincipal(OperationContext* txn, const UserName& userName) {
+ Status status = cc().getAuthorizationSession()->addAndAuthorizeUser(txn, userName);
uassertStatusOK(status);
}
- bool allowed( const char * rq , vector<string>& headers, const SockAddr &from ) {
- if ( from.isLocalHost() || !_webUsers->haveAdminUsers() ) {
+ bool allowed(OperationContext* txn,
+ const char * rq,
+ vector<string>& headers,
+ const SockAddr &from) {
+
+ if ( from.isLocalHost() || !_webUsers->haveAdminUsers(txn) ) {
// TODO(spencer): should the above check use "&&" not "||"? Currently this is much
// more permissive than the server's localhost auth bypass.
cc().getAuthorizationSession()->grantInternalAuthorization();
@@ -131,7 +135,7 @@ namespace mongo {
User* user;
AuthorizationManager& authzManager =
cc().getAuthorizationSession()->getAuthorizationManager();
- Status status = authzManager.acquireUser(userName, &user);
+ Status status = authzManager.acquireUser(txn, userName, &user);
if (!status.isOK()) {
if (status.code() != ErrorCodes::UserNotFound) {
uasserted(17051, status.reason());
@@ -159,7 +163,7 @@ namespace mongo {
string r1 = md5simpledigest( r.str() );
if ( r1 == parms["response"] ) {
- _authorizePrincipal(userName);
+ _authorizePrincipal(txn, userName);
return true;
}
}
@@ -191,7 +195,7 @@ namespace mongo {
if ( url.size() > 1 ) {
- if ( ! allowed( rq , headers, from ) ) {
+ if (!allowed(txn.get(), rq, headers, from)) {
responseCode = 401;
headers.push_back( "Content-Type: text/plain;charset=utf-8" );
responseMsg = "not allowed\n";
@@ -240,7 +244,7 @@ namespace mongo {
// generate home page
- if ( ! allowed( rq , headers, from ) ) {
+ if (!allowed(txn.get(), rq, headers, from)) {
responseCode = 401;
headers.push_back( "Content-Type: text/plain;charset=utf-8" );
responseMsg = "not allowed\n";
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index 5446d2b5c2d..ca10066c960 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -116,7 +116,7 @@ namespace mongo {
string collName = collElt.String();
// Need a context to get the actual Collection*
- Client::ReadContext ctx(dbname);
+ Client::ReadContext ctx(txn, dbname);
// Make sure the collection is valid.
Database* db = ctx.ctx().db();
diff --git a/src/mongo/db/fts/fts_command.cpp b/src/mongo/db/fts/fts_command.cpp
index c95a6c52bb1..128b5a9f255 100644
--- a/src/mongo/db/fts/fts_command.cpp
+++ b/src/mongo/db/fts/fts_command.cpp
@@ -92,7 +92,7 @@ namespace mongo {
projection = cmdObj["project"].Obj();
}
- return _run( dbname, cmdObj, options,
+ return _run( txn, dbname, cmdObj, options,
ns, search, language, limit, filter, projection, errmsg, result );
}
diff --git a/src/mongo/db/fts/fts_command.h b/src/mongo/db/fts/fts_command.h
index 4c0ced7efea..7f6b4d7bc4d 100644
--- a/src/mongo/db/fts/fts_command.h
+++ b/src/mongo/db/fts/fts_command.h
@@ -40,6 +40,8 @@
namespace mongo {
+ class OperationContext;
+
namespace fts {
class FTSCommand : public Command {
@@ -64,7 +66,8 @@ namespace mongo {
bool fromRepl);
protected:
- bool _run( const std::string& dbName,
+ bool _run( OperationContext* txn,
+ const std::string& dbName,
BSONObj& cmdObj,
int cmdOptions,
const std::string& ns,
diff --git a/src/mongo/db/fts/fts_command_mongod.cpp b/src/mongo/db/fts/fts_command_mongod.cpp
index 230c6d00fb4..c422d9d8863 100644
--- a/src/mongo/db/fts/fts_command_mongod.cpp
+++ b/src/mongo/db/fts/fts_command_mongod.cpp
@@ -54,7 +54,8 @@ namespace mongo {
* @param fromRepl
* @return true if successful, false otherwise
*/
- bool FTSCommand::_run(const string& dbname,
+ bool FTSCommand::_run(OperationContext* txn,
+ const string& dbname,
BSONObj& cmdObj,
int cmdOptions,
const string& ns,
@@ -92,7 +93,7 @@ namespace mongo {
projBob.appendElements(sortSpec);
BSONObj projObj = projBob.obj();
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
CanonicalQuery* cq;
Status canonicalizeStatus =
diff --git a/src/mongo/db/fts/fts_command_mongos.cpp b/src/mongo/db/fts/fts_command_mongos.cpp
index 0c0f09e957b..df152856e2d 100644
--- a/src/mongo/db/fts/fts_command_mongos.cpp
+++ b/src/mongo/db/fts/fts_command_mongos.cpp
@@ -54,7 +54,8 @@ namespace mongo {
double score;
};
- bool FTSCommand::_run(const string& dbName,
+ bool FTSCommand::_run(OperationContext* txn,
+ const string& dbName,
BSONObj& cmdObj,
int cmdOptions,
const string& ns,
diff --git a/src/mongo/db/geo/haystack.cpp b/src/mongo/db/geo/haystack.cpp
index b5c61765b79..644c2ba60d2 100644
--- a/src/mongo/db/geo/haystack.cpp
+++ b/src/mongo/db/geo/haystack.cpp
@@ -71,7 +71,7 @@ namespace mongo {
bool run(OperationContext* txn, const string& dbname, BSONObj& cmdObj, int,
string& errmsg, BSONObjBuilder& result, bool fromRepl) {
const string ns = dbname + "." + cmdObj.firstElement().valuestr();
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(txn, ns);
Database* db = ctx.ctx().db();
if ( !db ) {
diff --git a/src/mongo/db/index_builder.cpp b/src/mongo/db/index_builder.cpp
index 6014608300c..1e97c3da193 100644
--- a/src/mongo/db/index_builder.cpp
+++ b/src/mongo/db/index_builder.cpp
@@ -55,6 +55,8 @@ namespace mongo {
void IndexBuilder::run() {
LOG(2) << "IndexBuilder building index " << _index;
+ OperationContextImpl txn;
+
Client::initThread(name().c_str());
Lock::ParallelBatchWriterMode::iAmABatchParticipant();
@@ -62,8 +64,7 @@ namespace mongo {
cc().curop()->reset(HostAndPort(), dbInsert);
NamespaceString ns(_index["ns"].String());
- Client::WriteContext ctx(ns.getSystemIndexesCollection());
- OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns.getSystemIndexesCollection());
Database* db = dbHolder().get(ns.db().toString(), storageGlobalParams.dbpath);
diff --git a/src/mongo/db/index_rebuilder.cpp b/src/mongo/db/index_rebuilder.cpp
index 3e45d143cab..b9c89ab8b04 100644
--- a/src/mongo/db/index_rebuilder.cpp
+++ b/src/mongo/db/index_rebuilder.cpp
@@ -63,7 +63,9 @@ namespace mongo {
for (std::vector<std::string>::const_iterator dbName = dbNames.begin();
dbName < dbNames.end();
dbName++) {
- Client::ReadContext ctx(*dbName);
+ OperationContextImpl txn;
+ Client::ReadContext ctx(&txn, *dbName);
+
Database* db = ctx.ctx().db();
db->getDatabaseCatalogEntry()->getCollectionNamespaces(&collNames);
}
@@ -88,10 +90,11 @@ namespace mongo {
LOG(3) << "IndexRebuilder::checkNS: " << ns;
+ OperationContextImpl txn; // XXX???
+
// This write lock is held throughout the index building process
// for this namespace.
- Client::WriteContext ctx(ns);
- OperationContextImpl txn; // XXX???
+ Client::WriteContext ctx(&txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
if ( collection == NULL )
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 613165ff4d2..373e7f2b3ca 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -121,8 +121,9 @@ namespace mongo {
QueryMessage q(d);
BSONObjBuilder b;
+ OperationContextImpl txn;
const bool isAuthorized = cc().getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::inprog);
+ &txn, ResourcePattern::forClusterResource(), ActionType::inprog);
audit::logInProgAuthzCheck(
&cc(), q.query, isAuthorized ? ErrorCodes::OK : ErrorCodes::Unauthorized);
@@ -182,8 +183,10 @@ namespace mongo {
DbMessage d(m);
QueryMessage q(d);
BSONObj obj;
+
+ OperationContextImpl txn;
const bool isAuthorized = cc().getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::killop);
+ &txn, ResourcePattern::forClusterResource(), ActionType::killop);
audit::logKillOpAuthzCheck(&cc(),
q.query,
isAuthorized ? ErrorCodes::OK : ErrorCodes::Unauthorized);
@@ -210,8 +213,10 @@ namespace mongo {
bool _unlockFsync();
void unlockFsync(const char *ns, Message& m, DbResponse &dbresponse) {
BSONObj obj;
+
+ OperationContextImpl txn;
const bool isAuthorized = cc().getAuthorizationSession()->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::unlock);
+ &txn, ResourcePattern::forClusterResource(), ActionType::unlock);
audit::logFsyncUnlockAuthzCheck(
&cc(), isAuthorized ? ErrorCodes::OK : ErrorCodes::Unauthorized);
if (!isAuthorized) {
@@ -249,7 +254,7 @@ namespace mongo {
if (!ns.isCommand()) {
// Auth checking for Commands happens later.
Client* client = &cc();
- Status status = client->getAuthorizationSession()->checkAuthForQuery(ns, q.query);
+ Status status = client->getAuthorizationSession()->checkAuthForQuery(txn, ns, q.query);
audit::logQueryAuthzCheck(client, ns, q.query, status.code());
uassertStatusOK(status);
}
@@ -341,7 +346,7 @@ namespace mongo {
Client& c = cc();
if (!c.isGod())
- c.getAuthorizationSession()->startRequest();
+ c.getAuthorizationSession()->startRequest(txn);
if ( op == dbQuery ) {
if( strstr(ns, ".$cmd") ) {
@@ -528,7 +533,7 @@ namespace mongo {
verify( n < 30000 );
}
- int found = CollectionCursorCache::eraseCursorGlobalIfAuthorized(n, (long long *) x);
+ int found = CollectionCursorCache::eraseCursorGlobalIfAuthorized(txn, n, (long long *) x);
if ( logger::globalLogDomain()->shouldLog(logger::LogSeverity::Debug(1)) || found != n ) {
LOG( found == n ? 1 : 0 ) << "killcursors: found " << found << " of " << n << endl;
@@ -581,7 +586,8 @@ namespace mongo {
bool multi = flags & UpdateOption_Multi;
bool broadcast = flags & UpdateOption_Broadcast;
- Status status = cc().getAuthorizationSession()->checkAuthForUpdate(ns,
+ Status status = cc().getAuthorizationSession()->checkAuthForUpdate(txn,
+ ns,
query,
toupdate,
upsert);
@@ -603,7 +609,7 @@ namespace mongo {
UpdateExecutor executor(&request, &op.debug());
uassertStatusOK(executor.prepare());
- Lock::DBWrite lk(ns.ns());
+ Lock::DBWrite lk(txn->lockState(), ns.ns());
// if this ever moves to outside of lock, need to adjust check
// Client::Context::_finishInit
@@ -630,7 +636,7 @@ namespace mongo {
verify( d.moreJSObjs() );
BSONObj pattern = d.nextJsObj();
- Status status = cc().getAuthorizationSession()->checkAuthForDelete(ns, pattern);
+ Status status = cc().getAuthorizationSession()->checkAuthForDelete(txn, ns, pattern);
audit::logDeleteAuthzCheck(&cc(), ns, pattern, status.code());
uassertStatusOK(status);
@@ -643,7 +649,7 @@ namespace mongo {
request.setUpdateOpLog(true);
DeleteExecutor executor(&request);
uassertStatusOK(executor.prepare());
- Lock::DBWrite lk(ns.ns());
+ Lock::DBWrite lk(txn->lockState(), ns.ns());
// if this ever moves to outside of lock, need to adjust check Client::Context::_finishInit
if ( ! broadcast && handlePossibleShardedMessage( m , 0 ) )
@@ -684,7 +690,7 @@ namespace mongo {
uassert( 16258, str::stream() << "Invalid ns [" << ns << "]", nsString.isValid() );
Status status = cc().getAuthorizationSession()->checkAuthForGetMore(
- nsString, cursorid);
+ txn, nsString, cursorid);
audit::logGetMoreAuthzCheck(&cc(), nsString, cursorid, status.code());
uassertStatusOK(status);
@@ -717,7 +723,7 @@ namespace mongo {
// because it may now be out of sync with the client's iteration state.
// SERVER-7952
// TODO Temporary code, see SERVER-4563 for a cleanup overview.
- CollectionCursorCache::eraseCursorGlobal( cursorid );
+ CollectionCursorCache::eraseCursorGlobal(txn, cursorid );
}
ex.reset( new AssertionException( e.getInfo().msg, e.getCode() ) );
ok = false;
@@ -875,12 +881,12 @@ namespace mongo {
// Check auth for insert (also handles checking if this is an index build and checks
// for the proper privileges in that case).
const NamespaceString nsString(ns);
- Status status = cc().getAuthorizationSession()->checkAuthForInsert(nsString, obj);
+ Status status = cc().getAuthorizationSession()->checkAuthForInsert(txn, nsString, obj);
audit::logInsertAuthzCheck(&cc(), nsString, obj, status.code());
uassertStatusOK(status);
}
- Lock::DBWrite lk(ns);
+ Lock::DBWrite lk(txn->lockState(), ns);
// CONCURRENCY TODO: is being read locked in big log sufficient here?
// writelock is used to synchronize stepdowns w/ writes
@@ -924,7 +930,7 @@ namespace mongo {
local database does NOT count except for rsoplog collection.
used to set the hasData field on replset heartbeat command response
*/
- bool replHasDatabases() {
+ bool replHasDatabases(OperationContext* txn) {
vector<string> names;
getDatabaseNames(names);
if( names.size() >= 2 ) return true;
@@ -933,7 +939,7 @@ namespace mongo {
return true;
// we have a local database. return true if oplog isn't empty
{
- Lock::DBRead lk(repl::rsoplog);
+ Lock::DBRead lk(txn->lockState(), repl::rsoplog);
BSONObj o;
if( Helpers::getFirst(repl::rsoplog, o) )
return true;
@@ -1002,7 +1008,9 @@ namespace {
}
void DBDirectClient::killCursor( long long id ) {
- CollectionCursorCache::eraseCursorGlobal( id );
+ // The killCursor command on the DB client is only used by sharding,
+ // so no need to have it for MongoD.
+ verify(!"killCursor should not be used in MongoD");
}
HostAndPort DBDirectClient::_clientHost = HostAndPort( "0.0.0.0" , 0 );
@@ -1013,7 +1021,9 @@ namespace {
<< " to zero in query: " << query << endl;
skip = 0;
}
- Lock::DBRead lk( ns );
+
+ OperationContextImpl txn;
+ Lock::DBRead lk(txn.lockState(), ns);
string errmsg;
int errCode;
long long res = runCount( ns, _countCmd( ns , query , options , limit , skip ) , errmsg, errCode );
diff --git a/src/mongo/db/instance.h b/src/mongo/db/instance.h
index ff8e655b608..b7039b30c4c 100644
--- a/src/mongo/db/instance.h
+++ b/src/mongo/db/instance.h
@@ -79,7 +79,7 @@ namespace mongo {
/* returns true if there is no data on this server. useful when starting replication.
local database does NOT count.
*/
- bool replHasDatabases();
+ bool replHasDatabases(OperationContext* txn);
/**
* Embedded calls to the local server using the DBClientBase API without going over the network.
diff --git a/src/mongo/db/introspect.cpp b/src/mongo/db/introspect.cpp
index 79894bf88c7..ff9004ab6e8 100644
--- a/src/mongo/db/introspect.cpp
+++ b/src/mongo/db/introspect.cpp
@@ -137,7 +137,7 @@ namespace {
try {
// NOTE: It's kind of weird that we lock the op's namespace, but have to for now since
// we're sometimes inside the lock already
- Lock::DBWrite lk( currentOp.getNS() );
+ Lock::DBWrite lk(txn->lockState(), currentOp.getNS() );
if (dbHolder()._isLoaded(nsToDatabase(currentOp.getNS()), storageGlobalParams.dbpath)) {
Client::Context cx(currentOp.getNS(), storageGlobalParams.dbpath, false);
_profile(txn, c, cx.db(),
diff --git a/src/mongo/db/pipeline/document_source_cursor.cpp b/src/mongo/db/pipeline/document_source_cursor.cpp
index 87131cbc17b..70ac51d2000 100644
--- a/src/mongo/db/pipeline/document_source_cursor.cpp
+++ b/src/mongo/db/pipeline/document_source_cursor.cpp
@@ -78,7 +78,7 @@ namespace mongo {
// We have already validated the sharding version when we constructed the Runner
// so we shouldn't check it again.
- Lock::DBRead lk(_ns);
+ Lock::DBRead lk(pExpCtx->opCtx->lockState(), _ns);
Client::Context ctx(_ns, storageGlobalParams.dbpath, /*doVersion=*/false);
_runner->restoreState(pExpCtx->opCtx);
@@ -199,7 +199,7 @@ namespace {
Status explainStatus(ErrorCodes::InternalError, "");
scoped_ptr<TypeExplain> plan;
{
- Lock::DBRead lk(_ns);
+ Lock::DBRead lk(pExpCtx->opCtx->lockState(), _ns);
Client::Context ctx(_ns, storageGlobalParams.dbpath, /*doVersion=*/false);
massert(17392, "No _runner. Were we disposed before explained?",
_runner);
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index df8a6716987..4409b899c4c 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -64,7 +64,7 @@ namespace {
}
bool isCapped(const NamespaceString& ns) {
- Client::ReadContext ctx(ns.ns());
+ Client::ReadContext ctx(_ctx->opCtx, ns.ns());
Collection* collection = ctx.ctx().db()->getCollection(ns);
return collection && collection->isCapped();
}
diff --git a/src/mongo/db/prefetch.cpp b/src/mongo/db/prefetch.cpp
index 7634b2d862a..36ad06ef964 100644
--- a/src/mongo/db/prefetch.cpp
+++ b/src/mongo/db/prefetch.cpp
@@ -55,8 +55,12 @@ namespace mongo {
"repl.preload.docs",
&prefetchDocStats );
+ void prefetchIndexPages(Collection* collection, const BSONObj& obj);
+ void prefetchRecordPages(OperationContext* txn, const char* ns, const BSONObj& obj);
+
+
// prefetch for an oplog operation
- void prefetchPagesForReplicatedOp(Database* db, const BSONObj& op) {
+ void prefetchPagesForReplicatedOp(OperationContext* txn, Database* db, const BSONObj& op) {
const char *opField;
const char *opType = op.getStringField("op");
switch (*opType) {
@@ -110,10 +114,11 @@ namespace mongo {
// do not prefetch the data for capped collections because
// they typically do not have an _id index for findById() to use.
!collection->isCapped()) {
- prefetchRecordPages(ns, obj);
+ prefetchRecordPages(txn, ns, obj);
}
}
+ // page in pages needed for all index lookups on a given object
void prefetchIndexPages(Collection* collection, const BSONObj& obj) {
DiskLoc unusedDl; // unused
BSONObjSet unusedKeys;
@@ -170,8 +175,8 @@ namespace mongo {
}
}
-
- void prefetchRecordPages(const char* ns, const BSONObj& obj) {
+ // page in the data pages for a record associated with an object
+ void prefetchRecordPages(OperationContext* txn, const char* ns, const BSONObj& obj) {
BSONElement _id;
if( obj.getObjectID(_id) ) {
TimerHolder timer(&prefetchDocStats);
@@ -181,7 +186,7 @@ namespace mongo {
try {
// we can probably use Client::Context here instead of ReadContext as we
// have locked higher up the call stack already
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(txn, ns);
if( Helpers::findById(ctx.ctx().db(), ns, builder.done(), result) ) {
// do we want to use Record::touch() here? it's pretty similar.
volatile char _dummy_char = '\0';
diff --git a/src/mongo/db/prefetch.h b/src/mongo/db/prefetch.h
index 3e97753da23..36310b40676 100644
--- a/src/mongo/db/prefetch.h
+++ b/src/mongo/db/prefetch.h
@@ -33,13 +33,8 @@
namespace mongo {
class Collection;
class Database;
+ class OperationContext;
// page in both index and data pages for an op from the oplog
- void prefetchPagesForReplicatedOp(Database* db, const BSONObj& op);
-
- // page in pages needed for all index lookups on a given object
- void prefetchIndexPages(Collection *nsd, const BSONObj& obj);
-
- // page in the data pages for a record associated with an object
- void prefetchRecordPages(const char *ns, const BSONObj& obj);
+ void prefetchPagesForReplicatedOp(OperationContext* txn, Database* db, const BSONObj& op);
}
diff --git a/src/mongo/db/query/new_find.cpp b/src/mongo/db/query/new_find.cpp
index d78032fed07..7ed222b9f06 100644
--- a/src/mongo/db/query/new_find.cpp
+++ b/src/mongo/db/query/new_find.cpp
@@ -152,7 +152,7 @@ namespace mongo {
exhaust = false;
// This is a read lock.
- scoped_ptr<Client::ReadContext> ctx(new Client::ReadContext(ns));
+ scoped_ptr<Client::ReadContext> ctx(new Client::ReadContext(txn, ns));
Collection* collection = ctx->ctx().db()->getCollection(ns);
uassert( 17356, "collection dropped between getMore calls", collection );
@@ -459,7 +459,7 @@ namespace mongo {
// This is a read lock. We require this because if we're parsing a $where, the
// where-specific parsing code assumes we have a lock and creates execution machinery that
// requires it.
- Client::ReadContext ctx(q.ns);
+ Client::ReadContext ctx(txn, q.ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
// Parse the qm into a CanonicalQuery.
diff --git a/src/mongo/db/range_deleter.cpp b/src/mongo/db/range_deleter.cpp
index fd90b65c289..90cce2fcb4c 100644
--- a/src/mongo/db/range_deleter.cpp
+++ b/src/mongo/db/range_deleter.cpp
@@ -232,7 +232,10 @@ namespace mongo {
_stats->incPendingDeletes_inlock();
}
- _env->getCursorIds(ns, &toDelete->cursorsToWait);
+ {
+ boost::scoped_ptr<OperationContext> txn(transactionFactory());
+ _env->getCursorIds(txn.get(), ns, &toDelete->cursorsToWait);
+ }
{
scoped_lock sl(_queueMutex);
@@ -284,7 +287,7 @@ namespace mongo {
}
set<CursorId> cursorsToWait;
- _env->getCursorIds(ns, &cursorsToWait);
+ _env->getCursorIds(txn, ns, &cursorsToWait);
long long checkIntervalMillis = 5;
@@ -295,7 +298,7 @@ namespace mongo {
while (!cursorsToWait.empty()) {
set<CursorId> cursorsNow;
- _env->getCursorIds(ns, &cursorsNow);
+ _env->getCursorIds(txn, ns, &cursorsNow);
set<CursorId> cursorsLeft;
std::set_intersection(cursorsToWait.begin(),
@@ -438,7 +441,11 @@ namespace mongo {
RangeDeleteEntry* entry = *iter;
set<CursorId> cursorsNow;
- _env->getCursorIds(entry->ns, &cursorsNow);
+ {
+ boost::scoped_ptr<OperationContext> txn(
+ entry->transactionFactory()); // XXX?
+ _env->getCursorIds(txn.get(), entry->ns, &cursorsNow);
+ }
set<CursorId> cursorsLeft;
std::set_intersection(entry->cursorsToWait.begin(),
diff --git a/src/mongo/db/range_deleter.h b/src/mongo/db/range_deleter.h
index 9a3b8c6b1fa..15da3560513 100644
--- a/src/mongo/db/range_deleter.h
+++ b/src/mongo/db/range_deleter.h
@@ -304,7 +304,9 @@ namespace mongo {
* Must be a synchronous call. CursorIds should be populated after call.
* Must not throw exception.
*/
- virtual void getCursorIds(const StringData& ns, std::set<CursorId>* openCursors) = 0;
+ virtual void getCursorIds(OperationContext* txn,
+ const StringData& ns,
+ std::set<CursorId>* openCursors) = 0;
};
} // namespace mongo
diff --git a/src/mongo/db/range_deleter_db_env.cpp b/src/mongo/db/range_deleter_db_env.cpp
index 0a99f21cc55..39e0c81a465 100644
--- a/src/mongo/db/range_deleter_db_env.cpp
+++ b/src/mongo/db/range_deleter_db_env.cpp
@@ -156,9 +156,10 @@ namespace mongo {
return true;
}
- void RangeDeleterDBEnv::getCursorIds(const StringData& ns,
+ void RangeDeleterDBEnv::getCursorIds(OperationContext* txn,
+ const StringData& ns,
std::set<CursorId>* openCursors) {
- Client::ReadContext ctx(ns.toString());
+ Client::ReadContext ctx(txn, ns.toString());
Collection* collection = ctx.ctx().db()->getCollection( ns );
if ( !collection )
return;
diff --git a/src/mongo/db/range_deleter_db_env.h b/src/mongo/db/range_deleter_db_env.h
index 9708fa49495..c5956db5b98 100644
--- a/src/mongo/db/range_deleter_db_env.h
+++ b/src/mongo/db/range_deleter_db_env.h
@@ -62,6 +62,8 @@ namespace mongo {
/**
* Gets the list of open cursors on a given namespace.
*/
- virtual void getCursorIds(const StringData& ns, std::set<CursorId>* openCursors);
+ virtual void getCursorIds(OperationContext* txn,
+ const StringData& ns,
+ std::set<CursorId>* openCursors);
};
}
diff --git a/src/mongo/db/range_deleter_mock_env.cpp b/src/mongo/db/range_deleter_mock_env.cpp
index 2b40a3e7bc6..29877a1a252 100644
--- a/src/mongo/db/range_deleter_mock_env.cpp
+++ b/src/mongo/db/range_deleter_mock_env.cpp
@@ -139,7 +139,8 @@ namespace mongo {
return true;
}
- void RangeDeleterMockEnv::getCursorIds(const StringData& ns, set<CursorId>* in) {
+ void RangeDeleterMockEnv::getCursorIds(
+ OperationContext* txn, const StringData& ns, set<CursorId>* in) {
{
scoped_lock sl(_cursorMapMutex);
const set<CursorId>& _cursors = _cursorMap[ns.toString()];
diff --git a/src/mongo/db/range_deleter_mock_env.h b/src/mongo/db/range_deleter_mock_env.h
index ce9457889d6..b1164ef830b 100644
--- a/src/mongo/db/range_deleter_mock_env.h
+++ b/src/mongo/db/range_deleter_mock_env.h
@@ -139,7 +139,7 @@ namespace mongo {
* RangeDeleterEnv::getCursorIds. The cursors returned can be modified with
* the setCursorId and clearCursorMap methods.
*/
- void getCursorIds(const StringData& ns, std::set<CursorId>* in);
+ void getCursorIds(OperationContext* txn, const StringData& ns, std::set<CursorId>* in);
private:
// mutex acquisition ordering:
diff --git a/src/mongo/db/repair_database.cpp b/src/mongo/db/repair_database.cpp
index 72620d77609..52ecec48a95 100644
--- a/src/mongo/db/repair_database.cpp
+++ b/src/mongo/db/repair_database.cpp
@@ -318,7 +318,7 @@ namespace mongo {
Database* tempDatabase = NULL;
{
bool justCreated = false;
- tempDatabase = dbHolderW().getOrCreate( dbName, reservedPathString, justCreated );
+ tempDatabase = dbHolderW().getOrCreate(txn, dbName, reservedPathString, justCreated);
invariant( justCreated );
}
diff --git a/src/mongo/db/repl/heartbeat.cpp b/src/mongo/db/repl/heartbeat.cpp
index 006998a57ef..5f1f1179aca 100644
--- a/src/mongo/db/repl/heartbeat.cpp
+++ b/src/mongo/db/repl/heartbeat.cpp
@@ -112,7 +112,7 @@ namespace repl {
result.append("rs", true);
if( cmdObj["checkEmpty"].trueValue() ) {
- result.append("hasData", replHasDatabases());
+ result.append("hasData", replHasDatabases(txn));
}
if( (theReplSet == 0) || (theReplSet->startupStatus == ReplSetImpl::LOADINGCONFIG) ) {
string from( cmdObj.getStringField("from") );
diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp
index 48226902b95..ff2ff4921f5 100644
--- a/src/mongo/db/repl/master_slave.cpp
+++ b/src/mongo/db/repl/master_slave.cpp
@@ -60,7 +60,7 @@
namespace mongo {
namespace repl {
- void pretouchOperation(const BSONObj& op);
+ void pretouchOperation(OperationContext* txn, const BSONObj& op);
void pretouchN(vector<BSONObj>&, unsigned a, unsigned b);
/* if 1 sync() is running */
@@ -162,8 +162,8 @@ namespace repl {
void ReplSource::ensureMe() {
string myname = getHostName();
{
- Client::WriteContext ctx("local");
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, "local");
// local.me is an identifier for a server for getLastError w:2+
if (!Helpers::getSingleton("local.me", _me) ||
!_me.hasField("host") ||
@@ -560,6 +560,8 @@ namespace repl {
if ( !only.empty() && only != clientName )
return;
+ OperationContextImpl txn; // XXX?
+
if (replSettings.pretouch &&
!alreadyLocked/*doesn't make sense if in write lock already*/) {
if (replSettings.pretouch > 1) {
@@ -588,18 +590,17 @@ namespace repl {
a += m;
}
// we do one too...
- pretouchOperation(op);
+ pretouchOperation(&txn, op);
tp->join();
countdown = v.size();
}
}
else {
- pretouchOperation(op);
+ pretouchOperation(&txn, op);
}
}
scoped_ptr<Lock::GlobalWrite> lk( alreadyLocked ? 0 : new Lock::GlobalWrite() );
- OperationContextImpl txn; // XXX?
if ( replAllDead ) {
// hmmm why is this check here and not at top of this function? does it get set between top and here?
@@ -679,7 +680,7 @@ namespace repl {
int get() const { return _value; }
- virtual void append( BSONObjBuilder& b, const string& name ) {
+ virtual void append(OperationContext* txn, BSONObjBuilder& b, const string& name) {
b.append( name, _value );
}
@@ -1276,7 +1277,7 @@ namespace repl {
}
}
- void pretouchOperation(const BSONObj& op) {
+ void pretouchOperation(OperationContext* txn, const BSONObj& op) {
if( Lock::somethingWriteLocked() )
return; // no point pretouching if write locked. not sure if this will ever fire, but just in case.
@@ -1299,7 +1300,7 @@ namespace repl {
BSONObjBuilder b;
b.append(_id);
BSONObj result;
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(txn, ns );
if( Helpers::findById(ctx.ctx().db(), ns, b.done(), result) )
_dummy_z += result.objsize(); // touch
}
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 5996e180401..474416dd250 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -113,8 +113,8 @@ namespace repl {
todo : make _logOpRS() call this so we don't repeat ourself?
*/
void _logOpObjRS(const BSONObj& op) {
- Lock::DBWrite lk("local");
OperationContextImpl txn;
+ Lock::DBWrite lk(txn.lockState(), "local");
const OpTime ts = op["ts"]._opTime();
long long h = op["h"].numberLong();
@@ -231,7 +231,7 @@ namespace repl {
BSONObj *o2,
bool *bb,
bool fromMigrate ) {
- Lock::DBWrite lk1("local");
+ Lock::DBWrite lk1(txn->lockState(), "local");
if ( strncmp(ns, "local.", 6) == 0 ) {
if ( strncmp(ns, "local.slaves", 12) == 0 )
@@ -321,7 +321,7 @@ namespace repl {
BSONObj *o2,
bool *bb,
bool fromMigrate ) {
- Lock::DBWrite lk("local");
+ Lock::DBWrite lk(txn->lockState(), "local");
static BufBuilder bufbuilder(8*1024); // todo there is likely a mutex on this constructor
if ( strncmp(ns, "local.", 6) == 0 ) {
diff --git a/src/mongo/db/repl/repl_set_impl.cpp b/src/mongo/db/repl/repl_set_impl.cpp
index 01f78853e04..5274e461f07 100644
--- a/src/mongo/db/repl/repl_set_impl.cpp
+++ b/src/mongo/db/repl/repl_set_impl.cpp
@@ -435,7 +435,8 @@ namespace {
}
void ReplSetImpl::loadLastOpTimeWritten(bool quiet) {
- Lock::DBRead lk(rsoplog);
+ OperationContextImpl txn; // XXX?
+ Lock::DBRead lk(txn.lockState(), rsoplog);
BSONObj o;
if (Helpers::getLast(rsoplog, o)) {
lastH = o["h"].numberLong();
@@ -445,7 +446,8 @@ namespace {
}
OpTime ReplSetImpl::getEarliestOpTimeWritten() const {
- Lock::DBRead lk(rsoplog);
+ OperationContextImpl txn; // XXX?
+ Lock::DBRead lk(txn.lockState(), rsoplog);
BSONObj o;
uassert(17347, "Problem reading earliest entry from oplog", Helpers::getFirst(rsoplog, o));
return o["ts"]._opTime();
@@ -859,19 +861,20 @@ namespace {
const BSONObj ReplSetImpl::_initialSyncFlag(BSON(_initialSyncFlagString << true));
void ReplSetImpl::clearInitialSyncFlag() {
- Lock::DBWrite lk("local");
OperationContextImpl txn; // XXX?
+ Lock::DBWrite lk(txn.lockState(), "local");
Helpers::putSingleton(&txn, "local.replset.minvalid", BSON("$unset" << _initialSyncFlag));
}
void ReplSetImpl::setInitialSyncFlag() {
- Lock::DBWrite lk("local");
OperationContextImpl txn; // XXX?
+ Lock::DBWrite lk(txn.lockState(), "local");
Helpers::putSingleton(&txn, "local.replset.minvalid", BSON("$set" << _initialSyncFlag));
}
bool ReplSetImpl::getInitialSyncFlag() {
- Lock::DBRead lk ("local");
+ OperationContextImpl txn; // XXX?
+ Lock::DBRead lk (txn.lockState(), "local");
BSONObj mv;
if (Helpers::getSingleton("local.replset.minvalid", mv)) {
return mv[_initialSyncFlagString].trueValue();
@@ -884,13 +887,15 @@ namespace {
BSONObjBuilder subobj(builder.subobjStart("$set"));
subobj.appendTimestamp("ts", obj["ts"].date());
subobj.done();
- Lock::DBWrite lk("local");
+
OperationContextImpl txn; // XXX?
+ Lock::DBWrite lk(txn.lockState(), "local");
Helpers::putSingleton(&txn, "local.replset.minvalid", builder.obj());
}
OpTime ReplSetImpl::getMinValid() {
- Lock::DBRead lk("local.replset.minvalid");
+ OperationContextImpl txn; // XXX?
+ Lock::DBRead lk(txn.lockState(), "local.replset.minvalid");
BSONObj mv;
if (Helpers::getSingleton("local.replset.minvalid", mv)) {
return mv["ts"]._opTime();
diff --git a/src/mongo/db/repl/repl_settings.cpp b/src/mongo/db/repl/repl_settings.cpp
index e8cb54d8728..48dad4218cc 100644
--- a/src/mongo/db/repl/repl_settings.cpp
+++ b/src/mongo/db/repl/repl_settings.cpp
@@ -40,6 +40,7 @@
#include "mongo/db/repl/master_slave.h"
#include "mongo/db/repl/oplogreader.h"
#include "mongo/db/repl/rs.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/storage_options.h"
#include "mongo/db/wire_version.h"
#include "mongo/s/write_ops/batched_command_request.h"
@@ -55,7 +56,7 @@ namespace repl {
return replSettings.slave || replSettings.master || theReplSet;
}
- void appendReplicationInfo(BSONObjBuilder& result, int level) {
+ void appendReplicationInfo(OperationContext* txn, BSONObjBuilder& result, int level) {
if ( replSet ) {
if( theReplSet == 0 || theReplSet->state().shunned() ) {
result.append("ismaster", false);
@@ -88,7 +89,7 @@ namespace repl {
list<BSONObj> src;
{
const char* localSources = "local.sources";
- Client::ReadContext ctx(localSources, storageGlobalParams.dbpath);
+ Client::ReadContext ctx(txn, localSources);
auto_ptr<Runner> runner(InternalPlanner::collectionScan(localSources,
ctx.ctx().db()->getCollection(localSources)));
BSONObj obj;
@@ -151,7 +152,9 @@ namespace repl {
int level = configElement.numberInt();
BSONObjBuilder result;
- appendReplicationInfo(result, level);
+
+ OperationContextImpl txn; // XXX?
+ appendReplicationInfo(&txn, result, level);
return result.obj();
}
} replicationInfoServerStatus;
@@ -196,7 +199,7 @@ namespace repl {
if ( cmdObj["forShell"].trueValue() )
lastError.disableForCommand();
- appendReplicationInfo(result, 0);
+ appendReplicationInfo(txn, result, 0);
result.appendNumber("maxBsonObjectSize", BSONObjMaxUserSize);
result.appendNumber("maxMessageSizeBytes", MaxMessageSizeBytes);
diff --git a/src/mongo/db/repl/rs.cpp b/src/mongo/db/repl/rs.cpp
index 798269c7c29..ee32241039d 100644
--- a/src/mongo/db/repl/rs.cpp
+++ b/src/mongo/db/repl/rs.cpp
@@ -171,7 +171,7 @@ namespace repl {
}
}
- virtual void append( BSONObjBuilder& b, const string& name ) {
+ virtual void append(OperationContext* txn, BSONObjBuilder& b, const string& name) {
b.append( name, _value() );
}
diff --git a/src/mongo/db/repl/rs_config.cpp b/src/mongo/db/repl/rs_config.cpp
index 0e29c52e323..da705f14659 100644
--- a/src/mongo/db/repl/rs_config.cpp
+++ b/src/mongo/db/repl/rs_config.cpp
@@ -28,8 +28,6 @@
* it in the license file.
*/
-#include "mongo/pch.h"
-
#include <boost/algorithm/string.hpp>
#include "mongo/db/dbhelpers.h"
@@ -82,8 +80,8 @@ namespace repl {
log() << "replSet info saving a newer config version to local.system.replset: "
<< newConfigBSON << rsLog;
{
- Client::WriteContext cx( rsConfigNs );
OperationContextImpl txn;
+ Client::WriteContext cx(&txn, rsConfigNs);
//theReplSet->lastOpTimeWritten = ??;
//rather than above, do a logOp()? probably
diff --git a/src/mongo/db/repl/rs_initialsync.cpp b/src/mongo/db/repl/rs_initialsync.cpp
index f3120fb246a..32d9d7e6e3c 100644
--- a/src/mongo/db/repl/rs_initialsync.cpp
+++ b/src/mongo/db/repl/rs_initialsync.cpp
@@ -99,8 +99,8 @@ namespace repl {
else
sethbmsg( str::stream() << "initial sync cloning indexes for : " << db , 0);
- Client::WriteContext ctx(db);
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, db);
string err;
int errCode;
@@ -130,8 +130,9 @@ namespace repl {
void _logOpObjRS(const BSONObj& op);
static void emptyOplog() {
- Client::WriteContext ctx(rsoplog);
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, rsoplog);
+
Collection* collection = ctx.ctx().db()->getCollection(rsoplog);
// temp
@@ -321,7 +322,8 @@ namespace repl {
log() << "replSet cleaning up [1]" << rsLog;
{
- Client::WriteContext cx( "local." );
+ OperationContextImpl txn; // XXX?
+ Client::WriteContext cx(&txn, "local.");
cx.ctx().db()->flushFiles(true);
}
log() << "replSet cleaning up [2]" << rsLog;
@@ -465,7 +467,9 @@ namespace repl {
verify( !box.getState().primary() ); // wouldn't make sense if we were.
{
- Client::WriteContext cx( "local." );
+ OperationContextImpl txn;
+ Client::WriteContext cx(&txn, "local.");
+
cx.ctx().db()->flushFiles(true);
try {
log() << "replSet set minValid=" << minValid["ts"]._opTime().toString() << rsLog;
diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp
index 45b24c899df..b8bc672753f 100644
--- a/src/mongo/db/repl/rs_rollback.cpp
+++ b/src/mongo/db/repl/rs_rollback.cpp
@@ -654,7 +654,8 @@ namespace repl {
// check that we are at minvalid, otherwise we cannot rollback as we may be in an
// inconsistent state
{
- Lock::DBRead lk("local.replset.minvalid");
+ OperationContextImpl txn;
+ Lock::DBRead lk(txn.lockState(), "local.replset.minvalid");
BSONObj mv;
if (Helpers::getSingleton("local.replset.minvalid", mv)) {
OpTime minvalid = mv["ts"]._opTime();
diff --git a/src/mongo/db/repl/sync_source_feedback.cpp b/src/mongo/db/repl/sync_source_feedback.cpp
index 8a8ac1da5f9..d30eb517898 100644
--- a/src/mongo/db/repl/sync_source_feedback.cpp
+++ b/src/mongo/db/repl/sync_source_feedback.cpp
@@ -66,8 +66,9 @@ namespace repl {
void SyncSourceFeedback::ensureMe() {
string myname = getHostName();
{
- Client::WriteContext ctx("local");
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, "local");
+
// local.me is an identifier for a server for getLastError w:2+
if (!Helpers::getSingleton("local.me", _me) ||
!_me.hasField("host") ||
diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp
index 4526c4af3d3..92eea631595 100644
--- a/src/mongo/db/repl/sync_tail.cpp
+++ b/src/mongo/db/repl/sync_tail.cpp
@@ -94,6 +94,7 @@ namespace repl {
bool isCommand(op["op"].valuestrsafe()[0] == 'c');
+ OperationContextImpl txn;
boost::scoped_ptr<Lock::ScopedLock> lk;
if(isCommand) {
@@ -102,11 +103,10 @@ namespace repl {
lk.reset(new Lock::GlobalWrite());
} else {
// DB level lock for this operation
- lk.reset(new Lock::DBWrite(ns));
+ lk.reset(new Lock::DBWrite(txn.lockState(), ns));
}
Client::Context ctx(ns, storageGlobalParams.dbpath);
- OperationContextImpl txn;
ctx.getClient()->curop()->reset();
// For non-initial-sync, we convert updates to upserts
// to suppress errors when replaying oplog entries.
@@ -126,8 +126,9 @@ namespace repl {
try {
// one possible tweak here would be to stay in the read lock for this database
// for multiple prefetches if they are for the same database.
- Client::ReadContext ctx(ns);
- prefetchPagesForReplicatedOp(ctx.ctx().db(), op);
+ OperationContextImpl txn;
+ Client::ReadContext ctx(&txn, ns);
+ prefetchPagesForReplicatedOp(&txn, ctx.ctx().db(), op);
}
catch (const DBException& e) {
LOG(2) << "ignoring exception in prefetchOp(): " << e.what() << endl;
@@ -475,7 +476,9 @@ namespace repl {
void SyncTail::applyOpsToOplog(std::deque<BSONObj>* ops) {
{
- Lock::DBWrite lk("local");
+ OperationContextImpl txn; // XXX?
+ Lock::DBWrite lk(txn.lockState(), "local");
+
while (!ops->empty()) {
const BSONObj& op = ops->front();
// this updates theReplSet->lastOpTimeWritten
diff --git a/src/mongo/db/restapi.cpp b/src/mongo/db/restapi.cpp
index 1e9e2708efa..657dc627d16 100644
--- a/src/mongo/db/restapi.cpp
+++ b/src/mongo/db/restapi.cpp
@@ -260,9 +260,9 @@ namespace mongo {
} restHandler;
- bool RestAdminAccess::haveAdminUsers() const {
+ bool RestAdminAccess::haveAdminUsers(OperationContext* txn) const {
AuthorizationSession* authzSession = cc().getAuthorizationSession();
- return authzSession->getAuthorizationManager().hasAnyPrivilegeDocuments();
+ return authzSession->getAuthorizationManager().hasAnyPrivilegeDocuments(txn);
}
class LowLevelMongodStatus : public WebStatusPlugin {
diff --git a/src/mongo/db/restapi.h b/src/mongo/db/restapi.h
index e170e740b20..d73103ab785 100644
--- a/src/mongo/db/restapi.h
+++ b/src/mongo/db/restapi.h
@@ -43,7 +43,7 @@ namespace mongo {
public:
virtual ~RestAdminAccess() { }
- virtual bool haveAdminUsers() const;
+ virtual bool haveAdminUsers(OperationContext* txn) const;
};
} // namespace mongo
diff --git a/src/mongo/db/server_parameters.h b/src/mongo/db/server_parameters.h
index c4feb946ad5..9c281e4499c 100644
--- a/src/mongo/db/server_parameters.h
+++ b/src/mongo/db/server_parameters.h
@@ -39,6 +39,7 @@
namespace mongo {
class ServerParameterSet;
+ class OperationContext;
/**
* Lets you make server level settings easily configurable.
@@ -66,7 +67,7 @@ namespace mongo {
bool allowedToChangeAtRuntime() const { return _allowedToChangeAtRuntime; }
- virtual void append( BSONObjBuilder& b, const std::string& name ) = 0;
+ virtual void append(OperationContext* txn, BSONObjBuilder& b, const std::string& name ) = 0;
virtual Status set( const BSONElement& newValueElement ) = 0;
@@ -114,7 +115,7 @@ namespace mongo {
_value( value ) {}
virtual ~ExportedServerParameter() {}
- virtual void append( BSONObjBuilder& b, const std::string& name ) {
+ virtual void append(OperationContext* txn, BSONObjBuilder& b, const std::string& name) {
b.append( name, *_value );
}
diff --git a/src/mongo/db/server_parameters_test.cpp b/src/mongo/db/server_parameters_test.cpp
index 212b31dbacc..c2a6f56156c 100644
--- a/src/mongo/db/server_parameters_test.cpp
+++ b/src/mongo/db/server_parameters_test.cpp
@@ -30,6 +30,7 @@
#include "mongo/unittest/unittest.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/db/server_parameters.h"
namespace mongo {
@@ -68,7 +69,10 @@ namespace mongo {
ASSERT_EQUALS( "c", v[2] );
BSONObjBuilder b;
- vv.append( b, vv.name() );
+
+ OperationContextNoop txn;
+ vv.append(&txn, b, vv.name());
+
BSONObj y = b.obj();
ASSERT( x.firstElement().woCompare( y.firstElement(), false ) == 0 );
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index be47f16d3d3..c497c8ed7e4 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -113,9 +113,10 @@ namespace mongo {
long long n = 0;
{
- string ns = idx["ns"].String();
- Client::WriteContext ctx( ns );
+ const string ns = idx["ns"].String();
+
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns );
Collection* collection = ctx.ctx().db()->getCollection( ns );
if ( !collection ) {
// collection was dropped
@@ -171,7 +172,8 @@ namespace mongo {
set<string> dbs;
{
- Lock::DBRead lk( "local" );
+ OperationContextImpl txn; // XXX?
+ Lock::DBRead lk(txn.lockState(), "local");
dbHolder().getAllShortNames( dbs );
}
diff --git a/src/mongo/dbtests/clienttests.cpp b/src/mongo/dbtests/clienttests.cpp
index e47e67ea4ea..194cc048046 100644
--- a/src/mongo/dbtests/clienttests.cpp
+++ b/src/mongo/dbtests/clienttests.cpp
@@ -1,3 +1,5 @@
+// client.cpp
+
/*
* Copyright (C) 2010 10gen Inc.
*
@@ -26,16 +28,13 @@
* then also delete it in the license file.
*/
-// client.cpp
-
-#include "mongo/pch.h"
-
#include "mongo/client/dbclientcursor.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/database.h"
-#include "mongo/db/d_concurrency.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/dbtests/dbtests.h"
+
namespace ClientTests {
class Base {
@@ -123,8 +122,8 @@ namespace ClientTests {
public:
BuildIndex() : Base("buildIndex") {}
void run() {
- Lock::DBWrite lock(ns());
- Client::WriteContext ctx(ns());
+ OperationContextNoop txn;
+ Client::WriteContext ctx(&txn, ns());
db.insert(ns(), BSON("x" << 1 << "y" << 2));
db.insert(ns(), BSON("x" << 2 << "y" << 2));
diff --git a/src/mongo/dbtests/counttests.cpp b/src/mongo/dbtests/counttests.cpp
index 1ff84d735f8..729443e2835 100644
--- a/src/mongo/dbtests/counttests.cpp
+++ b/src/mongo/dbtests/counttests.cpp
@@ -41,13 +41,16 @@
namespace CountTests {
class Base {
+ OperationContextImpl _txn;
Lock::DBWrite lk;
+
Client::Context _context;
+
Database* _database;
Collection* _collection;
- OperationContextImpl _txn;
+
public:
- Base() : lk(ns()), _context( ns() ) {
+ Base() : lk(_txn.lockState(), ns()), _context( ns() ) {
_database = _context.db();
_collection = _database->getCollection( ns() );
if ( _collection ) {
diff --git a/src/mongo/dbtests/dbhelper_tests.cpp b/src/mongo/dbtests/dbhelper_tests.cpp
index 535dab6124d..0cee60de170 100644
--- a/src/mongo/dbtests/dbhelper_tests.cpp
+++ b/src/mongo/dbtests/dbhelper_tests.cpp
@@ -58,8 +58,9 @@ namespace mongo {
{
// Remove _id range [_min, _max).
OperationContextImpl txn;
- Lock::DBWrite lk( ns );
+ Lock::DBWrite lk(txn.lockState(), ns);
Client::Context ctx( ns );
+
KeyRange range( ns,
BSON( "_id" << _min ),
BSON( "_id" << _max ),
@@ -112,6 +113,8 @@ namespace mongo {
TEST(DBHelperTests, FindDiskLocs) {
DBDirectClient client;
+ OperationContextImpl txn;
+
// Some unique tag we can use to make sure we're pulling back the right data
OID tag = OID::gen();
client.remove( ns, BSONObj() );
@@ -128,14 +131,15 @@ namespace mongo {
long long estSizeBytes;
{
// search _id range (0, 10)
- Lock::DBRead lk( ns );
+ Lock::DBRead lk(txn.lockState(), ns);
KeyRange range( ns,
BSON( "_id" << 0 ),
BSON( "_id" << numDocsInserted ),
BSON( "_id" << 1 ) );
- Status result = Helpers::getLocsInRange( range,
+ Status result = Helpers::getLocsInRange( &txn,
+ range,
maxSizeBytes,
&locs,
&numDocsFound,
@@ -164,6 +168,8 @@ namespace mongo {
TEST(DBHelperTests, FindDiskLocsNoIndex) {
DBDirectClient client;
+ OperationContextImpl txn;
+
client.remove( ns, BSONObj() );
client.insert( ns, BSON( "_id" << OID::gen() ) );
@@ -173,7 +179,7 @@ namespace mongo {
long long numDocsFound;
long long estSizeBytes;
{
- Lock::DBRead lk( ns );
+ Lock::DBRead lk(txn.lockState(), ns);
Client::Context ctx( ns );
// search invalid index range
@@ -182,7 +188,8 @@ namespace mongo {
BSON( "badIndex" << 10 ),
BSON( "badIndex" << 1 ) );
- Status result = Helpers::getLocsInRange( range,
+ Status result = Helpers::getLocsInRange( &txn,
+ range,
maxSizeBytes,
&locs,
&numDocsFound,
@@ -203,6 +210,8 @@ namespace mongo {
TEST(DBHelperTests, FindDiskLocsTooBig) {
DBDirectClient client;
+ OperationContextImpl txn;
+
client.remove( ns, BSONObj() );
int numDocsInserted = 10;
@@ -217,14 +226,15 @@ namespace mongo {
long long numDocsFound;
long long estSizeBytes;
{
- Lock::DBRead lk( ns );
+ Lock::DBRead lk(txn.lockState(), ns);
Client::Context ctx( ns );
KeyRange range( ns,
BSON( "_id" << 0 ),
BSON( "_id" << numDocsInserted ),
BSON( "_id" << 1 ) );
- Status result = Helpers::getLocsInRange( range,
+ Status result = Helpers::getLocsInRange( &txn,
+ range,
maxSizeBytes,
&locs,
&numDocsFound,
diff --git a/src/mongo/dbtests/documentsourcetests.cpp b/src/mongo/dbtests/documentsourcetests.cpp
index 593c310eb93..652958c2efe 100644
--- a/src/mongo/dbtests/documentsourcetests.cpp
+++ b/src/mongo/dbtests/documentsourcetests.cpp
@@ -166,7 +166,7 @@ namespace DocumentSourceTests {
_registration.reset();
_runner.reset();
- Client::WriteContext ctx (ns);
+ Client::WriteContext ctx(&_opCtx, ns);
CanonicalQuery* cq;
uassertStatusOK(CanonicalQuery::canonicalize(ns, /*query=*/BSONObj(), &cq));
Runner* runnerBare;
diff --git a/src/mongo/dbtests/indexcatalogtests.cpp b/src/mongo/dbtests/indexcatalogtests.cpp
index 8afba25af39..bf9b61cf5d3 100644
--- a/src/mongo/dbtests/indexcatalogtests.cpp
+++ b/src/mongo/dbtests/indexcatalogtests.cpp
@@ -31,22 +31,25 @@ namespace IndexCatalogTests {
class IndexIteratorTests {
public:
IndexIteratorTests() {
- Client::WriteContext ctx(_ns);
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, _ns);
+
_db = ctx.ctx().db();
_coll = _db->createCollection(&txn, _ns);
_catalog = _coll->getIndexCatalog();
}
~IndexIteratorTests() {
- Client::WriteContext ctx(_ns);
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, _ns);
+
_db->dropCollection(&txn, _ns);
}
void run() {
- Client::WriteContext ctx(_ns);
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, _ns);
+
int numFinishedIndexesStart = _catalog->numIndexesReady();
BSONObjBuilder b1;
diff --git a/src/mongo/dbtests/indexupdatetests.cpp b/src/mongo/dbtests/indexupdatetests.cpp
index 7c2f03662f6..792c1071d3e 100644
--- a/src/mongo/dbtests/indexupdatetests.cpp
+++ b/src/mongo/dbtests/indexupdatetests.cpp
@@ -55,7 +55,7 @@ namespace IndexUpdateTests {
class IndexBuildBase {
public:
IndexBuildBase() :
- _ctx( _ns ) {
+ _ctx(&_txn, _ns) {
_client.createCollection( _ns );
}
~IndexBuildBase() {
@@ -91,8 +91,9 @@ namespace IndexUpdateTests {
return collection()->getIndexCatalog()->findIndexByName( "a_1" );
}
#endif
- Client::WriteContext _ctx;
+
OperationContextImpl _txn;
+ Client::WriteContext _ctx;
};
/** addKeysToPhaseOne() adds keys from a collection's documents to an external sorter. */
diff --git a/src/mongo/dbtests/matchertests.cpp b/src/mongo/dbtests/matchertests.cpp
index 5bee238cda6..67bff7ef74b 100644
--- a/src/mongo/dbtests/matchertests.cpp
+++ b/src/mongo/dbtests/matchertests.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/json.h"
#include "mongo/db/matcher/matcher.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/util/timer.h"
@@ -216,7 +217,9 @@ namespace MatcherTests {
class WhereSimple1 {
public:
void run() {
- Client::ReadContext ctx( "unittests.matchertests" );
+ OperationContextImpl txn;
+ Client::ReadContext ctx(&txn, "unittests.matchertests");
+
M m(BSON("$where" << "function(){ return this.a == 1; }"),
WhereCallbackReal(StringData("unittests")));
ASSERT( m.matches( BSON( "a" << 1 ) ) );
diff --git a/src/mongo/dbtests/pdfiletests.cpp b/src/mongo/dbtests/pdfiletests.cpp
index 59d5f1bc483..5ef98e0b08b 100644
--- a/src/mongo/dbtests/pdfiletests.cpp
+++ b/src/mongo/dbtests/pdfiletests.cpp
@@ -164,7 +164,8 @@ namespace PdfileTests {
void run() {
SmallFilesControl c;
- Client::ReadContext ctx( "local" );
+ OperationContextImpl txn;
+ Client::ReadContext ctx(&txn, "local");
Database* db = ctx.ctx().db();
ExtentManager* em = db->getExtentManager();
diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp
index 970e59a97ca..02939707de3 100644
--- a/src/mongo/dbtests/plan_ranking.cpp
+++ b/src/mongo/dbtests/plan_ranking.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/instance.h"
#include "mongo/db/json.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/query/get_runner.h"
#include "mongo/db/query/qlog.h"
#include "mongo/db/query/query_knobs.h"
@@ -45,6 +46,7 @@
#include "mongo/db/query/stage_builder.h"
#include "mongo/dbtests/dbtests.h"
+
namespace mongo {
// How we access the external setParameter testing bool.
@@ -59,7 +61,7 @@ namespace PlanRankingTests {
class PlanRankingTestBase {
public:
PlanRankingTestBase() : _internalQueryForceIntersectionPlans(internalQueryForceIntersectionPlans) {
- Client::WriteContext ctx(ns);
+ Client::WriteContext ctx(&_txn, ns);
_client.dropCollection(ns);
}
@@ -69,12 +71,12 @@ namespace PlanRankingTests {
}
void insert(const BSONObj& obj) {
- Client::WriteContext ctx(ns);
+ Client::WriteContext ctx(&_txn, ns);
_client.insert(ns, obj);
}
void addIndex(const BSONObj& obj) {
- Client::WriteContext ctx(ns);
+ Client::WriteContext ctx(&_txn, ns);
_client.ensureIndex(ns, obj);
}
@@ -85,7 +87,7 @@ namespace PlanRankingTests {
* Takes ownership of 'cq'. Caller DOES NOT own the returned QuerySolution*.
*/
QuerySolution* pickBestPlan(CanonicalQuery* cq) {
- Client::ReadContext ctx(ns);
+ Client::ReadContext ctx(&_txn, ns);
Collection* collection = ctx.ctx().db()->getCollection(ns);
QueryPlannerParams plannerParams;
@@ -135,16 +137,17 @@ namespace PlanRankingTests {
// determining the number of documents in the tests below.
static const int N;
+ OperationContextImpl _txn;
+
private:
- static DBDirectClient _client;
+
+ DBDirectClient _client;
scoped_ptr<MultiPlanStage> _mps;
// Holds the value of global "internalQueryForceIntersectionPlans" setParameter flag.
// Restored at end of test invocation regardless of test result.
bool _internalQueryForceIntersectionPlans;
};
- DBDirectClient PlanRankingTestBase::_client;
-
// static
const int PlanRankingTestBase::N = internalQueryPlanEvaluationWorks + 1000;
diff --git a/src/mongo/dbtests/query_multi_plan_runner.cpp b/src/mongo/dbtests/query_multi_plan_runner.cpp
index bc853298488..99d1f61d172 100644
--- a/src/mongo/dbtests/query_multi_plan_runner.cpp
+++ b/src/mongo/dbtests/query_multi_plan_runner.cpp
@@ -38,6 +38,7 @@
#include "mongo/db/instance.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/dbtests/dbtests.h"
@@ -92,7 +93,8 @@ namespace QueryMultiPlanRunner {
class MPRCollectionScanVsHighlySelectiveIXScan : public MultiPlanRunnerBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
const int N = 5000;
for (int i = 0; i < N; ++i) {
diff --git a/src/mongo/dbtests/query_single_solution_runner.cpp b/src/mongo/dbtests/query_single_solution_runner.cpp
index 30d7ca0535f..3e2e1330323 100644
--- a/src/mongo/dbtests/query_single_solution_runner.cpp
+++ b/src/mongo/dbtests/query_single_solution_runner.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/query/query_solution.h"
#include "mongo/db/query/single_solution_runner.h"
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/dbtests/dbtests.h"
namespace QuerySingleSolutionRunner {
@@ -147,7 +148,7 @@ namespace QuerySingleSolutionRunner {
static const char* ns() { return "unittests.QueryStageSingleSolutionRunner"; }
size_t numCursors() {
- Client::ReadContext ctx( ns() );
+ Client::ReadContext ctx(&_txn, ns() );
Collection* collection = ctx.ctx().db()->getCollection( ns() );
if ( !collection )
return 0;
@@ -155,28 +156,29 @@ namespace QuerySingleSolutionRunner {
}
void registerRunner( Runner* runner ) {
- Client::ReadContext ctx( ns() );
+ Client::ReadContext ctx(&_txn, ns());
Collection* collection = ctx.ctx().db()->getOrCreateCollection( ns() );
return collection->cursorCache()->registerRunner( runner );
}
void deregisterRunner( Runner* runner ) {
- Client::ReadContext ctx( ns() );
+ Client::ReadContext ctx(&_txn, ns());
Collection* collection = ctx.ctx().db()->getOrCreateCollection( ns() );
return collection->cursorCache()->deregisterRunner( runner );
}
+ protected:
+ OperationContextImpl _txn;
+
private:
IndexDescriptor* getIndex(Database* db, const BSONObj& obj) {
Collection* collection = db->getCollection( ns() );
return collection->getIndexCatalog()->findIndexByKeyPattern(obj);
}
- static DBDirectClient _client;
+ DBDirectClient _client;
};
- DBDirectClient SingleSolutionRunnerBase::_client;
-
/**
* Test dropping the collection while the
* SingleSolutionRunner is doing a collection scan.
@@ -184,7 +186,7 @@ namespace QuerySingleSolutionRunner {
class DropCollScan : public SingleSolutionRunnerBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
insert(BSON("_id" << 1));
insert(BSON("_id" << 2));
@@ -212,7 +214,7 @@ namespace QuerySingleSolutionRunner {
class DropIndexScan : public SingleSolutionRunnerBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
insert(BSON("_id" << 1 << "a" << 6));
insert(BSON("_id" << 2 << "a" << 7));
insert(BSON("_id" << 3 << "a" << 8));
@@ -283,7 +285,7 @@ namespace QuerySingleSolutionRunner {
class SnapshotControl : public SnapshotBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
setupCollection();
BSONObj filterObj = fromjson("{a: {$gte: 2}}");
@@ -308,7 +310,7 @@ namespace QuerySingleSolutionRunner {
class SnapshotTest : public SnapshotBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
setupCollection();
BSONObj indexSpec = BSON("_id" << 1);
addIndex(indexSpec);
@@ -339,7 +341,7 @@ namespace QuerySingleSolutionRunner {
class Invalidate : public SingleSolutionRunnerBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
insert(BSON("a" << 1 << "b" << 1));
BSONObj filterObj = fromjson("{_id: {$gt: 0}, b: {$gt: 0}}");
@@ -364,7 +366,7 @@ namespace QuerySingleSolutionRunner {
class InvalidatePinned : public SingleSolutionRunnerBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
insert(BSON("a" << 1 << "b" << 1));
Collection* collection = ctx.ctx().db()->getCollection(ns());
@@ -402,12 +404,12 @@ namespace QuerySingleSolutionRunner {
public:
void run() {
{
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
insert(BSON("a" << 1 << "b" << 1));
}
{
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
Collection* collection = ctx.ctx().db()->getCollection(ns());
BSONObj filterObj = fromjson("{_id: {$gt: 0}, b: {$gt: 0}}");
@@ -420,7 +422,7 @@ namespace QuerySingleSolutionRunner {
// There should be one cursor before timeout,
// and zero cursors after timeout.
ASSERT_EQUALS(1U, numCursors());
- CollectionCursorCache::timeoutCursorsGlobal(600001);
+ CollectionCursorCache::timeoutCursorsGlobal(&_txn, 600001);
ASSERT_EQUALS(0U, numCursors());
}
};
diff --git a/src/mongo/dbtests/query_stage_and.cpp b/src/mongo/dbtests/query_stage_and.cpp
index 3f9d3526f2e..f1d33ff7fb8 100644
--- a/src/mongo/dbtests/query_stage_and.cpp
+++ b/src/mongo/dbtests/query_stage_and.cpp
@@ -109,12 +109,13 @@ namespace QueryStageAnd {
static const char* ns() { return "unittests.QueryStageAnd"; }
+ protected:
+ OperationContextImpl _txn;
+
private:
- static DBDirectClient _client;
+ DBDirectClient _client;
};
- DBDirectClient QueryStageAndBase::_client;
-
//
// Hash AND tests
//
@@ -126,12 +127,12 @@ namespace QueryStageAnd {
class QueryStageAndHashInvalidation : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -228,12 +229,12 @@ namespace QueryStageAnd {
class QueryStageAndHashInvalidateLookahead : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -314,12 +315,12 @@ namespace QueryStageAnd {
class QueryStageAndHashTwoLeaf : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -363,12 +364,12 @@ namespace QueryStageAnd {
class QueryStageAndHashTwoLeafFirstChildLargeKeys : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
// Generate large keys for {foo: 1, big: 1} index.
@@ -415,12 +416,12 @@ namespace QueryStageAnd {
class QueryStageAndHashTwoLeafLastChildLargeKeys : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
// Generate large keys for {baz: 1, big: 1} index.
@@ -466,12 +467,12 @@ namespace QueryStageAnd {
class QueryStageAndHashThreeLeaf : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -527,12 +528,12 @@ namespace QueryStageAnd {
class QueryStageAndHashThreeLeafMiddleChildLargeKeys : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
// Generate large keys for {bar: 1, big: 1} index.
@@ -586,12 +587,12 @@ namespace QueryStageAnd {
class QueryStageAndHashWithNothing : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -645,12 +646,12 @@ namespace QueryStageAnd {
class QueryStageAndHashProducesNothing : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 10; ++i) {
@@ -693,12 +694,12 @@ namespace QueryStageAnd {
class QueryStageAndHashWithMatcher : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -749,12 +750,12 @@ namespace QueryStageAnd {
class QueryStageAndSortedInvalidation : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
// Insert a bunch of data
@@ -866,12 +867,12 @@ namespace QueryStageAnd {
class QueryStageAndSortedThreeLeaf : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
// Insert a bunch of data
@@ -919,12 +920,12 @@ namespace QueryStageAnd {
class QueryStageAndSortedWithNothing : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
@@ -964,12 +965,12 @@ namespace QueryStageAnd {
class QueryStageAndSortedProducesNothing : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -1012,12 +1013,12 @@ namespace QueryStageAnd {
class QueryStageAndSortedWithMatcher : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
@@ -1057,12 +1058,12 @@ namespace QueryStageAnd {
class QueryStageAndSortedByLastChild : public QueryStageAndBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
for (int i = 0; i < 50; ++i) {
diff --git a/src/mongo/dbtests/query_stage_collscan.cpp b/src/mongo/dbtests/query_stage_collscan.cpp
index aa0fb3a2e65..fc30e82ad99 100644
--- a/src/mongo/dbtests/query_stage_collscan.cpp
+++ b/src/mongo/dbtests/query_stage_collscan.cpp
@@ -315,7 +315,7 @@ namespace QueryStageCollectionScan {
class QueryStageCollectionScanBase {
public:
QueryStageCollectionScanBase() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
for (int i = 0; i < numObj(); ++i) {
BSONObjBuilder bob;
@@ -325,7 +325,7 @@ namespace QueryStageCollectionScan {
}
virtual ~QueryStageCollectionScanBase() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.dropCollection(ns());
}
@@ -334,7 +334,7 @@ namespace QueryStageCollectionScan {
}
int countResults(CollectionScanParams::Direction direction, const BSONObj& filterObj) {
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
// Configure the scan.
CollectionScanParams params;
@@ -384,11 +384,13 @@ namespace QueryStageCollectionScan {
static const char* ns() { return "unittests.QueryStageCollectionScan"; }
+ protected:
+ OperationContextImpl _txn;
+
private:
- static DBDirectClient _client;
+ DBDirectClient _client;
};
- DBDirectClient QueryStageCollectionScanBase::_client;
//
// Go forwards, get everything.
@@ -442,7 +444,7 @@ namespace QueryStageCollectionScan {
class QueryStageCollscanObjectsInOrderForward : public QueryStageCollectionScanBase {
public:
void run() {
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
// Configure the scan.
CollectionScanParams params;
@@ -473,7 +475,7 @@ namespace QueryStageCollectionScan {
class QueryStageCollscanObjectsInOrderBackward : public QueryStageCollectionScanBase {
public:
void run() {
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
CollectionScanParams params;
params.collection = ctx.ctx().db()->getCollection( ns() );
@@ -502,7 +504,7 @@ namespace QueryStageCollectionScan {
class QueryStageCollscanInvalidateUpcomingObject : public QueryStageCollectionScanBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
Collection* coll = ctx.ctx().db()->getCollection( ns() );
@@ -564,7 +566,7 @@ namespace QueryStageCollectionScan {
class QueryStageCollscanInvalidateUpcomingObjectBackward : public QueryStageCollectionScanBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
Collection* coll = ctx.ctx().db()->getCollection(ns());
// Get the DiskLocs that would be returned by an in-order scan.
diff --git a/src/mongo/dbtests/query_stage_count.cpp b/src/mongo/dbtests/query_stage_count.cpp
index 090bf068f63..0d0dcbc0673 100644
--- a/src/mongo/dbtests/query_stage_count.cpp
+++ b/src/mongo/dbtests/query_stage_count.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/instance.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/pdfile.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/dbtests/dbtests.h"
@@ -51,7 +52,7 @@ namespace QueryStageCount {
CountBase() { }
virtual ~CountBase() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.dropCollection(ns());
}
@@ -92,11 +93,13 @@ namespace QueryStageCount {
static const char* ns() { return "unittests.QueryStageCount"; }
+ protected:
+ OperationContextImpl _txn;
+
private:
- static DBDirectClient _client;
+ DBDirectClient _client;
};
-
- DBDirectClient CountBase::_client;
+
//
// Check that dups are properly identified
@@ -104,7 +107,7 @@ namespace QueryStageCount {
class QueryStageCountDups : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert some docs
insert(BSON("a" << BSON_ARRAY(5 << 7)));
@@ -136,7 +139,7 @@ namespace QueryStageCount {
class QueryStageCountInclusiveBounds : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert some docs
for (int i = 0; i < 10; ++i) {
@@ -168,7 +171,7 @@ namespace QueryStageCount {
class QueryStageCountExclusiveBounds : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert some docs
for (int i = 0; i < 10; ++i) {
@@ -200,7 +203,7 @@ namespace QueryStageCount {
class QueryStageCountLowerBound : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert doc, add index
insert(BSON("a" << 2));
@@ -228,7 +231,7 @@ namespace QueryStageCount {
class QueryStageCountNothingInInterval : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert documents, add index
insert(BSON("a" << 2));
@@ -258,7 +261,7 @@ namespace QueryStageCount {
class QueryStageCountNothingInIntervalFirstMatchTooHigh : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert some documents, add index
insert(BSON("a" << 2));
@@ -288,7 +291,7 @@ namespace QueryStageCount {
class QueryStageCountNoChangeDuringYield : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert documents, add index
for (int i = 0; i < 10; ++i) {
@@ -339,7 +342,7 @@ namespace QueryStageCount {
class QueryStageCountDeleteDuringYield : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert documents, add index
for (int i = 0; i < 10; ++i) {
@@ -393,7 +396,7 @@ namespace QueryStageCount {
class QueryStageCountInsertNewDocsDuringYield : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert documents, add index
for (int i = 0; i < 10; ++i) {
@@ -450,7 +453,7 @@ namespace QueryStageCount {
class QueryStageCountBecomesMultiKeyDuringYield : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert documents, add index
for (int i = 0; i < 10; ++i) {
@@ -503,7 +506,7 @@ namespace QueryStageCount {
class QueryStageCountUnusedKeys : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert docs, add index
for (int i = 0; i < 10; ++i) {
@@ -538,7 +541,7 @@ namespace QueryStageCount {
class QueryStageCountUnusedEndKey : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert docs, add index
for (int i = 0; i < 10; ++i) {
@@ -571,7 +574,7 @@ namespace QueryStageCount {
class QueryStageCountKeyBecomesUnusedDuringYield : public CountBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
// Insert documents, add index
for (int i = 0; i < 10; ++i) {
diff --git a/src/mongo/dbtests/query_stage_distinct.cpp b/src/mongo/dbtests/query_stage_distinct.cpp
index 37a0a6473b1..ecbbbaf5561 100644
--- a/src/mongo/dbtests/query_stage_distinct.cpp
+++ b/src/mongo/dbtests/query_stage_distinct.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/instance.h"
#include "mongo/db/json.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/query/index_bounds_builder.h"
#include "mongo/db/query/plan_executor.h"
#include "mongo/db/catalog/collection.h"
@@ -48,22 +49,22 @@ namespace QueryStageDistinct {
DistinctBase() { }
virtual ~DistinctBase() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.dropCollection(ns());
}
void addIndex(const BSONObj& obj) {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.ensureIndex(ns(), obj);
}
void insert(const BSONObj& obj) {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.insert(ns(), obj);
}
IndexDescriptor* getIndex(const BSONObj& obj) {
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
Collection* collection = ctx.ctx().db()->getCollection( ns() );
return collection->getIndexCatalog()->findIndexByKeyPattern( obj );
}
@@ -96,11 +97,13 @@ namespace QueryStageDistinct {
static const char* ns() { return "unittests.QueryStageDistinct"; }
+ protected:
+ OperationContextImpl _txn;
+
private:
- static DBDirectClient _client;
+ DBDirectClient _client;
};
- DBDirectClient DistinctBase::_client;
// Tests distinct with single key indices.
class QueryStageDistinctBasic : public DistinctBase {
@@ -121,7 +124,7 @@ namespace QueryStageDistinct {
// Make an index on a:1
addIndex(BSON("a" << 1));
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
// Set up the distinct stage.
DistinctParams params;
@@ -184,7 +187,7 @@ namespace QueryStageDistinct {
// Make an index on a:1
addIndex(BSON("a" << 1));
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
// Set up the distinct stage.
DistinctParams params;
diff --git a/src/mongo/dbtests/query_stage_fetch.cpp b/src/mongo/dbtests/query_stage_fetch.cpp
index 4aaaa2657b7..b99a95b1d87 100644
--- a/src/mongo/dbtests/query_stage_fetch.cpp
+++ b/src/mongo/dbtests/query_stage_fetch.cpp
@@ -87,8 +87,9 @@ namespace QueryStageFetch {
class FetchStageAlreadyFetched : public QueryStageFetchBase {
public:
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
@@ -145,8 +146,9 @@ namespace QueryStageFetch {
class FetchStageFilter : public QueryStageFetchBase {
public:
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
diff --git a/src/mongo/dbtests/query_stage_keep.cpp b/src/mongo/dbtests/query_stage_keep.cpp
index c030387ff09..5ea488a37f2 100644
--- a/src/mongo/dbtests/query_stage_keep.cpp
+++ b/src/mongo/dbtests/query_stage_keep.cpp
@@ -104,8 +104,9 @@ namespace QueryStageKeep {
class KeepStageBasic : public QueryStageKeepBase {
public:
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
diff --git a/src/mongo/dbtests/query_stage_merge_sort.cpp b/src/mongo/dbtests/query_stage_merge_sort.cpp
index 6ddf69290e5..43319528bb2 100644
--- a/src/mongo/dbtests/query_stage_merge_sort.cpp
+++ b/src/mongo/dbtests/query_stage_merge_sort.cpp
@@ -50,7 +50,7 @@ namespace QueryStageMergeSortTests {
QueryStageMergeSortTestBase() { }
virtual ~QueryStageMergeSortTestBase() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.dropCollection(ns());
}
@@ -95,23 +95,25 @@ namespace QueryStageMergeSortTests {
}
static const char* ns() { return "unittests.QueryStageMergeSort"; }
+
+ protected:
+ OperationContextImpl _txn;
+
private:
- static DBDirectClient _client;
+ DBDirectClient _client;
};
- DBDirectClient QueryStageMergeSortTestBase::_client;
-
// SERVER-1205:
// find($or[{a:1}, {b:1}]).sort({c:1}) with indices {a:1, c:1} and {b:1, c:1}.
class QueryStageMergeSortPrefixIndex : public QueryStageMergeSortTestBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
const int N = 50;
@@ -170,12 +172,12 @@ namespace QueryStageMergeSortTests {
class QueryStageMergeSortDups : public QueryStageMergeSortTestBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
const int N = 50;
@@ -233,12 +235,12 @@ namespace QueryStageMergeSortTests {
class QueryStageMergeSortDupsNoDedup : public QueryStageMergeSortTestBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
const int N = 50;
@@ -297,12 +299,12 @@ namespace QueryStageMergeSortTests {
class QueryStageMergeSortPrefixIndexReverse : public QueryStageMergeSortTestBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
const int N = 50;
@@ -362,12 +364,12 @@ namespace QueryStageMergeSortTests {
class QueryStageMergeSortOneStageEOF : public QueryStageMergeSortTestBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
const int N = 50;
@@ -425,12 +427,12 @@ namespace QueryStageMergeSortTests {
class QueryStageMergeSortManyShort : public QueryStageMergeSortTestBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
WorkingSet* ws = new WorkingSet();
@@ -478,12 +480,12 @@ namespace QueryStageMergeSortTests {
class QueryStageMergeSortInvalidation : public QueryStageMergeSortTestBase {
public:
void run() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
OperationContextImpl txn;
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
- coll = db->createCollection(&txn, ns());
+ coll = db->createCollection(&_txn, ns());
}
WorkingSet ws;
diff --git a/src/mongo/dbtests/query_stage_sort.cpp b/src/mongo/dbtests/query_stage_sort.cpp
index f0605a7abbc..2440f67948f 100644
--- a/src/mongo/dbtests/query_stage_sort.cpp
+++ b/src/mongo/dbtests/query_stage_sort.cpp
@@ -169,10 +169,9 @@ namespace QueryStageSortTests {
static const char* ns() { return "unittests.QueryStageSort"; }
private:
- static DBDirectClient _client;
+ DBDirectClient _client;
};
- DBDirectClient QueryStageSortTestBase::_client;
// Sort some small # of results in increasing order.
class QueryStageSortInc: public QueryStageSortTestBase {
@@ -180,8 +179,9 @@ namespace QueryStageSortTests {
virtual int numObj() { return 100; }
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
@@ -199,8 +199,9 @@ namespace QueryStageSortTests {
virtual int numObj() { return 100; }
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
@@ -227,8 +228,9 @@ namespace QueryStageSortTests {
virtual int numObj() { return 10000; }
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
@@ -246,8 +248,9 @@ namespace QueryStageSortTests {
virtual int numObj() { return 2000; }
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
@@ -336,8 +339,9 @@ namespace QueryStageSortTests {
virtual int numObj() { return 100; }
void run() {
- Client::WriteContext ctx(ns());
OperationContextImpl txn;
+ Client::WriteContext ctx(&txn, ns());
+
Database* db = ctx.ctx().db();
Collection* coll = db->getCollection(ns());
if (!coll) {
diff --git a/src/mongo/dbtests/query_stage_tests.cpp b/src/mongo/dbtests/query_stage_tests.cpp
index 3bf9b0ca31f..7e0b0f20c6e 100644
--- a/src/mongo/dbtests/query_stage_tests.cpp
+++ b/src/mongo/dbtests/query_stage_tests.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/instance.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression_parser.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/query/plan_executor.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/dbtests/dbtests.h"
@@ -46,7 +47,7 @@ namespace QueryStageTests {
class IndexScanBase {
public:
IndexScanBase() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
for (int i = 0; i < numObj(); ++i) {
BSONObjBuilder bob;
@@ -61,17 +62,17 @@ namespace QueryStageTests {
}
virtual ~IndexScanBase() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.dropCollection(ns());
}
void addIndex(const BSONObj& obj) {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
_client.ensureIndex(ns(), obj);
}
int countResults(const IndexScanParams& params, BSONObj filterObj = BSONObj()) {
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
StatusWithMatchExpression swme = MatchExpressionParser::parse(filterObj);
verify(swme.isOK());
@@ -91,7 +92,7 @@ namespace QueryStageTests {
}
void makeGeoData() {
- Client::WriteContext ctx(ns());
+ Client::WriteContext ctx(&_txn, ns());
for (int i = 0; i < numObj(); ++i) {
double lat = double(rand()) / RAND_MAX;
@@ -101,7 +102,7 @@ namespace QueryStageTests {
}
IndexDescriptor* getIndex(const BSONObj& obj) {
- Client::ReadContext ctx(ns());
+ Client::ReadContext ctx(&_txn, ns());
Collection* collection = ctx.ctx().db()->getCollection( ns() );
return collection->getIndexCatalog()->findIndexByKeyPattern( obj );
}
@@ -109,12 +110,13 @@ namespace QueryStageTests {
static int numObj() { return 50; }
static const char* ns() { return "unittests.IndexScan"; }
+ protected:
+ OperationContextImpl _txn;
+
private:
- static DBDirectClient _client;
+ DBDirectClient _client;
};
- DBDirectClient IndexScanBase::_client;
-
class QueryStageIXScanBasic : public IndexScanBase {
public:
virtual ~QueryStageIXScanBasic() { }
diff --git a/src/mongo/dbtests/querytests.cpp b/src/mongo/dbtests/querytests.cpp
index 0f834d1d50c..0e73c01e3b5 100644
--- a/src/mongo/dbtests/querytests.cpp
+++ b/src/mongo/dbtests/querytests.cpp
@@ -157,14 +157,13 @@ namespace QueryTests {
// an empty object (one might be allowed inside a reserved namespace at some point).
Lock::GlobalWrite lk;
Client::Context ctx( "unittests.querytests" );
- OperationContextImpl txn;
Database* db = ctx.db();
if ( db->getCollection( ns() ) ) {
_collection = NULL;
- db->dropCollection( &txn, ns() );
+ db->dropCollection( &_txn, ns() );
}
- _collection = db->createCollection( &txn, ns(), CollectionOptions(), true, false );
+ _collection = db->createCollection( &_txn, ns(), CollectionOptions(), true, false );
ASSERT( _collection );
DBDirectClient cl;
@@ -189,21 +188,25 @@ namespace QueryTests {
~ClientBase() {
//mongo::lastError.release();
}
+
protected:
- static void insert( const char *ns, BSONObj o ) {
+ void insert( const char *ns, BSONObj o ) {
client_.insert( ns, o );
}
- static void update( const char *ns, BSONObj q, BSONObj o, bool upsert = 0 ) {
+ void update( const char *ns, BSONObj q, BSONObj o, bool upsert = 0 ) {
client_.update( ns, Query( q ), o, upsert );
}
- static bool error() {
+ bool error() {
return !client_.getPrevError().getField( "err" ).isNull();
}
- DBDirectClient &client() const { return client_; }
- static DBDirectClient client_;
+ const DBDirectClient& client() const { return client_; }
+ DBDirectClient& client() { return client_; }
+
+ DBDirectClient client_;
+
+ OperationContextImpl _txn;
};
- DBDirectClient ClientBase::client_;
class BoundedKey : public ClientBase {
public:
@@ -239,7 +242,7 @@ namespace QueryTests {
{
// Check internal server handoff to getmore.
- Lock::DBWrite lk(ns);
+ Lock::DBWrite lk(_txn.lockState(), ns);
Client::Context ctx( ns );
ClientCursorPin clientCursor( ctx.db()->getCollection(ns), cursorId );
// pq doesn't exist if it's a runner inside of the clientcursor.
@@ -252,6 +255,9 @@ namespace QueryTests {
ASSERT( cursor->more() );
ASSERT_EQUALS( 3, cursor->next().getIntField( "a" ) );
}
+
+ protected:
+ OperationContextImpl _txn;
};
/**
@@ -294,10 +300,11 @@ namespace QueryTests {
// Check that the cursor has been removed.
{
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(&_txn, ns);
ASSERT( 0 == ctx.ctx().db()->getCollection( ns )->cursorCache()->numCursors() );
}
- ASSERT_FALSE( CollectionCursorCache::eraseCursorGlobal( cursorId ) );
+
+ ASSERT_FALSE(CollectionCursorCache::eraseCursorGlobal(&_txn, cursorId));
// Check that a subsequent get more fails with the cursor removed.
ASSERT_THROWS( client().getMore( ns, cursorId ), UserException );
@@ -343,7 +350,7 @@ namespace QueryTests {
// Check that the cursor still exists
{
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(&_txn, ns);
ASSERT( 1 == ctx.ctx().db()->getCollection( ns )->cursorCache()->numCursors() );
ASSERT( ctx.ctx().db()->getCollection( ns )->cursorCache()->find( cursorId, false ) );
}
@@ -583,7 +590,7 @@ namespace QueryTests {
}
void run() {
const char *ns = "unittests.querytests.OplogReplaySlaveReadTill";
- Lock::DBWrite lk(ns);
+ Lock::DBWrite lk(_txn.lockState(), ns);
Client::Context ctx( ns );
BSONObj info;
@@ -654,7 +661,7 @@ namespace QueryTests {
count( 2 );
}
private:
- void count( unsigned long long c ) const {
+ void count( unsigned long long c ) {
ASSERT_EQUALS( c, client().count( "unittests.querytests.BasicCount", BSON( "a" << 4 ) ) );
}
};
@@ -749,8 +756,8 @@ namespace QueryTests {
}
static const char *ns() { return "unittests.querytests.AutoResetIndexCache"; }
static const char *idxNs() { return "unittests.system.indexes"; }
- void index() const { ASSERT( !client().findOne( idxNs(), BSON( "name" << NE << "_id_" ) ).isEmpty() ); }
- void noIndex() const {
+ void index() { ASSERT( !client().findOne( idxNs(), BSON( "name" << NE << "_id_" ) ).isEmpty() ); }
+ void noIndex() {
BSONObj o = client().findOne( idxNs(), BSON( "name" << NE << "_id_" ) );
if( !o.isEmpty() ) {
cout << o.toString() << endl;
@@ -1130,7 +1137,7 @@ namespace QueryTests {
}
size_t numCursorsOpen() {
- Client::ReadContext ctx( _ns );
+ Client::ReadContext ctx(&_txn, _ns);
Collection* collection = ctx.ctx().db()->getCollection( _ns );
if ( !collection )
return 0;
@@ -1172,16 +1179,13 @@ namespace QueryTests {
}
void run() {
string err;
-
- Client::WriteContext ctx( "unittests" );
- OperationContextImpl txn;
+ Client::WriteContext ctx(&_txn, "unittests" );
// note that extents are always at least 4KB now - so this will get rounded up a bit.
- ASSERT( userCreateNS( &txn, ctx.ctx().db(), ns(),
+ ASSERT( userCreateNS( &_txn, ctx.ctx().db(), ns(),
fromjson( "{ capped : true, size : 2000 }" ), false ).isOK() );
for ( int i=0; i<200; i++ ) {
insertNext();
-// cout << count() << endl;
ASSERT( count() < 90 );
}
@@ -1224,7 +1228,7 @@ namespace QueryTests {
}
void run() {
- Client::WriteContext ctx( "unittests" );
+ Client::WriteContext ctx(&_txn, "unittests" );
for ( int i=0; i<50; i++ ) {
insert( ns() , BSON( "_id" << i << "x" << i * 2 ) );
@@ -1275,7 +1279,7 @@ namespace QueryTests {
}
void run() {
- Client::WriteContext ctx( "unittests" );
+ Client::WriteContext ctx(&_txn, "unittests" );
for ( int i=0; i<1000; i++ ) {
insert( ns() , BSON( "_id" << i << "x" << i * 2 ) );
@@ -1298,7 +1302,7 @@ namespace QueryTests {
}
void run() {
- Client::WriteContext ctx( "unittests" );
+ Client::WriteContext ctx(&_txn, "unittests" );
for ( int i=0; i<1000; i++ ) {
insert( ns() , BSON( "_id" << i << "x" << i * 2 ) );
@@ -1414,7 +1418,7 @@ namespace QueryTests {
public:
CollectionInternalBase( const char *nsLeaf ) :
CollectionBase( nsLeaf ),
- _lk( ns() ),
+ _lk(_txn.lockState(), ns() ),
_ctx( ns() ) {
}
private:
@@ -1439,8 +1443,7 @@ namespace QueryTests {
DbMessage dbMessage( message );
QueryMessage queryMessage( dbMessage );
Message result;
- OperationContextImpl txn;
- string exhaust = newRunQuery( &txn, message, queryMessage, *cc().curop(), result );
+ string exhaust = newRunQuery( &_txn, message, queryMessage, *cc().curop(), result );
ASSERT( exhaust.size() );
ASSERT_EQUALS( string( ns() ), exhaust );
}
@@ -1459,7 +1462,7 @@ namespace QueryTests {
ClientCursor *clientCursor = 0;
{
- Client::ReadContext ctx( ns() );
+ Client::ReadContext ctx(&_txn, ns());
ClientCursorPin clientCursorPointer( ctx.ctx().db()->getCollection( ns() ),
cursorId );
clientCursor = clientCursorPointer.c();
@@ -1497,10 +1500,11 @@ namespace QueryTests {
long long cursorId = cursor->getCursorId();
{
- Client::WriteContext ctx( ns() );
+ Client::WriteContext ctx(&_txn, ns() );
ClientCursorPin pinCursor( ctx.ctx().db()->getCollection( ns() ), cursorId );
-
- ASSERT_THROWS( client().killCursor( cursorId ), MsgAssertionException );
+
+ ASSERT_THROWS(CollectionCursorCache::eraseCursorGlobal(&_txn, cursorId),
+ MsgAssertionException);
string expectedAssertion =
str::stream() << "Cannot kill active cursor " << cursorId;
ASSERT_EQUALS( expectedAssertion, client().getLastError() );
diff --git a/src/mongo/dbtests/replsettests.cpp b/src/mongo/dbtests/replsettests.cpp
index fb2a2afdd0a..deb82f41e17 100644
--- a/src/mongo/dbtests/replsettests.cpp
+++ b/src/mongo/dbtests/replsettests.cpp
@@ -147,9 +147,10 @@ namespace ReplSetTests {
DBDirectClient *client() const { return &client_; }
static void insert( const BSONObj &o, bool god = false ) {
- Lock::DBWrite lk(ns());
- Client::Context ctx(ns());
OperationContextImpl txn;
+ Lock::DBWrite lk(txn.lockState(), ns());
+ Client::Context ctx(ns());
+
Database* db = ctx.db();
Collection* coll = db->getCollection(ns());
if (!coll) {
@@ -174,8 +175,8 @@ namespace ReplSetTests {
}
void drop() {
- Client::WriteContext c(ns());
OperationContextImpl txn;
+ Client::WriteContext c(&txn, ns());
Database* db = c.ctx().db();
@@ -306,6 +307,8 @@ namespace ReplSetTests {
class CappedInitialSync : public Base {
string _cappedNs;
+
+ OperationContextImpl _txn;
Lock::DBWrite _lk;
string spec() const {
@@ -342,7 +345,8 @@ namespace ReplSetTests {
return o;
}
public:
- CappedInitialSync() : _cappedNs("unittests.foo.bar"), _lk(_cappedNs) {
+ CappedInitialSync() :
+ _cappedNs("unittests.foo.bar"), _lk(_txn.lockState(), _cappedNs) {
dropCapped();
create();
}
@@ -363,7 +367,8 @@ namespace ReplSetTests {
}
void run() {
- Lock::DBWrite lk(_cappedNs);
+ OperationContextImpl txn;
+ Lock::DBWrite lk(txn.lockState(), _cappedNs);
BSONObj op = updateFail();
diff --git a/src/mongo/dbtests/runner_registry.cpp b/src/mongo/dbtests/runner_registry.cpp
index 8881ff2d4f3..b29088e36d8 100644
--- a/src/mongo/dbtests/runner_registry.cpp
+++ b/src/mongo/dbtests/runner_registry.cpp
@@ -51,7 +51,7 @@ namespace RunnerRegistry {
class RunnerRegistryBase {
public:
RunnerRegistryBase() {
- _ctx.reset(new Client::WriteContext(ns()));
+ _ctx.reset(new Client::WriteContext(&_opCtx, ns()));
_client.dropCollection(ns());
for (int i = 0; i < N(); ++i) {
@@ -269,7 +269,7 @@ namespace RunnerRegistry {
// requires a "global write lock."
_ctx.reset();
_client.dropDatabase("somesillydb");
- _ctx.reset(new Client::WriteContext(ns()));
+ _ctx.reset(new Client::WriteContext(&_opCtx, ns()));
// Unregister and restore state.
deregisterRunner(run.get());
@@ -285,7 +285,7 @@ namespace RunnerRegistry {
// Drop our DB. Once again, must give up the lock.
_ctx.reset();
_client.dropDatabase("unittests");
- _ctx.reset(new Client::WriteContext(ns()));
+ _ctx.reset(new Client::WriteContext(&_opCtx, ns()));
// Unregister and restore state.
deregisterRunner(run.get());
diff --git a/src/mongo/dbtests/threadedtests.cpp b/src/mongo/dbtests/threadedtests.cpp
index b5537364525..96e6e0df7b4 100644
--- a/src/mongo/dbtests/threadedtests.cpp
+++ b/src/mongo/dbtests/threadedtests.cpp
@@ -35,6 +35,7 @@
#include "mongo/bson/util/atomic_int.h"
#include "mongo/db/d_concurrency.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/stdx/functional.h"
@@ -115,6 +116,8 @@ namespace ThreadedTests {
}
virtual void subthread(int tnumber) {
Client::initThread("mongomutextest");
+ LockState lockState;
+
sleepmillis(0);
for( int i = 0; i < N; i++ ) {
int x = std::rand();
@@ -169,13 +172,13 @@ namespace ThreadedTests {
}
else if( i % 7 == 5 ) {
{
- Lock::DBRead r("foo");
+ Lock::DBRead r(&lockState, "foo");
if( sometimes ) {
Lock::TempRelease t;
}
}
{
- Lock::DBRead r("bar");
+ Lock::DBRead r(&lockState, "bar");
}
}
else if( i % 7 == 6 ) {
@@ -183,13 +186,13 @@ namespace ThreadedTests {
int q = i % 11;
if( q == 0 ) {
char what = 'r';
- Lock::DBRead r("foo");
+ Lock::DBRead r(&lockState, "foo");
ASSERT( Lock::isLocked() == what && Lock::atLeastReadLocked("foo") );
ASSERT( !Lock::nested() );
- Lock::DBRead r2("foo");
+ Lock::DBRead r2(&lockState, "foo");
ASSERT( Lock::nested() );
ASSERT( Lock::isLocked() == what && Lock::atLeastReadLocked("foo") );
- Lock::DBRead r3("local");
+ Lock::DBRead r3(&lockState, "local");
if( sometimes ) {
Lock::TempRelease t;
}
@@ -199,41 +202,48 @@ namespace ThreadedTests {
else if( q == 1 ) {
// test locking local only -- with no preceeding lock
{
- Lock::DBRead x("local");
+ Lock::DBRead x(&lockState, "local");
//Lock::DBRead y("q");
if( sometimes ) {
Lock::TempRelease t; // we don't temprelease (cant=true) here thus this is just a check that nothing weird happens...
}
}
- {
- Lock::DBWrite x("local");
+ {
+ OperationContextImpl txn;
+ Lock::DBWrite x(txn.lockState(), "local");
if( sometimes ) {
Lock::TempRelease t;
}
}
} else if( q == 1 ) {
- { Lock::DBRead x("admin"); }
- { Lock::DBWrite x("admin"); }
+ { Lock::DBRead x(&lockState, "admin"); }
+ {
+ OperationContextImpl txn;
+ Lock::DBWrite x(txn.lockState(), "admin");
+ }
} else if( q == 2 ) {
/*Lock::DBWrite x("foo");
Lock::DBWrite y("admin");
{ Lock::TempRelease t; }*/
}
else if( q == 3 ) {
- Lock::DBWrite x("foo");
- Lock::DBRead y("admin");
+ OperationContextImpl txn;
+ Lock::DBWrite x(txn.lockState(), "foo");
+ Lock::DBRead y(&lockState, "admin");
{ Lock::TempRelease t; }
}
else if( q == 4 ) {
- Lock::DBRead x("foo2");
- Lock::DBRead y("admin");
+ Lock::DBRead x(&lockState, "foo2");
+ Lock::DBRead y(&lockState, "admin");
{ Lock::TempRelease t; }
}
else if ( q > 4 && q < 8 ) {
static const char * const dbnames[] = {
"bar0", "bar1", "bar2", "bar3", "bar4", "bar5",
"bar6", "bar7", "bar8", "bar9", "bar10" };
- Lock::DBWrite w(dbnames[q]);
+
+ OperationContextImpl txn;
+ Lock::DBWrite w(txn.lockState(), dbnames[q]);
{
Lock::UpgradeGlobalLockToExclusive wToX;
if (wToX.gotUpgrade()) {
@@ -245,21 +255,24 @@ namespace ThreadedTests {
}
}
else {
- Lock::DBWrite w("foo");
+ OperationContextImpl txn;
+ Lock::DBWrite w(txn.lockState(), "foo");
+
{
Lock::TempRelease t;
}
- Lock::DBRead r2("foo");
- Lock::DBRead r3("local");
+
+ Lock::DBRead r2(&lockState, "foo");
+ Lock::DBRead r3(&lockState, "local");
if( sometimes ) {
Lock::TempRelease t;
}
}
}
else {
- Lock::DBRead r("foo");
- Lock::DBRead r2("foo");
- Lock::DBRead r3("local");
+ Lock::DBRead r(&lockState, "foo");
+ Lock::DBRead r2(&lockState, "foo");
+ Lock::DBRead r3(&lockState, "local");
}
}
pm.hit();
diff --git a/src/mongo/dbtests/updatetests.cpp b/src/mongo/dbtests/updatetests.cpp
index 32e20bd9d01..e89997330cf 100644
--- a/src/mongo/dbtests/updatetests.cpp
+++ b/src/mongo/dbtests/updatetests.cpp
@@ -1060,14 +1060,11 @@ namespace UpdateTests {
BSONObj result;
BSONObj expected;
- switch ( i ) {
- default:
- client().update( ns(), Query(), getUpdate(i) );
- result = client().findOne( ns(), Query() );
- expected = fromjson( "{'_id':0,x:[]}" );
- ASSERT_EQUALS( result, expected );
- break;
- }
+
+ client().update( ns(), Query(), getUpdate(i) );
+ result = client().findOne( ns(), Query() );
+ expected = fromjson( "{'_id':0,x:[]}" );
+ ASSERT_EQUALS( result, expected );
}
}
};
@@ -1092,14 +1089,11 @@ namespace UpdateTests {
BSONObj result;
BSONObj expected;
- switch ( i ) {
- default:
- client().update( ns(), Query(), getUpdate(i) );
- result = client().findOne( ns(), Query() );
- expected = fromjson( "{'_id':0,x:[]}" );
- ASSERT_EQUALS( result, expected );
- break;
- }
+
+ client().update( ns(), Query(), getUpdate(i) );
+ result = client().findOne( ns(), Query() );
+ expected = fromjson( "{'_id':0,x:[]}" );
+ ASSERT_EQUALS( result, expected );
}
}
};
diff --git a/src/mongo/s/commands/auth_schema_upgrade_s.cpp b/src/mongo/s/commands/auth_schema_upgrade_s.cpp
index 144d5c80380..41f569815b1 100644
--- a/src/mongo/s/commands/auth_schema_upgrade_s.cpp
+++ b/src/mongo/s/commands/auth_schema_upgrade_s.cpp
@@ -157,7 +157,7 @@ namespace {
return appendCommandStatus(result, status);
}
- status = authzManager->upgradeSchema(maxSteps, writeConcern);
+ status = authzManager->upgradeSchema(txn, maxSteps, writeConcern);
if (!status.isOK())
return appendCommandStatus(result, status);
diff --git a/src/mongo/s/commands/cluster_index_filter_cmd.cpp b/src/mongo/s/commands/cluster_index_filter_cmd.cpp
index 10855e96aaa..2bd84e2b982 100644
--- a/src/mongo/s/commands/cluster_index_filter_cmd.cpp
+++ b/src/mongo/s/commands/cluster_index_filter_cmd.cpp
@@ -64,13 +64,15 @@ namespace mongo {
ss << _helpText;
}
- Status checkAuthForCommand( ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj ) {
+ Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj ) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
ResourcePattern pattern = parseResourcePattern(dbname, cmdObj);
- if (authzSession->isAuthorizedForActionsOnResource(pattern,
+ if (authzSession->isAuthorizedForActionsOnResource(txn,
+ pattern,
ActionType::planCacheIndexFilter)) {
return Status::OK();
}
diff --git a/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp b/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp
index 2e79c431563..2fefe753a7a 100644
--- a/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp
+++ b/src/mongo/s/commands/cluster_merge_chunks_cmd.cpp
@@ -52,10 +52,12 @@ namespace mongo {
<< "usage: { mergeChunks : <ns>, bounds : [ <min key>, <max key> ] }";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
ActionType::splitChunk)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
diff --git a/src/mongo/s/commands/cluster_plan_cache_cmd.cpp b/src/mongo/s/commands/cluster_plan_cache_cmd.cpp
index 1aa015a495b..15a0076163f 100644
--- a/src/mongo/s/commands/cluster_plan_cache_cmd.cpp
+++ b/src/mongo/s/commands/cluster_plan_cache_cmd.cpp
@@ -64,13 +64,14 @@ namespace mongo {
ss << _helpText;
}
- Status checkAuthForCommand( ClientBasic* client,
- const std::string& dbname,
- const BSONObj& cmdObj ) {
+ Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
+ const std::string& dbname,
+ const BSONObj& cmdObj ) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
ResourcePattern pattern = parseResourcePattern(dbname, cmdObj);
- if (authzSession->isAuthorizedForActionsOnResource(pattern, _actionType)) {
+ if (authzSession->isAuthorizedForActionsOnResource(txn, pattern, _actionType)) {
return Status::OK();
}
diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp
index 3e4a7ce290e..4ffc49f3857 100644
--- a/src/mongo/s/commands/cluster_write_cmd.cpp
+++ b/src/mongo/s/commands/cluster_write_cmd.cpp
@@ -62,11 +62,13 @@ namespace mongo {
bool isWriteCommandForConfigServer() const { return false; }
- Status checkAuthForCommand( ClientBasic* client,
+ Status checkAuthForCommand( OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj ) {
- Status status = auth::checkAuthForWriteCommand( client->getAuthorizationSession(),
+ Status status = auth::checkAuthForWriteCommand( txn,
+ client->getAuthorizationSession(),
_writeType,
NamespaceString( parseNs( dbname,
cmdObj ) ),
diff --git a/src/mongo/s/commands_admin.cpp b/src/mongo/s/commands_admin.cpp
index 5280ce55def..0e91748dfd8 100644
--- a/src/mongo/s/commands_admin.cpp
+++ b/src/mongo/s/commands_admin.cpp
@@ -192,10 +192,12 @@ namespace mongo {
virtual void help( stringstream& help ) const {
help << " example: { moveprimary : 'foo' , to : 'localhost:9999' }";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(parseNs(dbname, cmdObj)),
ActionType::moveChunk)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
@@ -387,10 +389,12 @@ namespace mongo {
<< "Enable sharding for a db. (Use 'shardcollection' command afterwards.)\n"
<< " { enablesharding : \"<dbname>\" }\n";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forDatabaseName(parseNs(dbname, cmdObj)),
ActionType::enableSharding)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
@@ -445,10 +449,12 @@ namespace mongo {
<< "Shard a collection. Requires key. Optional unique. Sharding must already be enabled for the database.\n"
<< " { enablesharding : \"<dbname>\" }\n";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname,
cmdObj))),
ActionType::enableSharding)) {
@@ -830,10 +836,12 @@ namespace mongo {
virtual void help( stringstream& help ) const {
help << " example: { getShardVersion : 'alleyinsider.foo' } ";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname,
cmdObj))),
ActionType::getShardVersion)) {
@@ -881,10 +889,12 @@ namespace mongo {
<< " NOTE: this does not move the chunks, it merely creates a logical separation \n"
;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname,
cmdObj))),
ActionType::splitChunk)) {
@@ -1043,10 +1053,12 @@ namespace mongo {
<< " { movechunk : 'test.foo' , bounds : [ { num : 0 } , { num : 10 } ] "
<< " , to : 'shard001' }\n";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname,
cmdObj))),
ActionType::moveChunk)) {
@@ -1866,7 +1878,8 @@ namespace mongo {
virtual bool adminOnly() const { return true; }
virtual bool isWriteCommandForConfigServer() const { return false; }
virtual void help( stringstream& help ) const { help << "Not supported through mongos"; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
return Status::OK(); // Require no auth since this command isn't supported in mongos
diff --git a/src/mongo/s/commands_public.cpp b/src/mongo/s/commands_public.cpp
index b98a4413967..4a8c586c15f 100644
--- a/src/mongo/s/commands_public.cpp
+++ b/src/mongo/s/commands_public.cpp
@@ -598,22 +598,29 @@ namespace mongo {
class CreateCmd : public PublicGridCommand {
public:
CreateCmd() : PublicGridCommand( "create" ) {}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
AuthorizationSession* authzSession = client->getAuthorizationSession();
if (cmdObj["capped"].trueValue()) {
if (!authzSession->isAuthorizedForActionsOnResource(
- parseResourcePattern(dbname, cmdObj), ActionType::convertToCapped)) {
+ txn,
+ parseResourcePattern(dbname, cmdObj),
+ ActionType::convertToCapped)) {
return Status(ErrorCodes::Unauthorized, "unauthorized");
}
}
// ActionType::createCollection or ActionType::insert are both acceptable
if (authzSession->isAuthorizedForActionsOnResource(
- parseResourcePattern(dbname, cmdObj), ActionType::createCollection) ||
+ txn,
+ parseResourcePattern(dbname, cmdObj),
+ ActionType::createCollection) ||
authzSession->isAuthorizedForActionsOnResource(
- parseResourcePattern(dbname, cmdObj), ActionType::insert)) {
+ txn,
+ parseResourcePattern(dbname, cmdObj),
+ ActionType::insert)) {
return Status::OK();
}
@@ -749,12 +756,12 @@ namespace mongo {
class RenameCollectionCmd : public PublicGridCommand {
public:
RenameCollectionCmd() : PublicGridCommand( "renameCollection" ) {}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
- return rename_collection::checkAuthForRenameCollectionCommand(client,
- dbname,
- cmdObj);
+ return rename_collection::checkAuthForRenameCollectionCommand(
+ txn, client, dbname, cmdObj);
}
virtual bool adminOnly() const {
return true;
@@ -787,10 +794,11 @@ namespace mongo {
virtual bool adminOnly() const {
return true;
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
- return copydb::checkAuthForCopydbCommand(client, dbname, cmdObj);
+ return copydb::checkAuthForCopydbCommand(txn, client, dbname, cmdObj);
}
bool run(OperationContext* txn, const string& dbName, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string todb = cmdObj.getStringField("todb");
@@ -1267,10 +1275,12 @@ namespace mongo {
public:
SplitVectorCmd() : NotAllowedOnShardedCollectionCmd("splitVector") {}
virtual bool passOptions() const { return true; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname,
cmdObj))),
ActionType::splitVector)) {
diff --git a/src/mongo/s/cursors.cpp b/src/mongo/s/cursors.cpp
index e13b5be44d3..5e1a26822f5 100644
--- a/src/mongo/s/cursors.cpp
+++ b/src/mongo/s/cursors.cpp
@@ -45,6 +45,7 @@
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/max_time.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/util/concurrency/task.h"
#include "mongo/util/net/listen.h"
@@ -338,10 +339,12 @@ namespace mongo {
{
scoped_lock lk( _mutex );
+ OperationContextNoop txn;
+
MapSharded::iterator i = _cursors.find( id );
if ( i != _cursors.end() ) {
const bool isAuthorized = authSession->isAuthorizedForActionsOnNamespace(
- NamespaceString(i->second->getNS()), ActionType::killCursors);
+ &txn, NamespaceString(i->second->getNS()), ActionType::killCursors);
audit::logKillCursorsAuthzCheck(
client,
NamespaceString(i->second->getNS()),
@@ -362,7 +365,7 @@ namespace mongo {
}
verify(refsNSIt != _refsNS.end());
const bool isAuthorized = authSession->isAuthorizedForActionsOnNamespace(
- NamespaceString(refsNSIt->second), ActionType::killCursors);
+ &txn, NamespaceString(refsNSIt->second), ActionType::killCursors);
audit::logKillCursorsAuthzCheck(
client,
NamespaceString(refsNSIt->second),
diff --git a/src/mongo/s/d_merge.cpp b/src/mongo/s/d_merge.cpp
index 748327e7d57..0d0f11c6469 100644
--- a/src/mongo/s/d_merge.cpp
+++ b/src/mongo/s/d_merge.cpp
@@ -28,6 +28,7 @@
#include "mongo/base/owned_pointer_vector.h"
#include "mongo/db/d_concurrency.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/namespace_string.h"
#include "mongo/s/d_logic.h"
#include "mongo/s/distlock.h"
@@ -290,7 +291,8 @@ namespace mongo {
//
{
- Lock::DBWrite writeLk( nss.ns() );
+ OperationContextImpl txn; // XXX?
+ Lock::DBWrite writeLk(txn.lockState(), nss.ns());
shardingState.mergeChunks( nss.ns(), minKey, maxKey, mergeVersion );
}
diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp
index e0c8a6f5bca..4e11efc9c39 100644
--- a/src/mongo/s/d_migrate.cpp
+++ b/src/mongo/s/d_migrate.cpp
@@ -369,7 +369,7 @@ namespace mongo {
* called from the dest of a migrate
* transfers mods from src to dest
*/
- bool transferMods( string& errmsg , BSONObjBuilder& b ) {
+ bool transferMods(OperationContext* txn, string& errmsg, BSONObjBuilder& b) {
if ( ! _getActive() ) {
errmsg = "no active migration!";
return false;
@@ -378,7 +378,7 @@ namespace mongo {
long long size = 0;
{
- Client::ReadContext cx( _ns );
+ Client::ReadContext cx(txn, _ns);
xfer( cx.ctx().db(), &_deleted, b, "deleted", size, false );
xfer( cx.ctx().db(), &_reload, b, "reload", size, true );
@@ -396,8 +396,11 @@ namespace mongo {
* @param errmsg filled with textual description of error if this call return false
* @return false if approximate chunk size is too big to move or true otherwise
*/
- bool storeCurrentLocs( long long maxChunkSize , string& errmsg , BSONObjBuilder& result ) {
- Client::ReadContext ctx( _ns );
+ bool storeCurrentLocs(OperationContext* txn,
+ long long maxChunkSize,
+ string& errmsg,
+ BSONObjBuilder& result ) {
+ Client::ReadContext ctx(txn, _ns);
Collection* collection = ctx.ctx().db()->getCollection( _ns );
if ( !collection ) {
errmsg = "ns not found, should be impossible";
@@ -405,7 +408,7 @@ namespace mongo {
}
invariant( _dummyRunner.get() == NULL );
- _dummyRunner.reset( new DummyRunner( _ns, collection ) );
+ _dummyRunner.reset(new DummyRunner(txn, _ns, collection));
// Allow multiKey based on the invariant that shard keys must be single-valued.
// Therefore, any multi-key index prefixed by shard key cannot be multikey over
@@ -476,7 +479,7 @@ namespace mongo {
return true;
}
- bool clone( string& errmsg , BSONObjBuilder& result ) {
+ bool clone(OperationContext* txn, string& errmsg , BSONObjBuilder& result ) {
if ( ! _getActive() ) {
errmsg = "not active";
return false;
@@ -486,7 +489,7 @@ namespace mongo {
int allocSize;
{
- Client::ReadContext ctx( _ns );
+ Client::ReadContext ctx(txn, _ns);
Collection* collection = ctx.ctx().db()->getCollection( _ns );
verify( collection );
scoped_spinlock lk( _trackerLocks );
@@ -499,7 +502,7 @@ namespace mongo {
while ( 1 ) {
bool filledBuffer = false;
- Client::ReadContext ctx( _ns );
+ Client::ReadContext ctx(txn, _ns);
Collection* collection = ctx.ctx().db()->getCollection( _ns );
scoped_spinlock lk( _trackerLocks );
@@ -613,16 +616,18 @@ namespace mongo {
class DummyRunner : public Runner {
public:
- DummyRunner( const StringData& ns,
- Collection* collection ) {
+ DummyRunner(OperationContext* txn,
+ const StringData& ns,
+ Collection* collection ) {
_ns = ns.toString();
+ _txn = txn;
_collection = collection;
_collection->cursorCache()->registerRunner( this );
}
~DummyRunner() {
if ( !_collection )
return;
- Client::ReadContext ctx( _ns );
+ Client::ReadContext ctx(_txn, _ns);
Collection* collection = ctx.ctx().db()->getCollection( _ns );
invariant( _collection == collection );
_collection->cursorCache()->deregisterRunner( this );
@@ -657,6 +662,7 @@ namespace mongo {
private:
string _ns;
+ OperationContext* _txn;
Collection* _collection;
};
@@ -712,7 +718,7 @@ namespace mongo {
out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
}
bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- return migrateFromStatus.transferMods( errmsg, result );
+ return migrateFromStatus.transferMods(txn, errmsg, result);
}
} transferModsCommand;
@@ -729,7 +735,7 @@ namespace mongo {
out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
}
bool run(OperationContext* txn, const string& , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- return migrateFromStatus.clone( errmsg, result );
+ return migrateFromStatus.clone(txn, errmsg, result);
}
} initialCloneCommand;
@@ -757,10 +763,12 @@ namespace mongo {
virtual bool slaveOk() const { return false; }
virtual bool adminOnly() const { return true; }
virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
ActionType::moveChunk)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
@@ -1041,8 +1049,9 @@ namespace mongo {
{
// this gets a read lock, so we know we have a checkpoint for mods
- if ( ! migrateFromStatus.storeCurrentLocs( maxChunkSize , errmsg , result ) )
+ if (!migrateFromStatus.storeCurrentLocs(txn, maxChunkSize, errmsg, result)) {
return false;
+ }
ScopedDbConnection connTo(toShard.getConnString());
BSONObj res;
@@ -1203,7 +1212,7 @@ namespace mongo {
myVersion.incMajor();
{
- Lock::DBWrite lk( ns );
+ Lock::DBWrite lk(txn->lockState(), ns );
verify( myVersion > shardingState.getVersion( ns ) );
// bump the metadata's version up and "forget" about the chunk being moved
@@ -1586,7 +1595,7 @@ namespace mongo {
if ( state != DONE ) {
// Unprotect the range if needed/possible on unsuccessful TO migration
- Lock::DBWrite lk( ns );
+ Lock::DBWrite lk(txn->lockState(), ns);
string errMsg;
if ( !shardingState.forgetPending( ns, min, max, epoch, &errMsg ) ) {
warning() << errMsg << endl;
@@ -1617,7 +1626,7 @@ namespace mongo {
{
// 0. copy system.namespaces entry if collection doesn't already exist
- Client::WriteContext ctx( ns );
+ Client::WriteContext ctx(txn, ns );
// Only copy if ns doesn't already exist
Database* db = ctx.ctx().db();
Collection* collection = db->getCollection( ns );
@@ -1652,7 +1661,7 @@ namespace mongo {
for ( unsigned i=0; i<all.size(); i++ ) {
BSONObj idx = all[i];
- Client::WriteContext ctx( ns );
+ Client::WriteContext ctx(txn, ns );
Database* db = ctx.ctx().db();
Collection* collection = db->getCollection( txn, ns );
if ( !collection ) {
@@ -1702,7 +1711,7 @@ namespace mongo {
{
// Protect the range by noting that we're now starting a migration to it
- Lock::DBWrite lk( ns );
+ Lock::DBWrite lk(txn->lockState(), ns);
if ( !shardingState.notePending( ns, min, max, epoch, &errmsg ) ) {
warning() << errmsg << endl;
state = FAIL;
@@ -1748,7 +1757,7 @@ namespace mongo {
while( i.more() ) {
BSONObj o = i.next().Obj();
{
- Client::WriteContext cx( ns );
+ Client::WriteContext cx(txn, ns );
BSONObj localDoc;
if ( willOverrideLocalId( cx.ctx().db(), o, &localDoc ) ) {
@@ -1943,7 +1952,7 @@ namespace mongo {
BSONObjIterator i( xfer["deleted"].Obj() );
while ( i.more() ) {
- Client::WriteContext cx(ns);
+ Client::WriteContext cx(txn, ns);
BSONObj id = i.next().Obj();
@@ -1978,7 +1987,7 @@ namespace mongo {
if ( xfer["reload"].isABSONObj() ) {
BSONObjIterator i( xfer["reload"].Obj() );
while ( i.more() ) {
- Client::WriteContext cx(ns);
+ Client::WriteContext cx(txn, ns);
BSONObj it = i.next().Obj();
diff --git a/src/mongo/s/d_split.cpp b/src/mongo/s/d_split.cpp
index 04e17d553e3..8d54a271e4c 100644
--- a/src/mongo/s/d_split.cpp
+++ b/src/mongo/s/d_split.cpp
@@ -119,7 +119,7 @@ namespace mongo {
return false;
}
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
if ( !collection ) {
errmsg = "ns not found";
@@ -223,10 +223,12 @@ namespace mongo {
" 'force' will produce one split point even if data is small; defaults to false\n"
"NOTE: This command may take a while to run";
}
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
ActionType::splitVector)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
@@ -275,7 +277,7 @@ namespace mongo {
{
// Get the size estimate for this namespace
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
if ( !collection ) {
errmsg = "ns not found";
@@ -515,10 +517,12 @@ namespace mongo {
virtual bool slaveOk() const { return false; }
virtual bool adminOnly() const { return true; }
virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
ActionType::splitChunk)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
@@ -824,7 +828,7 @@ namespace mongo {
maxVersion.incMinor();
{
- Lock::DBWrite writeLk( ns );
+ Lock::DBWrite writeLk(txn->lockState(), ns);
shardingState.splitChunk( ns , min , max , splitKeys , maxVersion );
}
@@ -858,7 +862,7 @@ namespace mongo {
// If one of the chunks has only one object in it we should move it
for (int i=1; i >= 0 ; i--){ // high chunk more likely to have only one obj
- Client::ReadContext ctx( ns );
+ Client::ReadContext ctx(txn, ns);
Collection* collection = ctx.ctx().db()->getCollection( ns );
verify( collection );
diff --git a/src/mongo/s/d_state.cpp b/src/mongo/s/d_state.cpp
index c70ca52ea55..8b7d8990d18 100644
--- a/src/mongo/s/d_state.cpp
+++ b/src/mongo/s/d_state.cpp
@@ -48,6 +48,7 @@
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/db.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/wire_version.h"
#include "mongo/db/repl/is_master.h"
#include "mongo/client/connpool.h"
@@ -60,7 +61,6 @@
#include "mongo/util/concurrency/mutex.h"
#include "mongo/util/concurrency/ticketholder.h"
-using namespace std;
namespace mongo {
@@ -558,7 +558,8 @@ namespace mongo {
{
// DBLock needed since we're now potentially changing the metadata, and don't want
// reads/writes to be ongoing.
- Lock::DBWrite writeLk( ns );
+ OperationContextImpl txn;
+ Lock::DBWrite writeLk(txn.lockState(), ns );
//
// Get the metadata now that the load has completed
@@ -1183,10 +1184,12 @@ namespace mongo {
virtual bool isWriteCommandForConfigServer() const { return false; }
- virtual Status checkAuthForCommand(ClientBasic* client,
+ virtual Status checkAuthForCommand(OperationContext* txn,
+ ClientBasic* client,
const std::string& dbname,
const BSONObj& cmdObj) {
if (!client->getAuthorizationSession()->isAuthorizedForActionsOnResource(
+ txn,
ResourcePattern::forExactNamespace(NamespaceString(parseNs(dbname, cmdObj))),
ActionType::getShardVersion)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
@@ -1241,7 +1244,7 @@ namespace mongo {
}
bool run(OperationContext* txn, const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
- Lock::DBWrite dbXLock(dbname);
+ Lock::DBWrite dbXLock(txn->lockState(), dbname);
Client::Context ctx(dbname);
shardingState.appendInfo( result );
diff --git a/src/mongo/s/request.cpp b/src/mongo/s/request.cpp
index 73f891368d4..c4916fc2438 100644
--- a/src/mongo/s/request.cpp
+++ b/src/mongo/s/request.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
#include "mongo/db/dbmessage.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/db/stats/counters.h"
#include "mongo/s/chunk.h"
#include "mongo/s/client_info.h"
@@ -52,6 +53,8 @@ namespace mongo {
verify( _d.getns() );
_id = _m.header()->id;
+ _txn.reset(new OperationContextNoop());
+
_clientInfo = ClientInfo::get();
if ( p ) {
_clientInfo->newPeerRequest( p->remote() );
@@ -66,7 +69,7 @@ namespace mongo {
return;
_didInit = true;
reset();
- _clientInfo->getAuthorizationSession()->startRequest();
+ _clientInfo->getAuthorizationSession()->startRequest(_txn.get());
}
// Deprecated, will move to the strategy itself
diff --git a/src/mongo/s/request.h b/src/mongo/s/request.h
index 3e494952005..7ca59139e66 100644
--- a/src/mongo/s/request.h
+++ b/src/mongo/s/request.h
@@ -41,6 +41,8 @@ namespace mongo {
class OpCounters;
class ClientInfo;
+ class OperationContext;
+
class Request : boost::noncopyable {
public:
@@ -93,6 +95,8 @@ namespace mongo {
OpCounters* _counter;
+ boost::scoped_ptr<OperationContext> _txn;
+
bool _didInit;
};
diff --git a/src/mongo/s/s_only.cpp b/src/mongo/s/s_only.cpp
index bb6aeba7f17..a102d0ce836 100644
--- a/src/mongo/s/s_only.cpp
+++ b/src/mongo/s/s_only.cpp
@@ -134,7 +134,7 @@ namespace mongo {
return;
}
- Status status = _checkAuthorization(c, &client, dbname, cmdObj, fromRepl);
+ Status status = _checkAuthorization(txn, c, &client, dbname, cmdObj, fromRepl);
if (!status.isOK()) {
appendCommandStatus(result, status);
return;
diff --git a/src/mongo/s/strategy.cpp b/src/mongo/s/strategy.cpp
index fcca41f719d..8fe822f4645 100644
--- a/src/mongo/s/strategy.cpp
+++ b/src/mongo/s/strategy.cpp
@@ -40,6 +40,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/commands.h"
#include "mongo/db/max_time.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/db/server_parameters.h"
#include "mongo/db/structure/catalog/index_details.h"
#include "mongo/db/namespace_string.h"
@@ -127,7 +128,9 @@ namespace mongo {
NamespaceString ns(q.ns);
ClientBasic* client = ClientBasic::getCurrent();
AuthorizationSession* authSession = client->getAuthorizationSession();
- Status status = authSession->checkAuthForQuery(ns, q.query);
+
+ OperationContextNoop txn;
+ Status status = authSession->checkAuthForQuery(&txn, ns, q.query);
audit::logQueryAuthzCheck(client, ns, q.query, status.code());
uassertStatusOK(status);
@@ -299,8 +302,9 @@ namespace mongo {
ClientBasic* client = ClientBasic::getCurrent();
AuthorizationSession* authSession = client->getAuthorizationSession();
if ( strcmp( ns , "inprog" ) == 0 ) {
+ OperationContextNoop txn;
const bool isAuthorized = authSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::inprog);
+ &txn, ResourcePattern::forClusterResource(), ActionType::inprog);
audit::logInProgAuthzCheck(
client, q.query, isAuthorized ? ErrorCodes::OK : ErrorCodes::Unauthorized);
uassert(ErrorCodes::Unauthorized, "not authorized to run inprog", isAuthorized);
@@ -342,8 +346,9 @@ namespace mongo {
arr.done();
}
else if ( strcmp( ns , "killop" ) == 0 ) {
+ OperationContextNoop txn;
const bool isAuthorized = authSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forClusterResource(), ActionType::killop);
+ &txn, ResourcePattern::forClusterResource(), ActionType::killop);
audit::logKillOpAuthzCheck(
client,
q.query,
@@ -453,7 +458,9 @@ namespace mongo {
ClientBasic* client = ClientBasic::getCurrent();
NamespaceString nsString(ns);
AuthorizationSession* authSession = client->getAuthorizationSession();
- Status status = authSession->checkAuthForGetMore( nsString, id );
+
+ OperationContextNoop txn;
+ Status status = authSession->checkAuthForGetMore(&txn, nsString, id );
audit::logGetMoreAuthzCheck( client, nsString, id, status.code() );
uassertStatusOK(status);
diff --git a/src/mongo/tools/dump.cpp b/src/mongo/tools/dump.cpp
index a7672e0b722..f699e76585e 100644
--- a/src/mongo/tools/dump.cpp
+++ b/src/mongo/tools/dump.cpp
@@ -41,6 +41,7 @@
#include "mongo/db/catalog/database_catalog_entry.h"
#include "mongo/db/db.h"
#include "mongo/db/namespace_string.h"
+#include "mongo/db/operation_context_impl.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/tools/mongodump_options.h"
#include "mongo/tools/tool.h"
@@ -252,7 +253,7 @@ public:
int repair() {
toolInfoLog() << "going to try and recover data from: " << toolGlobalParams.db << std::endl;
- return _repair(toolGlobalParams.db);
+ return _repairByName(toolGlobalParams.db);
}
void _repairExtents(Collection* coll, Writer& writer) {
@@ -330,9 +331,11 @@ public:
<< std::endl;
}
- int _repair( string dbname ) {
- Client::WriteContext cx( dbname );
- Database * db = cx.ctx().db();
+ int _repairByName(string dbname) {
+ OperationContextImpl txn;
+ Client::WriteContext cx(&txn, dbname);
+
+ Database* db = dbHolderUnchecked().get(dbname, storageGlobalParams.dbpath);
list<string> namespaces;
db->getDatabaseCatalogEntry()->getCollectionNamespaces( &namespaces );
diff --git a/src/mongo/util/admin_access.h b/src/mongo/util/admin_access.h
index 115004427b0..6f9834147df 100644
--- a/src/mongo/util/admin_access.h
+++ b/src/mongo/util/admin_access.h
@@ -36,6 +36,8 @@
namespace mongo {
+ class OperationContext;
+
/*
* An AdminAccess is an interface class used to determine if certain users have
* privileges to a given resource.
@@ -48,14 +50,14 @@ namespace mongo {
/** @return if there are any priviledge users. This should not
* block for long and throw if can't get a lock if needed.
*/
- virtual bool haveAdminUsers() const = 0;
+ virtual bool haveAdminUsers(OperationContext* txn) const = 0;
};
class NoAdminAccess : public AdminAccess {
public:
virtual ~NoAdminAccess() { }
- virtual bool haveAdminUsers() const { return false; }
+ virtual bool haveAdminUsers(OperationContext* txn) const { return false; }
};
} // namespace mongo