// @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 "mongo/base/disallow_copying.h"
#include "mongo/db/jsobj.h"
#include "mongo/s/catalog/type_chunk.h"
#include "mongo/s/client/shard.h"
namespace mongo {
class ChunkManager;
class OperationContext;
struct ChunkInfo {
const BSONObj min;
const BSONObj max;
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 {
MigrateInfo(const std::string& a_ns,
const ShardId& a_to,
const ShardId& a_from,
const BSONObj& a_chunk)
: ns(a_ns), to(a_to), from(a_from), chunk(a_chunk) {}
const std::string ns;
const ShardId to;
const ShardId from;
const ChunkInfo chunk;
};
typedef std::map ShardInfoMap;
typedef std::map> ShardToChunksMap;
class DistributionStatus {
MONGO_DISALLOW_COPYING(DistributionStatus);
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 ShardId& shardId) const;
/** @return number of chunks in this shard with the given tag */
unsigned numberOfChunksInShardWithTag(const ShardId& shardId, const std::string& tag) const;
/** @return chunks for the shard */
const std::vector& getChunks(const ShardId& shardId) 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 shard ids we know about */
const std::set& shardIds() const {
return _shardIds;
}
/** @return the ShardInfo for the shard */
const ShardInfo& shardInfo(const ShardId& shardId) 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(OperationContext* txn, ShardInfoMap* shardInfo);
/**
* Note: jumbo and versions are not set.
*/
static void populateShardToChunksMap(const ShardInfoMap& allShards,
const ChunkManager& chunkMgr,
ShardToChunksMap* shardToChunksMap);
private:
const ShardInfoMap& _shardInfo;
const ShardToChunksMap& _shardChunks;
std::map _tagRanges;
std::set _allTags;
std::set _shardIds;
};
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