diff options
author | Mathias Stearn <mathias@10gen.com> | 2015-05-11 17:36:52 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2015-05-14 18:59:03 -0400 |
commit | 463d3343d559590d60cfd5c48ac98ad675d5390e (patch) | |
tree | 5ab045f64656074016c08229ae0bcc6734579e6e /src/mongo/db/pipeline | |
parent | 22de12dd4ac510cd2a37b643eb528673f651e21b (diff) | |
download | mongo-463d3343d559590d60cfd5c48ac98ad675d5390e.tar.gz |
SERVER-18227 Add bypassDocumentValidation option to commands that need it
Diffstat (limited to 'src/mongo/db/pipeline')
-rw-r--r-- | src/mongo/db/pipeline/document_source.h | 7 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_context.h | 20 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline_d.cpp | 18 |
5 files changed, 47 insertions, 21 deletions
diff --git a/src/mongo/db/pipeline/document_source.h b/src/mongo/db/pipeline/document_source.h index a2b6c2225da..fd88833611d 100644 --- a/src/mongo/db/pipeline/document_source.h +++ b/src/mongo/db/pipeline/document_source.h @@ -233,6 +233,11 @@ namespace mongo { virtual bool isCapped(const NamespaceString& ns) = 0; + /** + * Inserts 'objs' into 'ns' and returns the "detailed" last error object. + */ + virtual BSONObj insert(const NamespaceString& ns, const std::vector<BSONObj>& objs) = 0; + // Add new methods as needed. }; @@ -711,7 +716,7 @@ namespace mongo { // Sets _tempsNs and prepares it to receive data. void prepTempCollection(); - void spill(DBClientBase* conn, const std::vector<BSONObj>& toInsert); + void spill(const std::vector<BSONObj>& toInsert); bool _done; diff --git a/src/mongo/db/pipeline/document_source_out.cpp b/src/mongo/db/pipeline/document_source_out.cpp index fb58cb1565a..bdb8d1d7055 100644 --- a/src/mongo/db/pipeline/document_source_out.cpp +++ b/src/mongo/db/pipeline/document_source_out.cpp @@ -109,9 +109,8 @@ namespace mongo { } } - void DocumentSourceOut::spill(DBClientBase* conn, const vector<BSONObj>& toInsert) { - conn->insert(_tempNs.ns(), toInsert); - BSONObj err = conn->getLastErrorDetailed(); + void DocumentSourceOut::spill(const vector<BSONObj>& toInsert) { + BSONObj err = _mongod->insert(_tempNs, toInsert); uassert(16996, str::stream() << "insert for $out failed: " << err, DBClientWithCommands::getLastErrorString(err).empty()); } @@ -136,7 +135,7 @@ namespace mongo { BSONObj toInsert = next->toBson(); bufferedBytes += toInsert.objsize(); if (!bufferedObjects.empty() && bufferedBytes > BSONObjMaxUserSize) { - spill(conn, bufferedObjects); + spill(bufferedObjects); bufferedObjects.clear(); bufferedBytes = toInsert.objsize(); } @@ -144,7 +143,7 @@ namespace mongo { } if (!bufferedObjects.empty()) - spill(conn, bufferedObjects); + spill(bufferedObjects); // Checking again to make sure we didn't become sharded while running. uassert(17018, str::stream() << "namespace '" << _outputNs.ns() diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h index 5b4b6f55acf..96cce9e4b4f 100644 --- a/src/mongo/db/pipeline/expression_context.h +++ b/src/mongo/db/pipeline/expression_context.h @@ -39,12 +39,8 @@ namespace mongo { struct ExpressionContext : public IntrusiveCounterUnsigned { public: ExpressionContext(OperationContext* opCtx, const NamespaceString& ns) - : inShard(false) - , inRouter(false) - , extSortAllowed(false) - , ns(ns) + : ns(ns) , opCtx(opCtx) - , interruptCounter(interruptCheckPeriod) {} /** Used by a pipeline to check for interrupts so that killOp() works. @@ -54,18 +50,20 @@ namespace mongo { if (opCtx && --interruptCounter == 0) { // XXX SERVER-13931 for opCtx check // The checkForInterrupt could be expensive, at least in relative terms. opCtx->checkForInterrupt(); - interruptCounter = interruptCheckPeriod; + interruptCounter = kInterruptCheckPeriod; } } - bool inShard; - bool inRouter; - bool extSortAllowed; + bool inShard = false; + bool inRouter = false; + bool extSortAllowed = false; + bool bypassDocumentValidation = false; + NamespaceString ns; std::string tempDir; // Defaults to empty to prevent external sorting in mongos. OperationContext* opCtx; - static const int interruptCheckPeriod = 128; - int interruptCounter; // when 0, check interruptStatus + static const int kInterruptCheckPeriod = 128; + int interruptCounter = kInterruptCheckPeriod; // when 0, check interruptStatus }; } diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp index de7b7590bff..4804189982d 100644 --- a/src/mongo/db/pipeline/pipeline.cpp +++ b/src/mongo/db/pipeline/pipeline.cpp @@ -34,6 +34,7 @@ #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/privilege.h" +#include "mongo/db/catalog/document_validation.h" #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" #include "mongo/db/pipeline/accumulator.h" @@ -162,6 +163,11 @@ namespace mongo { continue; } + if (pFieldName == bypassDocumentValidationCommandOption()) { + pCtx->bypassDocumentValidation = cmdElement.trueValue(); + continue; + } + /* we didn't recognize a field in the command */ ostringstream sb; sb << "unrecognized field '" << cmdElement.fieldName() << "'"; @@ -353,6 +359,10 @@ namespace mongo { ActionSet actions; actions.addAction(ActionType::remove); actions.addAction(ActionType::insert); + if (shouldBypassDocumentValidationforCommand(cmdObj)) { + actions.addAction(ActionType::bypassDocumentValidation); + } + out->push_back(Privilege(ResourcePattern::forExactNamespace(outputNs), actions)); } } @@ -481,6 +491,10 @@ namespace mongo { serialized.setField("allowDiskUse", Value(true)); } + if (pCtx->bypassDocumentValidation) { + serialized.setField(bypassDocumentValidationCommandOption(), Value(true)); + } + return serialized.freeze(); } diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp index 51a4a6ef4cd..2709cc7f8d5 100644 --- a/src/mongo/db/pipeline/pipeline_d.cpp +++ b/src/mongo/db/pipeline/pipeline_d.cpp @@ -36,6 +36,7 @@ #include "mongo/client/dbclientinterface.h" #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/database.h" +#include "mongo/db/catalog/document_validation.h" #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/pipeline/document_source.h" @@ -51,31 +52,40 @@ namespace mongo { using std::string; namespace { - class MongodImplementation : public DocumentSourceNeedsMongod::MongodInterface { + class MongodImplementation final : public DocumentSourceNeedsMongod::MongodInterface { public: MongodImplementation(const intrusive_ptr<ExpressionContext>& ctx) : _ctx(ctx) , _client(ctx->opCtx) {} - DBClientBase* directClient() { + DBClientBase* directClient() final { // opCtx may have changed since our last call invariant(_ctx->opCtx); _client.setOpCtx(_ctx->opCtx); return &_client; } - bool isSharded(const NamespaceString& ns) { + bool isSharded(const NamespaceString& ns) final { const ChunkVersion unsharded(0, 0, OID()); return !(shardingState.getVersion(ns.ns()).isWriteCompatibleWith(unsharded)); } - bool isCapped(const NamespaceString& ns) { + bool isCapped(const NamespaceString& ns) final { AutoGetCollectionForRead ctx(_ctx->opCtx, ns.ns()); Collection* collection = ctx.getCollection(); return collection && collection->isCapped(); } + BSONObj insert(const NamespaceString& ns, const std::vector<BSONObj>& objs) final { + boost::optional<DisableDocumentValidation> maybeDisableValidation; + if (_ctx->bypassDocumentValidation) + maybeDisableValidation.emplace(_ctx->opCtx); + + _client.insert(ns.ns(), objs); + return _client.getLastErrorDetailed(); + } + private: intrusive_ptr<ExpressionContext> _ctx; DBDirectClient _client; |