195 lines
7.8 KiB
C++
195 lines
7.8 KiB
C++
/*
|
|
* File: CreateMasterFirstPeerPlacingStrategy.cc
|
|
* Author: schnegri
|
|
*
|
|
* Created on March 3, 2011 11:30 AM
|
|
*/
|
|
|
|
#include "CreateMasterFirstPeerPlacingStrategy.h"
|
|
|
|
#include "ms/MemberRegister.h"
|
|
|
|
#include "common/Exception.h"
|
|
#include "ms/PeerState.h"
|
|
|
|
namespace ubeeme {
|
|
namespace moversight {
|
|
|
|
/**
|
|
* @brief Creates a new CreateMasterFirstPeerPlacingStrategy instance.
|
|
* @param aRegister the register to manage the peer placement
|
|
*/
|
|
CreateMasterFirstPeerPlacingStrategy::CreateMasterFirstPeerPlacingStrategy(MemberRegister & aRegister) : PeerPlacingStrategy(aRegister) {
|
|
init();
|
|
}//End CreateMasterFirstPeerPlacingStrategy
|
|
|
|
/**
|
|
* @brief Destructor
|
|
*/
|
|
CreateMasterFirstPeerPlacingStrategy::~CreateMasterFirstPeerPlacingStrategy() {
|
|
}//End ~CreateMasterFirstPeerPlacingStrategy
|
|
|
|
/**
|
|
* @brief Determine the best place of the peer within the group.
|
|
*
|
|
* The method calculates the best place to add a new peer within the group topology. At first all masters are created, only if all master places are
|
|
* taken the new peer is added as slave to one of the masters.
|
|
* The method 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).
|
|
* @throw PeerPlaceException thrown if there is no place to add the new peer.
|
|
*/
|
|
void
|
|
CreateMasterFirstPeerPlacingStrategy::placePeer(Peer & peer) {
|
|
|
|
init();
|
|
|
|
ClusterSizeList csList = memRegister.getClusterSizeList();
|
|
|
|
//check if enough masters exist
|
|
if (csList.size() < memRegister.getMaxClusterCount()) {
|
|
lastCId = memRegister.createCluster();
|
|
}//End if
|
|
else {
|
|
|
|
ClusterSize cs = determinePeerLocation(csList);
|
|
// check if there is place for another peer in the cluster
|
|
if (cs.getSize() < memRegister.getMaxPeerCount()) {
|
|
lastCId = cs.getClusterID();
|
|
}//End if
|
|
else {
|
|
throw PeerPlaceException("Unable to place the peer since the maximum peer count per cluster is reached and a new cluster can not created due to the given max cluster count.");
|
|
}//End else
|
|
}//end else
|
|
|
|
memRegister.addPeer(peer, lastCId);
|
|
|
|
}//End placePeer
|
|
|
|
/**
|
|
* @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
|
|
CreateMasterFirstPeerPlacingStrategy::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");
|
|
}//End isMovePeerPossible
|
|
|
|
/**
|
|
* @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
|
|
CreateMasterFirstPeerPlacingStrategy::getClusterID() {
|
|
return lastCId;
|
|
}//End getClusterID
|
|
|
|
/**
|
|
* @brief Initialize the placing strategy. Called automatically before each placePeer action.
|
|
*/
|
|
void
|
|
CreateMasterFirstPeerPlacingStrategy::init() {
|
|
lastCId = 0;
|
|
}//End init
|
|
|
|
/**
|
|
* @brief Determines, the best location of a peer, depending the current metric. If no matching cluster found, return the first cluster as fallback.
|
|
* Checks in which cluster the new peer can be placed.
|
|
* @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
|
|
CreateMasterFirstPeerPlacingStrategy::determinePeerLocation(ClusterSizeList & csList) {
|
|
|
|
ClusterSize cs;
|
|
size_t clusterIndex = 0;
|
|
|
|
for (; clusterIndex < csList.size()
|
|
&& csList.get(clusterIndex).getSize() > memRegister.getMaxPeerCount() - 1; clusterIndex++)
|
|
;
|
|
//no matching cluster found? return first cluster as fallback
|
|
if (clusterIndex >= csList.size()) {
|
|
clusterIndex = 0;
|
|
}
|
|
|
|
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
|
|
CreateMasterFirstPeerPlacingStrategy::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
|
|
|
|
//if no new master can be found, return the old one.
|
|
return oldMasterID;
|
|
}//End
|
|
|
|
PeerPlacingStrategy *
|
|
CreateMasterFirstPeerPlacingStrategy::clone() const {
|
|
CreateMasterFirstPeerPlacingStrategy * strategy = new CreateMasterFirstPeerPlacingStrategy(memRegister);
|
|
strategy->lastCId = this->lastCId;
|
|
|
|
return strategy;
|
|
}//End
|
|
|
|
}//End namespace
|
|
}//End namespace
|