mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 01:21:03 +01:00
152 lines
4.9 KiB
C++
152 lines
4.9 KiB
C++
// @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/>.
|
|
*/
|
|
|
|
#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() {
|
|
//
|
|
// Overriding no-op behavior in shardconnection.cpp
|
|
//
|
|
// TODO: Better encapsulate this mechanism.
|
|
//
|
|
checkShardVersionCB = checkShardVersion;
|
|
resetShardVersionCB = resetShardVersion;
|
|
}
|
|
|
|
struct ConnectionShardStatus {
|
|
|
|
typedef unsigned long long S;
|
|
|
|
ConnectionShardStatus()
|
|
: _mutex( "ConnectionShardStatus" ){
|
|
}
|
|
|
|
S getSequence( DBClientBase * conn , const string& ns ){
|
|
scoped_lock lk( _mutex );
|
|
return _map[conn][ns];
|
|
}
|
|
|
|
void setSequence( DBClientBase * conn , const string& ns , const S& s ){
|
|
scoped_lock lk( _mutex );
|
|
_map[conn][ns] = s;
|
|
}
|
|
|
|
void reset( DBClientBase * conn ){
|
|
scoped_lock lk( _mutex );
|
|
_map.erase( conn );
|
|
}
|
|
|
|
// 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;
|
|
|
|
void resetShardVersion( DBClientBase * conn ){
|
|
connectionShardStatus.reset( conn );
|
|
}
|
|
|
|
/**
|
|
* @return true if had to do something
|
|
*/
|
|
bool checkShardVersion( DBClientBase& conn , const string& ns , bool authoritative , int tryNumber ){
|
|
// TODO: cache, optimize, etc...
|
|
|
|
WriteBackListener::init( conn );
|
|
|
|
DBConfigPtr conf = grid.getDBConfig( ns );
|
|
if ( ! conf )
|
|
return false;
|
|
|
|
unsigned long long officialSequenceNumber = 0;
|
|
|
|
ChunkManagerPtr manager;
|
|
const bool isSharded = conf->isSharded( ns );
|
|
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);
|
|
if ( sequenceNumber == officialSequenceNumber ){
|
|
return false;
|
|
}
|
|
|
|
|
|
ShardChunkVersion version = 0;
|
|
if ( isSharded ){
|
|
version = manager->getVersion( Shard::make( conn.getServerAddress() ) );
|
|
}
|
|
|
|
log(2) << " have to set shard version for conn: " << &conn << " ns:" << ns
|
|
<< " my last seq: " << sequenceNumber << " current: " << officialSequenceNumber
|
|
<< " version: " << version << " manager: " << manager.get()
|
|
<< endl;
|
|
|
|
BSONObj result;
|
|
if ( setShardVersion( conn , ns , version , authoritative , result ) ){
|
|
// success!
|
|
log(1) << " setShardVersion success!" << endl;
|
|
connectionShardStatus.setSequence( &conn , ns , officialSequenceNumber );
|
|
return true;
|
|
}
|
|
|
|
log(1) << " setShardVersion failed!\n" << result << endl;
|
|
|
|
if ( result.getBoolField( "need_authoritative" ) )
|
|
massert( 10428 , "need_authoritative set but in authoritative mode already" , ! authoritative );
|
|
|
|
if ( ! authoritative ){
|
|
checkShardVersion( conn , ns , 1 , tryNumber + 1 );
|
|
return true;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
} // namespace mongo
|