0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

tiny bit faster updates when no match or upsert perhaps

This commit is contained in:
dwight 2011-05-07 13:03:56 -04:00
parent 96ee65be74
commit 09bf5bbf6b

View File

@ -1064,187 +1064,187 @@ namespace mongo {
}
}
set<DiskLoc> seenObjects;
int numModded = 0;
long long nscanned = 0;
MatchDetails details;
shared_ptr< MultiCursor::CursorOp > opPtr( new UpdateOp( mods.get() && mods->hasDynamicArray() ) );
shared_ptr< MultiCursor > c( new MultiCursor( ns, patternOrig, BSONObj(), opPtr, true ) );
auto_ptr<ClientCursor> cc;
if( c->ok() ) {
set<DiskLoc> seenObjects;
MatchDetails details;
auto_ptr<ClientCursor> cc;
do {
nscanned++;
while ( c->ok() ) {
nscanned++;
bool atomic = c->matcher()->docMatcher().atomic();
bool atomic = c->matcher()->docMatcher().atomic();
// May have already matched in UpdateOp, but do again to get details set correctly
if ( ! c->matcher()->matchesCurrent( c.get(), &details ) ) {
c->advance();
// May have already matched in UpdateOp, but do again to get details set correctly
if ( ! c->matcher()->matchesCurrent( c.get(), &details ) ) {
c->advance();
if ( nscanned % 256 == 0 && ! atomic ) {
if ( cc.get() == 0 ) {
shared_ptr< Cursor > cPtr = c;
cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , cPtr , ns ) );
if ( nscanned % 256 == 0 && ! atomic ) {
if ( cc.get() == 0 ) {
shared_ptr< Cursor > cPtr = c;
cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , cPtr , ns ) );
}
if ( ! cc->yield() ) {
cc.release();
// TODO should we assert or something?
break;
}
if ( !c->ok() ) {
break;
}
}
if ( ! cc->yield() ) {
cc.release();
// TODO should we assert or something?
break;
}
if ( !c->ok() ) {
break;
}
}
continue;
}
Record *r = c->_current();
DiskLoc loc = c->currLoc();
// TODO Maybe this is unnecessary since we have seenObjects
if ( c->getsetdup( loc ) ) {
c->advance();
continue;
}
BSONObj js(r);
BSONObj pattern = patternOrig;
if ( logop ) {
BSONObjBuilder idPattern;
BSONElement id;
// NOTE: If the matching object lacks an id, we'll log
// with the original pattern. This isn't replay-safe.
// It might make sense to suppress the log instead
// if there's no id.
if ( js.getObjectID( id ) ) {
idPattern.append( id );
pattern = idPattern.obj();
}
else {
uassert( 10157 , "multi-update requires all modified objects to have an _id" , ! multi );
}
}
if ( profile && !multi ) // todo https://jira.mongodb.org/browse/SERVER-3052
ss << " nscanned:" << nscanned;
/* look for $inc etc. note as listed here, all fields to inc must be this type, you can't set some
regular ones at the moment. */
if ( isOperatorUpdate ) {
if ( multi ) {
c->advance(); // go to next record in case this one moves
if ( seenObjects.count( loc ) )
continue;
continue;
}
const BSONObj& onDisk = loc.obj();
Record *r = c->_current();
DiskLoc loc = c->currLoc();
ModSet * useMods = mods.get();
bool forceRewrite = false;
auto_ptr<ModSet> mymodset;
if ( details.elemMatchKey && mods->hasDynamicArray() ) {
useMods = mods->fixDynamicArray( details.elemMatchKey );
mymodset.reset( useMods );
forceRewrite = true;
// TODO Maybe this is unnecessary since we have seenObjects
if ( c->getsetdup( loc ) ) {
c->advance();
continue;
}
auto_ptr<ModSetState> mss = useMods->prepare( onDisk );
BSONObj js(r);
bool indexHack = multi && ( modsIsIndexed || ! mss->canApplyInPlace() );
if ( indexHack ) {
if ( cc.get() )
cc->updateLocation();
else
c->noteLocation();
}
if ( modsIsIndexed <= 0 && mss->canApplyInPlace() ) {
mss->applyModsInPlace( true );// const_cast<BSONObj&>(onDisk) );
DEBUGUPDATE( "\t\t\t doing in place update" );
if ( profile && !multi ) // todo https://jira.mongodb.org/browse/SERVER-3052
ss << " fastmod ";
if ( modsIsIndexed ) {
seenObjects.insert( loc );
}
}
else {
if ( rs )
rs->goingToDelete( onDisk );
BSONObj newObj = mss->createNewFromMods();
checkTooLarge(newObj);
DiskLoc newLoc = theDataFileMgr.updateRecord(ns, d, nsdt, r, loc , newObj.objdata(), newObj.objsize(), debug);
if ( newLoc != loc || modsIsIndexed ) {
// object moved, need to make sure we don' get again
seenObjects.insert( newLoc );
}
}
BSONObj pattern = patternOrig;
if ( logop ) {
DEV assert( mods->size() );
if ( mss->haveArrayDepMod() ) {
BSONObjBuilder patternBuilder;
patternBuilder.appendElements( pattern );
mss->appendSizeSpecForArrayDepMods( patternBuilder );
pattern = patternBuilder.obj();
}
if ( forceRewrite || mss->needOpLogRewrite() ) {
DEBUGUPDATE( "\t rewrite update: " << mss->getOpLogRewrite() );
logOp("u", ns, mss->getOpLogRewrite() , &pattern );
BSONObjBuilder idPattern;
BSONElement id;
// NOTE: If the matching object lacks an id, we'll log
// with the original pattern. This isn't replay-safe.
// It might make sense to suppress the log instead
// if there's no id.
if ( js.getObjectID( id ) ) {
idPattern.append( id );
pattern = idPattern.obj();
}
else {
logOp("u", ns, updateobj, &pattern );
}
}
numModded++;
if ( ! multi )
return UpdateResult( 1 , 1 , numModded );
if ( indexHack )
c->checkLocation();
if ( nscanned % 64 == 0 && ! atomic ) {
if ( cc.get() == 0 ) {
shared_ptr< Cursor > cPtr = c;
cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , cPtr , ns ) );
}
if ( ! cc->yield() ) {
cc.release();
break;
}
if ( !c->ok() ) {
break;
uassert( 10157 , "multi-update requires all modified objects to have an _id" , ! multi );
}
}
if (atomic)
getDur().commitIfNeeded();
if ( profile && !multi ) // todo https://jira.mongodb.org/browse/SERVER-3052
ss << " nscanned:" << nscanned;
continue;
}
/* look for $inc etc. note as listed here, all fields to inc must be this type, you can't set some
regular ones at the moment. */
if ( isOperatorUpdate ) {
uassert( 10158 , "multi update only works with $ operators" , ! multi );
if ( multi ) {
c->advance(); // go to next record in case this one moves
if ( seenObjects.count( loc ) )
continue;
}
BSONElementManipulator::lookForTimestamps( updateobj );
checkNoMods( updateobj );
theDataFileMgr.updateRecord(ns, d, nsdt, r, loc , updateobj.objdata(), updateobj.objsize(), debug, god);
if ( logop ) {
DEV wassert( !god ); // god doesn't get logged, this would be bad.
logOp("u", ns, updateobj, &pattern );
}
return UpdateResult( 1 , 0 , 1 );
} // end cursor loop
const BSONObj& onDisk = loc.obj();
ModSet * useMods = mods.get();
bool forceRewrite = false;
auto_ptr<ModSet> mymodset;
if ( details.elemMatchKey && mods->hasDynamicArray() ) {
useMods = mods->fixDynamicArray( details.elemMatchKey );
mymodset.reset( useMods );
forceRewrite = true;
}
auto_ptr<ModSetState> mss = useMods->prepare( onDisk );
bool indexHack = multi && ( modsIsIndexed || ! mss->canApplyInPlace() );
if ( indexHack ) {
if ( cc.get() )
cc->updateLocation();
else
c->noteLocation();
}
if ( modsIsIndexed <= 0 && mss->canApplyInPlace() ) {
mss->applyModsInPlace( true );// const_cast<BSONObj&>(onDisk) );
DEBUGUPDATE( "\t\t\t doing in place update" );
if ( profile && !multi ) // todo https://jira.mongodb.org/browse/SERVER-3052
ss << " fastmod ";
if ( modsIsIndexed ) {
seenObjects.insert( loc );
}
}
else {
if ( rs )
rs->goingToDelete( onDisk );
BSONObj newObj = mss->createNewFromMods();
checkTooLarge(newObj);
DiskLoc newLoc = theDataFileMgr.updateRecord(ns, d, nsdt, r, loc , newObj.objdata(), newObj.objsize(), debug);
if ( newLoc != loc || modsIsIndexed ) {
// object moved, need to make sure we don' get again
seenObjects.insert( newLoc );
}
}
if ( logop ) {
DEV assert( mods->size() );
if ( mss->haveArrayDepMod() ) {
BSONObjBuilder patternBuilder;
patternBuilder.appendElements( pattern );
mss->appendSizeSpecForArrayDepMods( patternBuilder );
pattern = patternBuilder.obj();
}
if ( forceRewrite || mss->needOpLogRewrite() ) {
DEBUGUPDATE( "\t rewrite update: " << mss->getOpLogRewrite() );
logOp("u", ns, mss->getOpLogRewrite() , &pattern );
}
else {
logOp("u", ns, updateobj, &pattern );
}
}
numModded++;
if ( ! multi )
return UpdateResult( 1 , 1 , numModded );
if ( indexHack )
c->checkLocation();
if ( nscanned % 64 == 0 && ! atomic ) {
if ( cc.get() == 0 ) {
shared_ptr< Cursor > cPtr = c;
cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , cPtr , ns ) );
}
if ( ! cc->yield() ) {
cc.release();
break;
}
if ( !c->ok() ) {
break;
}
}
if (atomic)
getDur().commitIfNeeded();
continue;
}
uassert( 10158 , "multi update only works with $ operators" , ! multi );
BSONElementManipulator::lookForTimestamps( updateobj );
checkNoMods( updateobj );
theDataFileMgr.updateRecord(ns, d, nsdt, r, loc , updateobj.objdata(), updateobj.objsize(), debug, god);
if ( logop ) {
DEV wassert( !god ); // god doesn't get logged, this would be bad.
logOp("u", ns, updateobj, &pattern );
}
return UpdateResult( 1 , 0 , 1 );
} while ( c->ok() );
} // endif
if ( numModded )
return UpdateResult( 1 , 1 , numModded );