diff options
author | Mathias Stearn <mathias@10gen.com> | 2015-04-29 19:47:42 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2015-05-08 14:27:27 -0400 |
commit | c5f317f59e41caffcd3972bc741abaa649229a5b (patch) | |
tree | ff30f65ab46d8cfbe9f4ff81d6a82fec0ad43b86 | |
parent | 849b8f436a5178c5be6afc2a49e9a4d1ecf5d92b (diff) | |
download | mongo-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/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/catalog/capped_utils.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection.h | 6 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_compact.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/catalog/document_validation.cpp | 36 | ||||
-rw-r--r-- | src/mongo/db/catalog/document_validation.h | 63 | ||||
-rw-r--r-- | src/mongo/db/catalog/rename_collection.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/repair_database.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/repl/master_slave.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/rs_initialsync.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/rs_rollback.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/repl/sync_tail.cpp | 4 | ||||
-rw-r--r-- | src/mongo/s/d_migrate.cpp | 3 |
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; |