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

$push idempotence checkpoint

This commit is contained in:
Aaron 2009-03-25 16:40:52 -04:00
parent 4b7f917bf5
commit 547a455b5b
2 changed files with 68 additions and 32 deletions

View File

@ -214,6 +214,7 @@ namespace mongo {
double *ndouble;
int *nint;
BSONElement elt;
int pushStartSize;
void setn(double n) const {
if ( ndouble ) *ndouble = n;
else *nint = (int) n;
@ -311,22 +312,13 @@ namespace mongo {
return true;
return false;
}
void appendSizeSpecForPushes( BSONObjBuilder &b, const BSONObj &original ) const {
void appendSizeSpecForPushes( BSONObjBuilder &b ) const {
for ( vector<Mod>::const_iterator i = mods_.begin(); i != mods_.end(); i++ ) {
if ( i->op == Mod::PUSH ) {
BSONElement arrElt = original.getFieldDotted( i->fieldName );
if ( arrElt.type() != Array )
continue;
BSONObj arr = arrElt.embeddedObject();
int count = 0;
BSONObjIterator j( arr );
while( j.more() ) {
BSONElement e = j.next();
if ( e.eoo() )
break;
++count;
}
b << i->fieldName << BSON( "$size" << count );
if ( i->pushStartSize == -1 )
b.appendNull( i->fieldName );
else
b << i->fieldName << BSON( "$size" << i->pushStartSize );
}
}
}
@ -420,27 +412,22 @@ namespace mongo {
uassert( "Push can only be applied to an array", e.type() == Array );
BSONObjBuilder arr;
BSONObjIterator i( e.embeddedObject() );
const char *lastIndex = 0;
int count = 0;
while( i.more() ) {
BSONElement arrI = i.next();
if ( arrI.eoo() )
break;
arr.append( arrI );
lastIndex = arrI.fieldName();
}
string nextIndex;
if ( !lastIndex )
nextIndex = "0";
else {
int index = strtol( lastIndex, 0, 10 );
stringstream ss;
ss << index + 1;
nextIndex = ss.str();
++count;
}
stringstream ss;
ss << count;
string nextIndex = ss.str();
arr.appendAs( m->elt, nextIndex.c_str() );
BSONObjBuilder encapsulatedArr;
encapsulatedArr.appendArray( "foo", arr.done() );
b2.appendAs( encapsulatedArr.done().firstElement(), m->fieldName );
m->pushStartSize = count;
}
++m;
++p;
@ -451,6 +438,7 @@ namespace mongo {
BSONObjBuilder encapsulatedArr;
encapsulatedArr.appendArray( "foo", arr.done() );
b2.appendAs( encapsulatedArr.done().firstElement(), m->fieldName );
m->pushStartSize = -1;
} else {
b2.appendAs( m->elt, m->fieldName );
}
@ -613,18 +601,18 @@ namespace mongo {
if ( profile )
ss << " fastmod ";
} else {
if ( logop && mods.havePush() ) {
BSONObjBuilder patternBuilder;
patternBuilder.appendElements( pattern );
mods.appendSizeSpecForPushes( patternBuilder, c->currLoc().obj() );
pattern = patternBuilder.obj();
}
BSONObj newObj = mods.createNewFromMods( c->currLoc().obj() );
theDataFileMgr.update(ns, r, c->currLoc(), newObj.objdata(), newObj.objsize(), ss);
}
if ( logop ) {
if ( mods.size() ) {
logOp("u", ns, updateobj, &pattern, &upsert);
if ( mods.havePush() ) {
BSONObjBuilder patternBuilder;
patternBuilder.appendElements( pattern );
mods.appendSizeSpecForPushes( patternBuilder );
pattern = patternBuilder.obj();
}
logOp("u", ns, updateobj, &pattern );
return 5;
}
}

View File

@ -624,6 +624,51 @@ namespace ReplTests {
}
};
class PushUpsert : public Base {
public:
void doIt() const {
client()->update( ns(), BSON( "_id" << 0 ), BSON( "$push" << BSON( "a" << 5.0 ) ), true );
}
void check() const {
ASSERT_EQUALS( 1, count() );
checkOne( fromjson( "{'_id':0,a:[4,5]}" ) );
}
void reset() const {
deleteAll( ns() );
insert( fromjson( "{'_id':0,a:[4]}" ) );
}
};
class MultiPush : public Base {
public:
void doIt() const {
client()->update( ns(), BSON( "_id" << 0 ), BSON( "$push" << BSON( "a" << 5.0 ) << "$push" << BSON( "b.c" << 6.0 ) ) );
}
void check() const {
ASSERT_EQUALS( 1, count() );
checkOne( fromjson( "{'_id':0,a:[4,5],b:{c:[6]}}" ) );
}
void reset() const {
deleteAll( ns() );
insert( fromjson( "{'_id':0,a:[4]}" ) );
}
};
class EmptyPush : public Base {
public:
void doIt() const {
client()->update( ns(), BSON( "_id" << 0 ), BSON( "$push" << BSON( "a" << 5.0 ) ) );
}
void check() const {
ASSERT_EQUALS( 1, count() );
checkOne( fromjson( "{'_id':0,a:[5]}" ) );
}
void reset() const {
deleteAll( ns() );
insert( fromjson( "{'_id':0}" ) );
}
};
} // namespace Idempotence
class All : public UnitTest::Suite {
@ -654,6 +699,9 @@ namespace ReplTests {
add< Idempotence::FailingUpdate >();
add< Idempotence::SetNumToStr >();
add< Idempotence::Push >();
add< Idempotence::PushUpsert >();
add< Idempotence::MultiPush >();
add< Idempotence::EmptyPush >();
}
};