summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2015-04-29 19:47:42 -0400
committerMathias Stearn <mathias@10gen.com>2015-05-08 14:27:27 -0400
commitc5f317f59e41caffcd3972bc741abaa649229a5b (patch)
treeff30f65ab46d8cfbe9f4ff81d6a82fec0ad43b86
parent849b8f436a5178c5be6afc2a49e9a4d1ecf5d92b (diff)
downloadmongo-c5f317f59e41caffcd3972bc741abaa649229a5b.tar.gz
SERVER-18227 Add a mechanism to disable document validation and start using it
This does not necessarily cover all places that need to disable validation.
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/catalog/capped_utils.cpp3
-rw-r--r--src/mongo/db/catalog/collection.cpp14
-rw-r--r--src/mongo/db/catalog/collection.h6
-rw-r--r--src/mongo/db/catalog/collection_compact.cpp3
-rw-r--r--src/mongo/db/catalog/document_validation.cpp36
-rw-r--r--src/mongo/db/catalog/document_validation.h63
-rw-r--r--src/mongo/db/catalog/rename_collection.cpp3
-rw-r--r--src/mongo/db/repair_database.cpp3
-rw-r--r--src/mongo/db/repl/master_slave.cpp2
-rw-r--r--src/mongo/db/repl/rs_initialsync.cpp2
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp6
-rw-r--r--src/mongo/db/repl/sync_tail.cpp4
-rw-r--r--src/mongo/s/d_migrate.cpp3
14 files changed, 140 insertions, 9 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 3c30a32b86a..279a203f836 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -499,6 +499,7 @@ serverOnlyFiles = [
"catalog/cursor_manager.cpp",
"catalog/database.cpp",
"catalog/database_holder.cpp",
+ "catalog/document_validation.cpp",
"catalog/drop_collection.cpp",
"catalog/drop_database.cpp",
"catalog/drop_indexes.cpp",
diff --git a/src/mongo/db/catalog/capped_utils.cpp b/src/mongo/db/catalog/capped_utils.cpp
index fc228a02025..92bbba46d0c 100644
--- a/src/mongo/db/catalog/capped_utils.cpp
+++ b/src/mongo/db/catalog/capped_utils.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/background.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/database.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_catalog.h"
#include "mongo/db/client.h"
#include "mongo/db/db_raii.h"
@@ -159,6 +160,8 @@ namespace {
InternalPlanner::FORWARD));
+ DisableDocumentValidation validationDisabler(txn);
+
while (true) {
BSONObj obj;
PlanExecutor::ExecState state = exec->getNext(&obj, NULL);
diff --git a/src/mongo/db/catalog/collection.cpp b/src/mongo/db/catalog/collection.cpp
index b4373634413..4a57cc7bbf0 100644
--- a/src/mongo/db/catalog/collection.cpp
+++ b/src/mongo/db/catalog/collection.cpp
@@ -40,6 +40,7 @@
#include "mongo/base/owned_pointer_map.h"
#include "mongo/db/catalog/collection_catalog_entry.h"
#include "mongo/db/catalog/database_catalog_entry.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_create.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands/server_status_metric.h"
@@ -220,10 +221,13 @@ namespace {
return true;
}
- Status Collection::checkValidation(const BSONObj& document) const {
+ Status Collection::checkValidation(OperationContext* txn, const BSONObj& document) const {
if (!_validator)
return Status::OK();
+ if (documentValidationDisabled(txn))
+ return Status::OK();
+
if (_validator->matchesBSON(document))
return Status::OK();
@@ -234,7 +238,7 @@ namespace {
StatusWith<RecordId> Collection::insertDocument(OperationContext* txn,
const DocWriter* doc,
bool enforceQuota) {
- invariant(!_validator);
+ invariant(!_validator || documentValidationDisabled(txn));
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_IX));
invariant( !_indexCatalog.haveAnyIndexes() ); // eventually can implement, just not done
@@ -255,7 +259,7 @@ namespace {
bool enforceQuota,
bool fromMigrate) {
{
- auto status = checkValidation(docToInsert);
+ auto status = checkValidation(txn, docToInsert);
if (!status.isOK())
return status;
}
@@ -286,7 +290,7 @@ namespace {
MultiIndexBlock* indexBlock,
bool enforceQuota) {
{
- auto status = checkValidation(doc);
+ auto status = checkValidation(txn, doc);
if (!status.isOK())
return status;
}
@@ -405,7 +409,7 @@ namespace {
OpDebug* debug,
oplogUpdateEntryArgs& args) {
{
- auto status = checkValidation(newDoc);
+ auto status = checkValidation(txn, newDoc);
if (!status.isOK())
return status;
}
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h
index f515d94e582..26559e1303d 100644
--- a/src/mongo/db/catalog/collection.h
+++ b/src/mongo/db/catalog/collection.h
@@ -175,6 +175,10 @@ namespace mongo {
bool enforceQuota,
bool fromMigrate = false);
+ /**
+ * Callers must ensure no document validation is performed for this collection when calling
+ * this method.
+ */
StatusWith<RecordId> insertDocument( OperationContext* txn,
const DocWriter* doc,
bool enforceQuota );
@@ -300,7 +304,7 @@ namespace mongo {
/**
* Returns a non-ok Status if document does not pass this collection's validator.
*/
- Status checkValidation(const BSONObj& document) const;
+ Status checkValidation(OperationContext* txn, const BSONObj& document) const;
Status recordStoreGoingToMove( OperationContext* txn,
const RecordId& oldLocation,
diff --git a/src/mongo/db/catalog/collection_compact.cpp b/src/mongo/db/catalog/collection_compact.cpp
index 264716ba889..a6f4f98041b 100644
--- a/src/mongo/db/catalog/collection_compact.cpp
+++ b/src/mongo/db/catalog/collection_compact.cpp
@@ -39,6 +39,7 @@
#include "mongo/db/commands/server_status.h"
#include "mongo/db/curop.h"
#include "mongo/db/catalog/database.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_key_validate.h"
#include "mongo/db/index/index_access_method.h"
#include "mongo/db/operation_context.h"
@@ -105,6 +106,8 @@ namespace mongo {
const CompactOptions* compactOptions ) {
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_X));
+ DisableDocumentValidation validationDisabler(txn);
+
if ( !_recordStore->compactSupported() )
return StatusWith<CompactStats>( ErrorCodes::CommandNotSupported,
str::stream() <<
diff --git a/src/mongo/db/catalog/document_validation.cpp b/src/mongo/db/catalog/document_validation.cpp
new file mode 100644
index 00000000000..73a6540a391
--- /dev/null
+++ b/src/mongo/db/catalog/document_validation.cpp
@@ -0,0 +1,36 @@
+/*
+* Copyright (C) 2015 MongoDB Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/catalog/document_validation.h"
+
+namespace mongo {
+ const OperationContext::Decoration<bool> documentValidationDisabled =
+ OperationContext::declareDecoration<bool>();
+}
diff --git a/src/mongo/db/catalog/document_validation.h b/src/mongo/db/catalog/document_validation.h
new file mode 100644
index 00000000000..0f838f6184a
--- /dev/null
+++ b/src/mongo/db/catalog/document_validation.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (C) 2015 MongoDB Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#pragma once
+
+#include "mongo/base/disallow_copying.h"
+#include "mongo/db/operation_context.h"
+
+namespace mongo {
+ /**
+ * If true, Collection should do no validation of writes from this OperationContext.
+ *
+ * Note that Decorations are value-constructed so this defaults to false.
+ */
+ extern const OperationContext::Decoration<bool> documentValidationDisabled;
+
+ /**
+ * Disables document validation on a single OperationContext while in scope.
+ * Resets to original value when leaving scope so they are safe to nest.
+ */
+ class DisableDocumentValidation {
+ MONGO_DISALLOW_COPYING(DisableDocumentValidation);
+ public:
+ DisableDocumentValidation(OperationContext* txn)
+ : _txn(txn)
+ , _initialState(documentValidationDisabled(_txn)) {
+ documentValidationDisabled(_txn) = true;
+ }
+
+ ~DisableDocumentValidation() {
+ documentValidationDisabled(_txn) = _initialState;
+ }
+
+ private:
+ OperationContext* const _txn;
+ const bool _initialState;
+ };
+}
diff --git a/src/mongo/db/catalog/rename_collection.cpp b/src/mongo/db/catalog/rename_collection.cpp
index 8d21fea5d8c..ce08118b107 100644
--- a/src/mongo/db/catalog/rename_collection.cpp
+++ b/src/mongo/db/catalog/rename_collection.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/catalog/collection_catalog_entry.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_catalog.h"
#include "mongo/db/catalog/index_create.h"
#include "mongo/db/client.h"
@@ -88,6 +89,8 @@ namespace {
const NamespaceString& target,
bool dropTarget,
bool stayTemp) {
+ DisableDocumentValidation validationDisabler(txn);
+
ScopedTransaction transaction(txn, MODE_X);
Lock::GlobalWrite globalWriteLock(txn->lockState());
// We stay in source context the whole time. This is mostly to set the CurOp namespace.
diff --git a/src/mongo/db/repair_database.cpp b/src/mongo/db/repair_database.cpp
index 516827a3715..9bbb8da24de 100644
--- a/src/mongo/db/repair_database.cpp
+++ b/src/mongo/db/repair_database.cpp
@@ -43,6 +43,7 @@
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_catalog_entry.h"
#include "mongo/db/catalog/database_holder.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_create.h"
#include "mongo/db/catalog/index_key_validate.h"
#include "mongo/db/storage/mmap_v1/mmap_v1_engine.h"
@@ -176,7 +177,7 @@ namespace {
bool preserveClonedFilesOnFailure,
bool backupOriginalFiles) {
-
+ DisableDocumentValidation validationDisabler(txn);
// We must hold some form of lock here
invariant(txn->lockState()->isLocked());
diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp
index b7b6f5452d0..7d9624f8849 100644
--- a/src/mongo/db/repl/master_slave.cpp
+++ b/src/mongo/db/repl/master_slave.cpp
@@ -51,6 +51,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/database_catalog_entry.h"
#include "mongo/db/catalog/database_holder.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/cloner.h"
#include "mongo/db/commands.h"
#include "mongo/db/db_raii.h"
@@ -1327,6 +1328,7 @@ namespace repl {
OperationContextImpl txn;
AuthorizationSession::get(txn.getClient())->grantInternalAuthorization();
+ DisableDocumentValidation validationDisabler(&txn);
while ( 1 ) {
try {
diff --git a/src/mongo/db/repl/rs_initialsync.cpp b/src/mongo/db/repl/rs_initialsync.cpp
index 3808abbc2cd..22817bc7746 100644
--- a/src/mongo/db/repl/rs_initialsync.cpp
+++ b/src/mongo/db/repl/rs_initialsync.cpp
@@ -37,6 +37,7 @@
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_manager_global.h"
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/client.h"
#include "mongo/db/cloner.h"
#include "mongo/db/db_raii.h"
@@ -346,6 +347,7 @@ namespace {
BackgroundSync* bgsync(BackgroundSync::get());
OperationContextImpl txn;
txn.setReplicatedWrites(false);
+ DisableDocumentValidation validationDisabler(&txn);
ReplicationCoordinator* replCoord(getGlobalReplicationCoordinator());
// reset state for initial sync
diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp
index 865ddda7af7..d79f6cd0ac3 100644
--- a/src/mongo/db/repl/rs_rollback.cpp
+++ b/src/mongo/db/repl/rs_rollback.cpp
@@ -35,15 +35,16 @@
#include <boost/shared_ptr.hpp>
-#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_manager_global.h"
+#include "mongo/db/auth/authorization_manager.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/client.h"
#include "mongo/db/cloner.h"
#include "mongo/db/commands.h"
-#include "mongo/db/db_raii.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/dbhelpers.h"
#include "mongo/db/exec/working_set_common.h"
+#include "mongo/db/db_raii.h"
#include "mongo/db/operation_context_impl.h"
#include "mongo/db/ops/delete.h"
#include "mongo/db/ops/update.h"
@@ -881,6 +882,7 @@ namespace {
log() << "beginning rollback" << rsLog;
+ DisableDocumentValidation validationDisabler(txn);
txn->setReplicatedWrites(false);
unsigned s = _syncRollback(txn, oplogreader, replCoord);
if (s)
diff --git a/src/mongo/db/repl/sync_tail.cpp b/src/mongo/db/repl/sync_tail.cpp
index aa239b0490c..f3d20488f69 100644
--- a/src/mongo/db/repl/sync_tail.cpp
+++ b/src/mongo/db/repl/sync_tail.cpp
@@ -41,6 +41,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/commands/fsync.h"
#include "mongo/db/commands/server_status_metric.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
@@ -211,6 +212,7 @@ namespace repl {
// For non-initial-sync, we convert updates to upserts
// to suppress errors when replaying oplog entries.
txn->setReplicatedWrites(false);
+ DisableDocumentValidation validationDisabler(txn);
Status status = applyOperation_inlock(txn, ctx.db(), op, convertUpdateToUpsert);
opsAppliedStats.increment();
@@ -667,6 +669,7 @@ namespace {
OperationContextImpl txn;
txn.setReplicatedWrites(false);
+ DisableDocumentValidation validationDisabler(&txn);
// allow us to get through the magic barrier
txn.lockState()->setIsBatchWriter(true);
@@ -700,6 +703,7 @@ namespace {
OperationContextImpl txn;
txn.setReplicatedWrites(false);
+ DisableDocumentValidation validationDisabler(&txn);
// allow us to get through the magic barrier
txn.lockState()->setIsBatchWriter(true);
diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp
index 8180bdf8b32..6552842b5f1 100644
--- a/src/mongo/s/d_migrate.cpp
+++ b/src/mongo/s/d_migrate.cpp
@@ -53,6 +53,7 @@
#include "mongo/db/auth/authorization_manager_global.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
+#include "mongo/db/catalog/document_validation.h"
#include "mongo/db/catalog/index_create.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands.h"
@@ -1937,6 +1938,8 @@ namespace mongo {
verify( ! min.isEmpty() );
verify( ! max.isEmpty() );
+ DisableDocumentValidation validationDisabler(txn);
+
log() << "starting receiving-end of migration of chunk " << min << " -> " << max <<
" for collection " << ns << " from " << fromShard
<< " at epoch " << epoch.toString() << endl;