/** * The load balancing operation: Returns a node choice from the given choices, * based on previously gathered statistics on the nodes, and a running "position" * which is increased by 1 on each call to this. * * @param choices the node choices, represented as Slobrok entries * @return the chosen node, or null only if the given choices were zero */ public Node getRecipient(Mirror.Entry[] choices) { if (choices.length == 0) return null; double weightSum = 0.0; Node selectedNode = null; for (Mirror.Entry entry : choices) { NodeMetrics nodeMetrics = getNodeMetrics(entry); weightSum += nodeMetrics.weight.get(); if (weightSum > position) { selectedNode = new Node(entry, nodeMetrics); break; } } if (selectedNode == null) { // Position>sum of all weights: Wrap around (but keep the remainder for some reason) position -= weightSum; selectedNode = new Node(choices[0], getNodeMetrics(choices[0])); } position += 1.0; selectedNode.metrics.sent.inc(1); return selectedNode; }