Files
scandocs/uni/masterarbeit/source/moversight/ms/placingstrategy/BalancedPeerPlacingStrategy.cc
2014-06-30 13:58:10 +02:00

212 lines
7.5 KiB
C++

/*
* File: BalancedPeerPlacingStrategy.cc
* Author: jgaebler
*
* Created on June 29, 2010, 1:55 PM
*/
#include "BalancedPeerPlacingStrategy.h"
#include "ms/MemberRegister.h"
#include "common/Exception.h"
#include "ms/PeerState.h"
namespace ubeeme {
namespace moversight {
/**
* @brief Creates a new BalancedPeerPlacingStrategy instance.
* @param aRegister The register to place the peers.
*/
BalancedPeerPlacingStrategy::BalancedPeerPlacingStrategy(MemberRegister & aRegister) : PeerPlacingStrategy(aRegister) {
init();
}
/**
* @brief Destructor
*/
BalancedPeerPlacingStrategy::~BalancedPeerPlacingStrategy() {
}
/**
* @brief Determine the best place for a peer within the group.
*
* The method calculates the best place to add a new peer within the group topology.
* It adds the peer to the group, as calculated, and sets the cluster id of the peer.
*
* @param peer the fresh, unplaced peer (owns only a peerId and a peerTransportAddress)
*/
void
BalancedPeerPlacingStrategy::placePeer(Peer & peer) {
init();
ClusterSizeList csList = memRegister.getClusterSizeList();
ClusterSize cs = determinePeerLocation(csList);
if (cs.getSize() < memRegister.getMaxPeerCount()) {
lastCId = cs.getClusterID();
}//End if
else {
if (csList.size() < memRegister.getMaxClusterCount()) {
lastCId = memRegister.createCluster();
}//End if
else {
throw ClusterLimitReachedException("Unable to place the peer since the maximum peer count per cluster due to the cluster limit reached.");
}//End else
}//End else
memRegister.addPeer(peer, lastCId);
}
/**
* @brief Determines if a move operation possible, using the current metric.
*
* This method determines if a move possible, using the current method.
* It checks if the source and destination cluster exist, also if the peer to move element of the group.
* If the current group setup satisfy all pre-conditions, the method calculates if it possible to move the given peer in the destination cluster, based on the current metric.
* @param pId The peer id of the peer to move.
* @param srcClusterId The source cluster id.
* @param destClusterId The destination cluster id.
* @throw PeerPlaceException Thrown, if the given peer not found within the group or cluster.
* @throw ClusterNotFoundException Thrown, if the given cluster not found within the group (source or destination cluster).
* @return True, if the move possible, false otherwise.
*/
bool
BalancedPeerPlacingStrategy::isMovePeerPossible(PeerID pId, ClusterID srcClusterId, ClusterID destClusterId) {
ClusterList & cl = memRegister.getClusters();
//check peer
if (!memRegister.contains(pId)) {
throw PeerPlaceException("peer not found");
}//End if
//check source cluster
if (!cl.contains(srcClusterId)) {
throw ClusterNotFoundException("source cluster not found");
}//End if
//check destination cluster
if (cl.contains(destClusterId)) {
Cluster & destC = cl.getByID(destClusterId);
if (destC.size() < memRegister.getMaxPeerCount()) {
return true;
}//end true
return false;
}//End if
throw ClusterNotFoundException("destination cluster not found");
}
/**
* @brief Returns the cluster ID of the peer, if it will placed within the group as calculated.
* @return the new cluster ID of the peer
*/
ClusterID
BalancedPeerPlacingStrategy::getClusterID() {
return lastCId;
}
/**
* @brief Initialize the placing strategy. Called automatically before each placePeer action.
*/
void
BalancedPeerPlacingStrategy::init() {
lastCId = 0;
}
/**
* @brief Determines, the best location of a peer, depending the current metric. If no matching cluster found, return the first cluster as fallback.
* @param csList The current group situation, described as cluster density.
* @return A cluster size object, which describes the best cluster to store the peer.
* The size of the cluster size object describes the situation before performing the peer placement.
*/
ClusterSize
BalancedPeerPlacingStrategy::determinePeerLocation(ClusterSizeList & csList) {
int sum = 0;
size_t averageClusterSize = 0;
for (size_t i = 0; i < csList.size(); i++) {
sum += csList.get(i).getSize();
}//End for
if (sum > 0) {
averageClusterSize = sum / csList.size();
}//End if
ClusterSize cs;
size_t clusterIndex = 0;
if (csList.size() == 0) {
memRegister.createCluster();
csList = memRegister.getClusterSizeList();
}//End if
for (;
clusterIndex < csList.size() &&
csList.get(clusterIndex).getSize() > averageClusterSize;
clusterIndex++);
//no matching cluster found? return the first cluster as fallback
if (clusterIndex >= csList.size()) {
clusterIndex = 0;
}//end if
cs = csList.get(clusterIndex);
return cs;
}
/**
* @brief Determines a peer, which is able to act as master for the given cluster.
*
* This method determines a peer, which is able to act as master for the given cluster.
* @param cID The ID of the cluster to determine the new master peer.
* @throw ClusterNotFoundException If the cluster id not present within the group.
* @throw AttributeNotSetException If the master not defined within the given cluster.
* @return The peer ID of the new master peer. If the ID equal to the ID of the current master, no other peer is possible to act as master within the given cluster.
*/
PeerID
BalancedPeerPlacingStrategy::determinePossibleNewMaster(ClusterID cID) {
Cluster & c = memRegister.getCluster(cID);
PeerID oldMasterId = c.getMaster().getPeerID();
const PeerList & pList = c.getPeerList();
for (size_t i = 0; i < pList.size(); i++) {
//exclude the current master and pending or disjoining peers
if (pList.get(i).getPeerID() != oldMasterId &&
pList.get(i).getPeerState() != PENDING &&
pList.get(i).getPeerState() != DISJOINED) {
return pList.get(i).getPeerID();
}//end if
}//End for
return oldMasterId;
}
PeerPlacingStrategy *
BalancedPeerPlacingStrategy::clone() const {
BalancedPeerPlacingStrategy * strategy = new BalancedPeerPlacingStrategy(memRegister);
strategy->lastCId = this->lastCId;
return strategy;
}
}//End namespace
}//End namespace