// @file balancer_policy.h
/**
* 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 .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
#pragma once
#include
#include "mongo/base/status_with.h"
#include "mongo/base/owned_pointer_vector.h"
#include "mongo/db/jsobj.h"
#include "mongo/s/catalog/type_chunk.h"
namespace mongo {
class ChunkManager;
struct ChunkInfo {
const BSONObj min;
const BSONObj max;
ChunkInfo( const BSONObj& a_min, const BSONObj& a_max )
: min( a_min.getOwned() ), max( a_max.getOwned() ){}
ChunkInfo( const BSONObj& chunk )
: min(chunk[ChunkType::min()].Obj().getOwned()),
max(chunk[ChunkType::max()].Obj().getOwned()) {
}
std::string toString() const;
};
struct TagRange {
BSONObj min;
BSONObj max;
std::string tag;
TagRange(){}
TagRange( const BSONObj& a_min, const BSONObj& a_max, const std::string& a_tag )
: min( a_min.getOwned() ), max( a_max.getOwned() ), tag( a_tag ){}
std::string toString() const;
};
class ShardInfo {
public:
ShardInfo();
ShardInfo(long long maxSizeMB,
long long currSizeMB,
bool draining,
const std::set& tags = std::set(),
const std::string& _mongoVersion = std::string(""));
void addTag( const std::string& tag );
/** @return true if we have the tag OR if the tag is "" */
bool hasTag( const std::string& tag ) const;
/**
* @return true if a shard cannot receive any new chunks because it reaches 'shardLimits'.
* Expects the optional fields "maxSize", can in size in MB, and "usedSize", currently used size
* in MB, on 'shardLimits'.
*/
bool isSizeMaxed() const;
/**
* @return true if 'shardLimist' contains a field "draining". Expects the optional field
* "isDraining" on 'shrdLimits'.
*/
bool isDraining() const { return _draining; }
long long getMaxSizeMB() const { return _maxSizeMB; }
long long getCurrSizeMB() const { return _currSizeMB; }
std::string getMongoVersion() const { return _mongoVersion; }
std::string toString() const;
private:
long long _maxSizeMB;
long long _currSizeMB;
bool _draining;
std::set _tags;
std::string _mongoVersion;
};
struct MigrateInfo {
const std::string ns;
const std::string to;
const std::string from;
const ChunkInfo chunk;
MigrateInfo( const std::string& a_ns , const std::string& a_to , const std::string& a_from , const BSONObj& a_chunk )
: ns( a_ns ) , to( a_to ) , from( a_from ), chunk( a_chunk ) {}
};
typedef std::map< std::string,ShardInfo > ShardInfoMap;
typedef std::map* > ShardToChunksMap;
class DistributionStatus : boost::noncopyable {
public:
DistributionStatus( const ShardInfoMap& shardInfo,
const ShardToChunksMap& shardToChunksMap );
// only used when building
/**
* @return if range is valid
*/
bool addTagRange( const TagRange& range );
// ---- these methods might be better suiting in BalancerPolicy
/**
* @param forTag "" if you don't care, or a tag
* @return shard best suited to receive a chunk
*/
std::string getBestReceieverShard( const std::string& forTag ) const;
/**
* @return the shard with the most chunks
* based on # of chunks with the given tag
*/
std::string getMostOverloadedShard( const std::string& forTag ) const;
// ---- basic accessors, counters, etc...
/** @return total number of chunks */
unsigned totalChunks() const;
/** @return number of chunks in this shard */
unsigned numberOfChunksInShard( const std::string& shard ) const;
/** @return number of chunks in this shard with the given tag */
unsigned numberOfChunksInShardWithTag( const std::string& shard, const std::string& tag ) const;
/** @return chunks for the shard */
const std::vector& getChunks(const std::string& shard) const;
/** @return all tags we know about, not include "" */
const std::set& tags() const { return _allTags; }
/** @return the right tag for chunk, possibly "" */
std::string getTagForChunk(const ChunkType& chunk) const;
/** @return all shards we know about */
const std::set& shards() const { return _shards; }
/** @return the ShardInfo for the shard */
const ShardInfo& shardInfo( const std::string& shard ) const;
/** writes all state to log() */
void dump() const;
/**
* Retrieves shard metadata information from the config server as well as some stats
* from the shards.
*/
static Status populateShardInfoMap(ShardInfoMap* shardInfo);
/**
* Note: jumbo and versions are not set.
*/
static void populateShardToChunksMap(const ShardInfoMap& allShards,
const ChunkManager& chunkMgr,
ShardToChunksMap* shardToChunksMap);
/**
* Returns the tag of the given chunk by querying the config server.
*
* TODO: add a way to incrementally update chunk tags metadata so this is not needed.
*/
static StatusWith getTagForSingleChunk(const std::string& configServer,
const std::string& ns,
const ChunkType& chunk);
private:
const ShardInfoMap& _shardInfo;
const ShardToChunksMap& _shardChunks;
std::map _tagRanges;
std::set _allTags;
std::set _shards;
};
class BalancerPolicy {
public:
/**
* Returns a suggested chunk to move whithin a collection's shards, given information about
* space usage and number of chunks for that collection. If the policy doesn't recommend
* moving, it returns NULL.
*
* @param ns is the collections namepace.
* @param DistributionStatus holds all the info about the current state of the cluster/namespace
* @param balancedLastTime is the number of chunks effectively moved in the last round.
* @returns NULL or MigrateInfo of the best move to make towards balacing the collection.
* caller owns the MigrateInfo instance
*/
static MigrateInfo* balance( const std::string& ns,
const DistributionStatus& distribution,
int balancedLastTime );
};
} // namespace mongo