Status ActionSet::parseActionSetFromString(const std::string& actionsString, ActionSet* result) { std::vector<std::string> actionsList; splitStringDelim(actionsString, &actionsList, ','); std::vector<std::string> unrecognizedActions; Status status = parseActionSetFromStringVector(actionsList, result, &unrecognizedActions); invariantOK(status); if (unrecognizedActions.empty()) { return Status::OK(); } std::string unrecognizedActionsString; joinStringDelim(unrecognizedActions, &unrecognizedActionsString, ','); return Status( ErrorCodes::FailedToParse, str::stream() << "Unrecognized action privilege strings: " << unrecognizedActionsString); }
Status V2UserDocumentParser::initializeUserPrivilegesFromUserDocument(const BSONObj& doc, User* user) const { BSONElement privilegesElement = doc[PRIVILEGES_FIELD_NAME]; if (privilegesElement.eoo()) return Status::OK(); if (privilegesElement.type() != Array) { return Status(ErrorCodes::UnsupportedFormat, "User document 'inheritedPrivileges' element must be Array if present."); } PrivilegeVector privileges; std::string errmsg; for (BSONObjIterator it(privilegesElement.Obj()); it.more(); it.next()) { if ((*it).type() != Object) { warning() << "Wrong type of element in inheritedPrivileges array for " << user->getName() << ": " << *it; continue; } Privilege privilege; ParsedPrivilege pp; if (!pp.parseBSON((*it).Obj(), &errmsg)) { warning() << "Could not parse privilege element in user document for " << user->getName() << ": " << errmsg; continue; } std::vector<std::string> unrecognizedActions; Status status = ParsedPrivilege::parsedPrivilegeToPrivilege(pp, &privilege, &unrecognizedActions); if (!status.isOK()) { warning() << "Could not parse privilege element in user document for " << user->getName() << causedBy(status); continue; } if (unrecognizedActions.size()) { std::string unrecognizedActionsString; joinStringDelim(unrecognizedActions, &unrecognizedActionsString, ','); warning() << "Encountered unrecognized actions \" " << unrecognizedActionsString << "\" while parsing user document for " << user->getName(); } privileges.push_back(privilege); } user->setPrivileges(privileges); return Status::OK(); }
bool ConfigServer::init( vector<string> configHosts ) { uassert( 10187 , "need configdbs" , configHosts.size() ); string hn = getHostName(); if ( hn.empty() ) { sleepsecs(5); dbexit( EXIT_BADOPTIONS ); } set<string> hosts; for ( size_t i=0; i<configHosts.size(); i++ ) { string host = configHosts[i]; hosts.insert( getHost( host , false ) ); configHosts[i] = getHost( host , true ); } for ( set<string>::iterator i=hosts.begin(); i!=hosts.end(); i++ ) { string host = *i; bool ok = false; for ( int x=10; x>0; x-- ) { if ( ! hostbyname( host.c_str() ).empty() ) { ok = true; break; } log() << "can't resolve DNS for [" << host << "] sleeping and trying " << x << " more times" << endl; sleepsecs( 10 ); } if ( ! ok ) return false; } _config = configHosts; string fullString; joinStringDelim( configHosts, &fullString, ',' ); _primary.setAddress( fullString , true ); log(1) << " config string : " << fullString << endl; return true; }
BalancerPolicy::ChunkInfo* BalancerPolicy::balance( const string& ns, const ShardToLimitsMap& shardToLimitsMap, const ShardToChunksMap& shardToChunksMap, int balancedLastTime ) { pair<string,unsigned> min("",numeric_limits<unsigned>::max()); pair<string,unsigned> max("",0); vector<string> drainingShards; bool maxOpsQueued = false; for (ShardToChunksIter i = shardToChunksMap.begin(); i!=shardToChunksMap.end(); ++i ) { // Find whether this shard's capacity or availability are exhausted const string& shard = i->first; BSONObj shardLimits; ShardToLimitsIter it = shardToLimitsMap.find( shard ); if ( it != shardToLimitsMap.end() ) shardLimits = it->second; const bool maxedOut = isSizeMaxed( shardLimits ); const bool draining = isDraining( shardLimits ); const bool opsQueued = hasOpsQueued( shardLimits ); // Is this shard a better chunk receiver then the current one? // Shards that would be bad receiver candidates: // + maxed out shards // + draining shards // + shards with operations queued for writeback const unsigned size = i->second.size(); if ( ! maxedOut && ! draining && ! opsQueued ) { if ( size < min.second ) { min = make_pair( shard , size ); } } else if ( opsQueued ) { MONGO_LOG(1) << "won't send a chunk to: " << shard << " because it has ops queued" << endl; } else if ( maxedOut ) { MONGO_LOG(1) << "won't send a chunk to: " << shard << " because it is maxedOut" << endl; } // Check whether this shard is a better chunk donor then the current one. // Draining shards take a lower priority than overloaded shards. if ( size > max.second ) { max = make_pair( shard , size ); maxOpsQueued = opsQueued; } if ( draining && (size > 0)) { drainingShards.push_back( shard ); } } // If there is no candidate chunk receiver -- they may have all been maxed out, // draining, ... -- there's not much that the policy can do. if ( min.second == numeric_limits<unsigned>::max() ) { log() << "no available shards to take chunks" << endl; return NULL; } if ( maxOpsQueued ) { log() << "biggest shard " << max.first << " has unprocessed writebacks, waiting for completion of migrate" << endl; return NULL; } MONGO_LOG(1) << "collection : " << ns << endl; MONGO_LOG(1) << "donor : " << max.second << " chunks on " << max.first << endl; MONGO_LOG(1) << "receiver : " << min.second << " chunks on " << min.first << endl; if ( ! drainingShards.empty() ) { string drainingStr; joinStringDelim( drainingShards, &drainingStr, ',' ); MONGO_LOG(1) << "draining : " << ! drainingShards.empty() << "(" << drainingShards.size() << ")" << endl; } // Solving imbalances takes a higher priority than draining shards. Many shards can // be draining at once but we choose only one of them to cater to per round. // Important to start balanced, so when there are few chunks any imbalance must be fixed. const int imbalance = max.second - min.second; int threshold = 8; if (balancedLastTime || max.second < 20) threshold = 2; else if (max.second < 80) threshold = 4; string from, to; if ( imbalance >= threshold ) { from = max.first; to = min.first; } else if ( ! drainingShards.empty() ) { from = drainingShards[ rand() % drainingShards.size() ]; to = min.first; } else { // Everything is balanced here! return NULL; } const vector<BSONObj>& chunksFrom = shardToChunksMap.find( from )->second; const vector<BSONObj>& chunksTo = shardToChunksMap.find( to )->second; BSONObj chunkToMove = pickChunk( chunksFrom , chunksTo ); log() << "chose [" << from << "] to [" << to << "] " << chunkToMove << endl; return new ChunkInfo( ns, to, from, chunkToMove ); }
BalancerPolicy::ChunkInfo* BalancerPolicy::balance( const string& ns, const ShardToLimitsMap& shardToLimitsMap, const ShardToChunksMap& shardToChunksMap, int balancedLastTime ){ pair<string,unsigned> min("",numeric_limits<unsigned>::max()); pair<string,unsigned> max("",0); vector<string> drainingShards; for (ShardToChunksIter i = shardToChunksMap.begin(); i!=shardToChunksMap.end(); ++i ){ // Find whether this shard has reached its size cap or whether it is being removed. const string& shard = i->first; BSONObj shardLimits; ShardToLimitsIter it = shardToLimitsMap.find( shard ); if ( it != shardToLimitsMap.end() ) shardLimits = it->second; const bool maxedOut = isSizeMaxed( shardLimits ); const bool draining = isDraining( shardLimits ); // Check whether this shard is a better chunk receiver then the current one. // Maxed out shards or draining shards cannot be considered receivers. const unsigned size = i->second.size(); if ( ! maxedOut && ! draining ){ if ( size < min.second ){ min = make_pair( shard , size ); } } // Check whether this shard is a better chunk donor then the current one. // Draining shards take a lower priority than overloaded shards. if ( size > max.second ){ max = make_pair( shard , size ); } if ( draining && (size > 0)){ drainingShards.push_back( shard ); } } // If there is no candidate chunk receiver -- they may have all been maxed out, // draining, ... -- there's not much that the policy can do. if ( min.second == numeric_limits<unsigned>::max() ){ log() << "no availalable shards to take chunks" << endl; return NULL; } log(1) << "collection : " << ns << endl; log(1) << "donor : " << max.second << " chunks on " << max.first << endl; log(1) << "receiver : " << min.second << " chunks on " << min.first << endl; if ( ! drainingShards.empty() ){ string drainingStr; joinStringDelim( drainingShards, &drainingStr, ',' ); log(1) << "draining : " << ! drainingShards.empty() << "(" << drainingShards.size() << ")" << endl; } // Solving imbalances takes a higher priority than draining shards. Many shards can // be draining at once but we choose only one of them to cater to per round. const int imbalance = max.second - min.second; const int threshold = balancedLastTime ? 2 : 8; string from, to; if ( imbalance >= threshold ){ from = max.first; to = min.first; } else if ( ! drainingShards.empty() ){ from = drainingShards[ rand() % drainingShards.size() ]; to = min.first; } else { // Everything is balanced here! return NULL; } const vector<BSONObj>& chunksFrom = shardToChunksMap.find( from )->second; const vector<BSONObj>& chunksTo = shardToChunksMap.find( to )->second; BSONObj chunkToMove = pickChunk( chunksFrom , chunksTo ); log() << "chose [" << from << "] to [" << to << "] " << chunkToMove << endl; return new ChunkInfo( ns, to, from, chunkToMove ); }