mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
fix replication with multiple $inc SERVER-1161
This commit is contained in:
parent
aa3e6e29af
commit
d5e520ff7c
@ -67,7 +67,7 @@ namespace mongo {
|
||||
ms.incint = elt.numberInt() + in.numberInt();
|
||||
}
|
||||
|
||||
ms.appendIncValue( bb );
|
||||
ms.appendIncValue( bb , false );
|
||||
}
|
||||
|
||||
template< class Builder >
|
||||
@ -306,8 +306,10 @@ namespace mongo {
|
||||
}
|
||||
|
||||
auto_ptr<ModSetState> ModSet::prepare(const BSONObj &obj) const {
|
||||
DEBUGUPDATE( "\t start prepare" );
|
||||
ModSetState * mss = new ModSetState( obj );
|
||||
|
||||
|
||||
|
||||
// Perform this check first, so that we don't leave a partially modified object on uassert.
|
||||
for ( ModHolder::const_iterator i = _mods.begin(); i != _mods.end(); ++i ) {
|
||||
DEBUGUPDATE( "\t\t prepare : " << i->first );
|
||||
@ -407,9 +409,41 @@ namespace mongo {
|
||||
mss->amIInPlacePossible( false );
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGUPDATE( "\t mss\n" << mss->toString() << "\t--" );
|
||||
|
||||
return auto_ptr<ModSetState>( mss );
|
||||
}
|
||||
|
||||
void ModState::appendForOpLog( BSONObjBuilder& b ) const {
|
||||
if ( incType ){
|
||||
DEBUGUPDATE( "\t\t\t\t\t appendForOpLog inc fieldname: " << m->fieldName << " short:" << m->shortFieldName );
|
||||
BSONObjBuilder bb( b.subobjStart( "$set" ) );
|
||||
appendIncValue( bb , true );
|
||||
bb.done();
|
||||
return;
|
||||
}
|
||||
|
||||
const char * name = fixedOpName ? fixedOpName : Mod::modNames[op()];
|
||||
|
||||
DEBUGUPDATE( "\t\t\t\t\t appendForOpLog name:" << name << " fixed: " << fixed << " fn: " << m->fieldName );
|
||||
|
||||
BSONObjBuilder bb( b.subobjStart( name ) );
|
||||
if ( fixed )
|
||||
bb.appendAs( *fixed , m->fieldName );
|
||||
else
|
||||
bb.appendAs( m->elt , m->fieldName );
|
||||
bb.done();
|
||||
}
|
||||
|
||||
string ModState::toString() const {
|
||||
stringstream ss;
|
||||
if ( fixedOpName )
|
||||
ss << " fixedOpName: " << fixedOpName;
|
||||
if ( fixed )
|
||||
ss << " fixed: " << fixed;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void ModSetState::applyModsInPlace() {
|
||||
for ( ModStateHolder::iterator i = _mods.begin(); i != _mods.end(); ++i ) {
|
||||
@ -492,7 +526,7 @@ namespace mongo {
|
||||
string field = root + e.fieldName();
|
||||
FieldCompareResult cmp = compareDottedFieldNames( m->second.m->fieldName , field );
|
||||
|
||||
DEBUGUPDATE( "\t\t\t" << field << "\t" << m->second.m->fieldName << "\t" << cmp );
|
||||
DEBUGUPDATE( "\t\t\t field:" << field << "\t mod:" << m->second.m->fieldName << "\t cmp:" << cmp );
|
||||
|
||||
switch ( cmp ){
|
||||
|
||||
@ -518,15 +552,18 @@ namespace mongo {
|
||||
continue;
|
||||
}
|
||||
case LEFT_BEFORE: // Mod on a field that doesn't exist
|
||||
DEBUGUPDATE( "\t\t\t\t creating new field for: " << m->second.m->fieldName );
|
||||
_appendNewFromMods( root , m->second , b , onedownseen );
|
||||
m++;
|
||||
continue;
|
||||
case SAME:
|
||||
DEBUGUPDATE( "\t\t\t\t applying mod on: " << m->second.m->fieldName );
|
||||
m->second.apply( b , e );
|
||||
e = es.next();
|
||||
m++;
|
||||
continue;
|
||||
case RIGHT_BEFORE: // field that doesn't have a MOD
|
||||
DEBUGUPDATE( "\t\t\t\t just copying" );
|
||||
b.append( e ); // if array, ignore field name
|
||||
e = es.next();
|
||||
continue;
|
||||
@ -540,12 +577,14 @@ namespace mongo {
|
||||
|
||||
// finished looping the mods, just adding the rest of the elements
|
||||
while ( e.type() ){
|
||||
DEBUGUPDATE( "\t\t\t copying: " << e.fieldName() );
|
||||
b.append( e ); // if array, ignore field name
|
||||
e = es.next();
|
||||
}
|
||||
|
||||
// do mods that don't have fields already
|
||||
for ( ; m != mend; m++ ){
|
||||
DEBUGUPDATE( "\t\t\t\t appending from mod at end: " << m->second.m->fieldName );
|
||||
_appendNewFromMods( root , m->second , b , onedownseen );
|
||||
}
|
||||
}
|
||||
@ -556,6 +595,14 @@ namespace mongo {
|
||||
return b.obj();
|
||||
}
|
||||
|
||||
string ModSetState::toString() const {
|
||||
stringstream ss;
|
||||
for ( ModStateHolder::const_iterator i=_mods.begin(); i!=_mods.end(); ++i ){
|
||||
ss << "\t\t" << i->first << "\t" << i->second.toString() << "\n";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
BSONObj ModSet::createNewFromQuery( const BSONObj& query ){
|
||||
BSONObj newObj;
|
||||
|
||||
@ -610,6 +657,7 @@ namespace mongo {
|
||||
|
||||
uassert( 10147 , "Invalid modifier specified" + string( fn ), e.type() == Object );
|
||||
BSONObj j = e.embeddedObject();
|
||||
DEBUGUPDATE( "\t" << j );
|
||||
|
||||
BSONObjIterator jt(j);
|
||||
Mod::Op op = opFromStr( fn );
|
||||
@ -639,7 +687,7 @@ namespace mongo {
|
||||
|
||||
_mods[m.fieldName] = m;
|
||||
|
||||
DEBUGUPDATE( "\t\t " << fieldName << "\t" << _hasDynamicArray );
|
||||
DEBUGUPDATE( "\t\t " << fieldName << "\t" << m.fieldName << "\t" << _hasDynamicArray );
|
||||
}
|
||||
}
|
||||
|
||||
|
31
db/update.h
31
db/update.h
@ -410,23 +410,7 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
|
||||
void appendForOpLog( BSONObjBuilder& b ) const {
|
||||
if ( incType ){
|
||||
BSONObjBuilder bb( b.subobjStart( "$set" ) );
|
||||
appendIncValue( bb );
|
||||
bb.done();
|
||||
return;
|
||||
}
|
||||
|
||||
const char * name = fixedOpName ? fixedOpName : Mod::modNames[op()];
|
||||
|
||||
BSONObjBuilder bb( b.subobjStart( name ) );
|
||||
if ( fixed )
|
||||
bb.appendAs( *fixed , m->fieldName );
|
||||
else
|
||||
bb.appendAs( m->elt , m->fieldName );
|
||||
bb.done();
|
||||
}
|
||||
void appendForOpLog( BSONObjBuilder& b ) const;
|
||||
|
||||
template< class Builder >
|
||||
void apply( Builder& b , BSONElement in ){
|
||||
@ -434,18 +418,22 @@ namespace mongo {
|
||||
}
|
||||
|
||||
template< class Builder >
|
||||
void appendIncValue( Builder& b ) const {
|
||||
void appendIncValue( Builder& b , bool useFullName ) const {
|
||||
const char * n = useFullName ? m->fieldName : m->shortFieldName;
|
||||
|
||||
switch ( incType ){
|
||||
case NumberDouble:
|
||||
b.append( m->shortFieldName , incdouble ); break;
|
||||
b.append( n , incdouble ); break;
|
||||
case NumberLong:
|
||||
b.append( m->shortFieldName , inclong ); break;
|
||||
b.append( n , inclong ); break;
|
||||
case NumberInt:
|
||||
b.append( m->shortFieldName , incint ); break;
|
||||
b.append( n , incint ); break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
string toString() const;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -576,6 +564,7 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
|
||||
string toString() const;
|
||||
|
||||
friend class ModSet;
|
||||
};
|
||||
|
@ -109,19 +109,21 @@ printjson( as.rpos.findOne() )
|
||||
//am.getSisterDB( "local" ).getCollection( "oplog.$main" ).find().limit(10).sort( { $natural : -1 } ).forEach( printjson )
|
||||
|
||||
t = am.b;
|
||||
t.update( { "_id" : "fun"}, { $inc : {"ws.fs.cp.wsj" : 6743} } , true, false)
|
||||
t.update( { "_id" : "fun"}, { $inc : {"a.b.c.x" : 6743} } , true, false)
|
||||
block()
|
||||
check( "b 1" );
|
||||
|
||||
t.update( { "_id" : "fun"}, { $inc : {"ws.fs.cp.wsj" : 5} } , true, false)
|
||||
t.update( { "_id" : "fun"}, { $inc : {"a.b.c.x" : 5} } , true, false)
|
||||
block()
|
||||
check( "b 2" );
|
||||
|
||||
t.update( { "_id" : "fun"}, { $inc : {"ws.fs.cp.wsj" : 100, "ws.fs.cp.forbes" : 911} } , true, false)
|
||||
t.update( { "_id" : "fun"}, { $inc : {"a.b.c.x" : 100, "a.b.c.y" : 911} } , true, false)
|
||||
block()
|
||||
printjson( t.findOne() )
|
||||
printjson( as.b.findOne() )
|
||||
//check( "b 3" );
|
||||
assert.eq( { _id : "fun" , a : { b : { c : { x : 6848 , y : 911 } } } } , as.b.findOne() , "b 3" );
|
||||
//printjson( t.findOne() )
|
||||
//printjson( as.b.findOne() )
|
||||
//am.getSisterDB( "local" ).getCollection( "oplog.$main" ).find().sort( { $natural : -1 } ).limit(3).forEach( printjson )
|
||||
check( "b 4" );
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user