package com.rayo.storage.lb;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.rayo.server.storage.GatewayStorageService;
import com.rayo.server.storage.model.RayoNode;
import com.voxeo.logging.Loggerf;
/**
* <p>This is a hybrid load balancer. It will use a complex algorithm based on
* weights and priorities to choose the next rayo node that will handle an incoming
* request and it will use a Round Robin algorithm to balance Rayo events across the
* different Rayo Clients</p>
*
* <p>The Rayo Nodes balancing algorithm works as follows:</p>
* <ul>
* <li>Each rayo node has a priority and a weight assigned.</li>
* <li>The priority indicates the important the Rayo node is. Lower priorities mean
* more important nodes. So if a node has a priority of 1 <string>it will always be
* choosed</strong> over a node with a priority of 2.</li>
* <li>The weight indicates how the load is distributed across that particular node.
* The weight value is relative to the values of other sibling nodes. So for example
* if we have two nodes with weights 10 and 20 this would mean that the second node
* would get twice the load than the first node.</li>
* </ul>
*
* <p>The algorithm to choose client resources is a simple round robin algorithm.</p>
*
* @author martin
*
*/
public class PriorityBasedLoadBalancer extends BlacklistingLoadBalancer {
private Loggerf log = Loggerf.getLogger(PriorityBasedLoadBalancer.class);
private Map<String, NodeSet> nodeSets = new ConcurrentHashMap<String, NodeSet>();
private RoundRobinLoadBalancer delegate = new RoundRobinLoadBalancer();
/*
* This load balancer delegates all the client resource load balancing stuff
* to a regular round robin load balancer. It is important therefore to override
* and delegate all the sensible method.
*/
@Override
public String pickClientResource(String jid) {
return delegate.pickClientResource(jid);
}
@Override
public void clientOperationFailed(String fullJid) {
delegate.clientOperationFailed(fullJid);
}
@Override
public void clientOperationSuceeded(String fullJid) {
delegate.clientOperationSuceeded(fullJid);
}
@Override
public RayoNode pickRayoNode(String platformId) {
log.debug("Picking rayo node for platform [%s]", platformId);
List<RayoNode> nodes = storageService.getRayoNodes(platformId);
if (nodes.isEmpty()) {
log.debug("Could not find any available node for platform [%s]", platformId);
return null;
}
NodeSet nodeSet = nodeSets.get(platformId);
if (nodeSet == null) {
nodeSet = new NodeSet();
nodeSets.put(platformId, nodeSet);
}
RayoNode node = nodes.get(nodes.indexOf(nodeSet.next(nodes)));
RayoNode last = node;
do {
if (!valid(node)) {
if (last == null) {
last = node;
}
node = nodes.get(nodes.indexOf(nodeSet.next(nodes)));
} else {
return node;
}
} while (!last.equals(node));
log.debug("All vailable nodes for platform [%s] are blacklisted", platformId);
return null;
}
public void setStorageService(GatewayStorageService storageService) {
super.setStorageService(storageService);
delegate.setStorageService(storageService);
}
}