summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2011-01-21 14:19:20 -0500
committerEliot Horowitz <eliot@10gen.com>2011-01-21 14:19:49 -0500
commitb331e1c7aed7d85dd14f86e1396f5c091aaa3f0f (patch)
treebed9d99f5714067d312e8f5c28220dd72687696e
parent124193c25929b70baa9fdd00127d87159b9b64ca (diff)
downloadmongo-b331e1c7aed7d85dd14f86e1396f5c091aaa3f0f.tar.gz
make sure getLastError fields are correct after writeback SERVER-1467
-rw-r--r--jstests/slowNightly/sharding_balance4.js18
-rw-r--r--s/client.cpp41
-rw-r--r--s/client.h8
-rw-r--r--s/strategy_shard.cpp7
-rw-r--r--s/writeback_listener.cpp11
-rw-r--r--s/writeback_listener.h2
6 files changed, 62 insertions, 25 deletions
diff --git a/jstests/slowNightly/sharding_balance4.js b/jstests/slowNightly/sharding_balance4.js
index c9907af77e7..4cbbba6f2fa 100644
--- a/jstests/slowNightly/sharding_balance4.js
+++ b/jstests/slowNightly/sharding_balance4.js
@@ -1,5 +1,7 @@
// sharding_balance4.js
+// check that doing updates done during a migrate all go to the right place
+
s = new ShardingTest( "slow_sharding_balance4" , 2 , 1 , 1 , { chunksize : 1 } )
s.adminCommand( { enablesharding : "test" } );
@@ -36,9 +38,8 @@ for ( i=0; i<N*10; i++ ){
}
db.getLastError();
-s.printChunks( "test.foo" )
-
-for ( var i=0; i<10; i++ ){
+for ( var i=0; i<50; i++ ){
+ s.printChunks( "test.foo" )
if ( check( "initial:" + i , true ) )
break;
sleep( 5000 )
@@ -56,8 +57,12 @@ function check( msg , dontAssert ){
if ( z && z.x == e )
continue;
- if ( dontAssert )
+ if ( dontAssert ){
+ if ( z )
+ delete z.s;
+ print( "not asserting for key failure: " + x + " want: " + e + " got: " + tojson(z) )
return false;
+ }
// we will assert past this point but wait a bit to see if it is because the missing update
// was being held in the writeback roundtrip
@@ -81,9 +86,14 @@ function check( msg , dontAssert ){
function diff(){
var myid = doUpdate( false )
var le = db.getLastErrorCmd();
+
if ( le.err )
print( "ELIOT ELIOT : " + tojson( le ) + "\t" + myid );
+ assert( le.updatedExisting , "GLE diff 1: " + tojson(le) )
+ assert.eq( 1 , le.n , "GLE diff 2: " + tojson(le) )
+
+
if ( Math.random() > .99 ){
db.getLastError()
check( "random late check" ); // SERVER-1430
diff --git a/s/client.cpp b/s/client.cpp
index c1c3da8ea7e..18f598a03d3 100644
--- a/s/client.cpp
+++ b/s/client.cpp
@@ -39,6 +39,7 @@ namespace mongo {
ClientInfo::ClientInfo( int clientId ) : _id( clientId ) {
_cur = &_a;
_prev = &_b;
+ _autoSplitOk = true;
newRequest();
}
@@ -123,14 +124,13 @@ namespace mongo {
_clients.erase( i );
}
- void ClientInfo::_addWriteBack( vector<WBInfo>& all , const BSONObj& o ) {
- BSONElement w = o["writeback"];
+ void ClientInfo::_addWriteBack( vector<WBInfo>& all , const BSONObj& gle ) {
+ BSONElement w = gle["writeback"];
if ( w.type() != jstOID )
return;
- BSONElement cid = o["connectionId"];
- cout << "ELIOT : " << cid << endl;
+ BSONElement cid = gle["connectionId"];
if ( cid.eoo() ) {
error() << "getLastError writeback can't work because of version mis-match" << endl;
@@ -140,13 +140,17 @@ namespace mongo {
all.push_back( WBInfo( cid.numberLong() , w.OID() ) );
}
- void ClientInfo::_handleWriteBacks( vector<WBInfo>& all ) {
+ vector<BSONObj> ClientInfo::_handleWriteBacks( vector<WBInfo>& all ) {
+ vector<BSONObj> res;
+
if ( all.size() == 0 )
- return;
+ return res;
for ( unsigned i=0; i<all.size(); i++ ) {
- WriteBackListener::waitFor( all[i].connectionId , all[i].id );
+ res.push_back( WriteBackListener::waitFor( all[i].connectionId , all[i].id ) );
}
+
+ return res;
}
@@ -164,14 +168,15 @@ namespace mongo {
// handle single server
if ( shards->size() == 1 ) {
string theShard = *(shards->begin() );
- result.append( "theshard" , theShard.c_str() );
+
ShardConnection conn( theShard , "" );
+
BSONObj res;
bool ok = conn->runCommand( "admin" , options , res );
- //log() << "\t" << res << endl;
- result.appendElements( res );
+ res = res.getOwned();
conn.done();
- result.append( "singleShard" , theShard );
+
+
_addWriteBack( writebacks , res );
// hit other machines just to block
@@ -185,7 +190,19 @@ namespace mongo {
conn.done();
}
clearSinceLastGetError();
- _handleWriteBacks( writebacks );
+
+ if ( writebacks.size() ){
+ vector<BSONObj> v = _handleWriteBacks( writebacks );
+ assert( v.size() == 1 );
+ result.appendElements( v[0] );
+ result.appendElementsUnique( res );
+ result.append( "initialGLEHost" , theShard );
+ }
+ else {
+ result.append( "singleShard" , theShard );
+ result.appendElements( res );
+ }
+
return ok;
}
diff --git a/s/client.h b/s/client.h
index 016300c481a..7e3d96d7ce9 100644
--- a/s/client.h
+++ b/s/client.h
@@ -72,6 +72,10 @@ namespace mongo {
*/
bool getLastError( const BSONObj& options , BSONObjBuilder& result );
+ /** @return if its ok to auto split from this client */
+ bool autoSplitOk() const { return _autoSplitOk; }
+
+ void noAutoSplit() { _autoSplitOk = false; }
static ClientInfo * get( int clientId = 0 , bool create = true );
static void disconnect( int clientId );
@@ -86,7 +90,7 @@ namespace mongo {
// for getLastError
void _addWriteBack( vector<WBInfo>& all , const BSONObj& o );
- void _handleWriteBacks( vector<WBInfo>& all );
+ vector<BSONObj> _handleWriteBacks( vector<WBInfo>& all );
int _id; // unique client id
@@ -105,7 +109,7 @@ namespace mongo {
set<string> _sinceLastGetError; // all shards accessed since last getLastError
int _lastAccess;
-
+ bool _autoSplitOk;
static mongo::mutex _clientsLock;
static Cache& _clients;
diff --git a/s/strategy_shard.cpp b/s/strategy_shard.cpp
index 7d2c09fd623..2a71a832c1f 100644
--- a/s/strategy_shard.cpp
+++ b/s/strategy_shard.cpp
@@ -21,6 +21,7 @@
#include "chunk.h"
#include "cursors.h"
#include "stats.h"
+#include "client.h"
#include "../client/connpool.h"
#include "../db/commands.h"
@@ -158,7 +159,8 @@ namespace mongo {
insert( c->getShard() , r.getns() , o );
r.gotInsert();
- c->splitIfShould( o.objsize() );
+ if ( r.getClientInfo()->autoSplitOk() )
+ c->splitIfShould( o.objsize() );
gotThrough = true;
break;
}
@@ -258,7 +260,8 @@ namespace mongo {
try {
ChunkPtr c = manager->findChunk( chunkFinder );
doWrite( dbUpdate , r , c->getShard() );
- c->splitIfShould( d.msg().header()->dataLen() );
+ if ( r.getClientInfo()->autoSplitOk() )
+ c->splitIfShould( d.msg().header()->dataLen() );
break;
}
catch ( StaleConfigException& e ) {
diff --git a/s/writeback_listener.cpp b/s/writeback_listener.cpp
index c2b359901be..41240e1b42d 100644
--- a/s/writeback_listener.cpp
+++ b/s/writeback_listener.cpp
@@ -53,22 +53,24 @@ namespace mongo {
}
/* static */
- void WriteBackListener::waitFor( ConnectionId connectionId, const OID& oid ) {
+ BSONObj WriteBackListener::waitFor( ConnectionId connectionId, const OID& oid ) {
Timer t;
for ( int i=0; i<5000; i++ ) {
{
scoped_lock lk( _seenWritebacksLock );
WBStatus s = _seenWritebacks[connectionId];
if ( oid <= s.id ) {
- // TODO return gle
- return;
+ assert( oid == s.id );
+ return s.gle;
}
+
}
sleepmillis( 10 );
}
stringstream ss;
ss << "didn't get writeback for: " << oid << " after: " << t.millis() << " ms";
uasserted( 13403 , ss.str() );
+ return BSONObj(); // never gets here
}
void WriteBackListener::run() {
@@ -139,10 +141,11 @@ namespace mongo {
try {
Request r( m , 0 );
r.init();
+ r.getClientInfo()->noAutoSplit();
r.process();
BSONObjBuilder b;
- if ( ! r.getClientInfo()->getLastError( BSONObj() , b ) ) {
+ if ( ! r.getClientInfo()->getLastError( BSON( "getLastError" << 1 ) , b ) ) {
b.appendBool( "commandFailed" , true );
}
gle = b.obj();
diff --git a/s/writeback_listener.h b/s/writeback_listener.h
index bcb039a404b..5bd08f2a2b4 100644
--- a/s/writeback_listener.h
+++ b/s/writeback_listener.h
@@ -37,7 +37,7 @@ namespace mongo {
public:
static void init( DBClientBase& conn );
- static void waitFor( ConnectionId connectionId, const OID& oid );
+ static BSONObj waitFor( ConnectionId connectionId, const OID& oid );
protected:
WriteBackListener( const string& addr );