Files
mongo/s/shard_version.cpp

152 lines
4.9 KiB
C++
Raw Normal View History

// @file shard_version.cpp
/**
* Copyright (C) 2010 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2010-10-01 16:33:15 -04:00
#include "pch.h"
#include "chunk.h"
#include "config.h"
#include "grid.h"
#include "util.h"
#include "shard.h"
#include "writeback_listener.h"
#include "shard_version.h"
namespace mongo {
// when running in sharded mode, use chunk shard version control
static bool checkShardVersion( DBClientBase & conn , const string& ns , bool authoritative = false , int tryNumber = 1 );
static void resetShardVersion( DBClientBase * conn );
void installChunkShardVersioning() {
2011-01-04 00:40:41 -05:00
//
// Overriding no-op behavior in shardconnection.cpp
2011-01-04 00:40:41 -05:00
//
// TODO: Better encapsulate this mechanism.
//
checkShardVersionCB = checkShardVersion;
resetShardVersionCB = resetShardVersion;
}
struct ConnectionShardStatus {
2011-01-04 00:40:41 -05:00
typedef unsigned long long S;
2011-01-04 00:40:41 -05:00
ConnectionShardStatus()
: _mutex( "ConnectionShardStatus" ) {
}
2011-01-04 00:40:41 -05:00
S getSequence( DBClientBase * conn , const string& ns ) {
scoped_lock lk( _mutex );
return _map[conn][ns];
}
2011-01-04 00:40:41 -05:00
void setSequence( DBClientBase * conn , const string& ns , const S& s ) {
scoped_lock lk( _mutex );
_map[conn][ns] = s;
}
2011-01-04 00:40:41 -05:00
void reset( DBClientBase * conn ) {
scoped_lock lk( _mutex );
_map.erase( conn );
}
2010-11-11 09:02:43 -05:00
// protects _map
mongo::mutex _mutex;
// a map from a connection into ChunkManager's sequence number for each namespace
map<DBClientBase*, map<string,unsigned long long> > _map;
} connectionShardStatus;
2011-01-04 00:40:41 -05:00
void resetShardVersion( DBClientBase * conn ) {
connectionShardStatus.reset( conn );
}
2011-01-04 00:40:41 -05:00
/**
* @return true if had to do something
*/
2011-01-04 00:40:41 -05:00
bool checkShardVersion( DBClientBase& conn , const string& ns , bool authoritative , int tryNumber ) {
// TODO: cache, optimize, etc...
2011-01-04 00:40:41 -05:00
WriteBackListener::init( conn );
DBConfigPtr conf = grid.getDBConfig( ns );
if ( ! conf )
return false;
2011-01-04 00:40:41 -05:00
unsigned long long officialSequenceNumber = 0;
2011-01-04 00:40:41 -05:00
ChunkManagerPtr manager;
const bool isSharded = conf->isSharded( ns );
2011-01-04 00:40:41 -05:00
if ( isSharded ) {
manager = conf->getChunkManager( ns , authoritative );
officialSequenceNumber = manager->getSequenceNumber();
}
// has the ChunkManager been reloaded since the last time we updated the connection-level version?
// (ie, last time we issued the setShardVersions below)
unsigned long long sequenceNumber = connectionShardStatus.getSequence(&conn,ns);
2011-01-04 00:40:41 -05:00
if ( sequenceNumber == officialSequenceNumber ) {
return false;
}
ShardChunkVersion version = 0;
2011-01-04 00:40:41 -05:00
if ( isSharded ) {
version = manager->getVersion( Shard::make( conn.getServerAddress() ) );
}
2011-01-04 00:40:41 -05:00
log(2) << " have to set shard version for conn: " << &conn << " ns:" << ns
<< " my last seq: " << sequenceNumber << " current: " << officialSequenceNumber
<< " version: " << version << " manager: " << manager.get()
<< endl;
2011-01-04 00:40:41 -05:00
BSONObj result;
2011-01-04 00:40:41 -05:00
if ( setShardVersion( conn , ns , version , authoritative , result ) ) {
// success!
log(1) << " setShardVersion success!" << endl;
connectionShardStatus.setSequence( &conn , ns , officialSequenceNumber );
return true;
}
2011-01-04 00:40:41 -05:00
log(1) << " setShardVersion failed!\n" << result << endl;
if ( result.getBoolField( "need_authoritative" ) )
massert( 10428 , "need_authoritative set but in authoritative mode already" , ! authoritative );
2011-01-04 00:40:41 -05:00
if ( ! authoritative ) {
checkShardVersion( conn , ns , 1 , tryNumber + 1 );
return true;
}
2011-01-04 00:40:41 -05:00
if ( tryNumber < 4 ) {
log(1) << "going to retry checkShardVersion" << endl;
sleepmillis( 10 );
checkShardVersion( conn , ns , 1 , tryNumber + 1 );
return true;
}
log() << " setShardVersion failed: " << result << endl;
massert( 10429 , (string)"setShardVersion failed! " + result.jsonString() , 0 );
return true;
}
2011-01-04 00:40:41 -05:00
} // namespace mongo