diff options
author | Alberto Lerner <alerner@10gen.com> | 2012-10-11 19:07:14 -0400 |
---|---|---|
committer | Alberto Lerner <alerner@10gen.com> | 2012-10-12 14:58:13 -0400 |
commit | 75bc746a2340ede9c97ed0d75de6d3430a18b376 (patch) | |
tree | 4698a25ea9676a0869148e79df390666122bc5be | |
parent | 60c65832ded36de7306678e09e77760248cd935e (diff) | |
download | mongo-75bc746a2340ede9c97ed0d75de6d3430a18b376.tar.gz |
SERVER-7186 Optimized logging of push and addToSet update modifiers.
-rw-r--r-- | src/mongo/db/ops/update_internal.cpp | 42 | ||||
-rw-r--r-- | src/mongo/db/ops/update_internal.h | 4 | ||||
-rw-r--r-- | src/mongo/dbtests/repltests.cpp | 18 | ||||
-rw-r--r-- | src/mongo/dbtests/updatetests.cpp | 4 |
4 files changed, 58 insertions, 10 deletions
diff --git a/src/mongo/db/ops/update_internal.cpp b/src/mongo/db/ops/update_internal.cpp index dccc22e0175..5486b0a3466 100644 --- a/src/mongo/db/ops/update_internal.cpp +++ b/src/mongo/db/ops/update_internal.cpp @@ -21,6 +21,7 @@ #include "mongo/db/oplog.h" #include "mongo/db/jsobjmanipulator.h" #include "mongo/db/pdfile.h" +#include "mongo/util/mongoutils/str.h" #include "update_internal.h" @@ -124,9 +125,21 @@ namespace mongo { } bb.append( elt ); - ms.fixedOpName = "$set"; - ms.forceEmptyArray = true; - ms.fixedArray = BSONArray(bb.done().getOwned()); + + // We don't want to log a $set for which the '_checkForAppending' test won't pass. If we're + // in that case, fall back to non-optimized logging. + if ( (elt.type() == Object && elt.embeddedObject().okForStorage()) || (elt.type() != Object) ) { + ms.fixedOpName = "$set"; + ms.forcePositional = true; + ms.position = bb.arrSize() - 1; + bb.done(); + } + else { + ms.fixedOpName = "$set"; + ms.forceEmptyArray = true; + ms.fixedArray = BSONArray( bb.done().getOwned() ); + } + break; } @@ -157,6 +170,9 @@ namespace mongo { } } + ms.fixedOpName = "$set"; + ms.forceEmptyArray = true; + ms.fixedArray = BSONArray(bb.done().getOwned()); } else { @@ -169,14 +185,20 @@ namespace mongo { found = true; } - if ( ! found ) + if ( ! found ) { bb.append( elt ); - + ms.fixedOpName = "$set"; + ms.forcePositional = true; + ms.position = bb.arrSize() - 1; + bb.done(); + + } else { + ms.fixedOpName = "$set"; + ms.forceEmptyArray = true; + ms.fixedArray = BSONArray(bb.done().getOwned()); + } } - ms.fixedOpName = "$set"; - ms.forceEmptyArray = true; - ms.fixedArray = BSONArray(bb.done().getOwned()); break; } @@ -568,6 +590,10 @@ namespace mongo { else if ( ! fixedArray.isEmpty() || forceEmptyArray ) { bb.append( m->fieldName, fixedArray ); } + else if ( forcePositional ) { + string positionalField = str::stream() << m->fieldName << "." << position; + bb.appendAs( m->elt, positionalField.c_str() ); + } else { bb.appendAs( m->elt , m->fieldName ); } diff --git a/src/mongo/db/ops/update_internal.h b/src/mongo/db/ops/update_internal.h index e3aa8c8dcf9..1b8f27bb700 100644 --- a/src/mongo/db/ops/update_internal.h +++ b/src/mongo/db/ops/update_internal.h @@ -401,6 +401,8 @@ namespace mongo { BSONElement* fixed; BSONArray fixedArray; bool forceEmptyArray; + bool forcePositional; + int position; int DEPRECATED_pushStartSize; BSONType incType; @@ -414,6 +416,8 @@ namespace mongo { fixedOpName = 0; fixed = 0; forceEmptyArray = false; + forcePositional = false; + position = 0; DEPRECATED_pushStartSize = -1; incType = EOO; dontApply = false; diff --git a/src/mongo/dbtests/repltests.cpp b/src/mongo/dbtests/repltests.cpp index 836670240a6..d3b131a5a41 100644 --- a/src/mongo/dbtests/repltests.cpp +++ b/src/mongo/dbtests/repltests.cpp @@ -815,6 +815,23 @@ namespace ReplTests { } }; + class PushWithDollarSigns : public Base { + void doIt() const { + client()->update( ns(), + BSON( "_id" << 0), + BSON( "$push" << BSON( "a" << BSON( "$foo" << 1 ) ) ) ); + } + using ReplTests::Base::check; + void check() const { + ASSERT_EQUALS( 1, count() ); + check( fromjson( "{'_id':0, a:[0, {'$foo':1}]}"), one( fromjson( "{'_id':0}" ) ) ); + } + void reset() const { + deleteAll( ns() ); + insert( BSON( "_id" << 0 << "a" << BSON_ARRAY( 0 ) ) ); + } + }; + class PushAllUpsert : public Base { public: void doIt() const { @@ -1288,6 +1305,7 @@ namespace ReplTests { add< Idempotence::EmptyPush >(); add< Idempotence::EmptyPushSparseIndex >(); add< Idempotence::PushAll >(); + add< Idempotence::PushWithDollarSigns >(); add< Idempotence::PushAllUpsert >(); add< Idempotence::EmptyPushAll >(); add< Idempotence::Pull >(); diff --git a/src/mongo/dbtests/updatetests.cpp b/src/mongo/dbtests/updatetests.cpp index 28efdfe5787..a014eefe9f9 100644 --- a/src/mongo/dbtests/updatetests.cpp +++ b/src/mongo/dbtests/updatetests.cpp @@ -722,7 +722,7 @@ namespace UpdateTests { auto_ptr<ModSetState> modSetState = modSet.prepare( obj ); ASSERT_FALSE( modSetState->canApplyInPlace() ); modSetState->createNewFromMods(); - ASSERT_EQUALS( BSON( "$set" << BSON( "a" << BSON_ARRAY( 1 << 2 << 3 ) ) ), + ASSERT_EQUALS( BSON( "$set" << BSON( "a.2" << 3 ) ), modSetState->getOpLogRewrite() ); } }; @@ -949,7 +949,7 @@ namespace UpdateTests { auto_ptr<ModSetState> modSetState = modSet.prepare( obj ); ASSERT_FALSE( modSetState->canApplyInPlace() ); modSetState->createNewFromMods(); - ASSERT_EQUALS( BSON( "$set" << BSON( "a" << BSON_ARRAY( 1 << 2 ) ) ), + ASSERT_EQUALS( BSON( "$set" << BSON( "a.1" << 2 ) ), modSetState->getOpLogRewrite() ); } }; |