From 98800767e0365418ebb154737bdaf7be06a7d0ce Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Tue, 13 Jan 2015 10:33:28 +0000
Subject: [PATCH] prevent division by 0 in utilization scorer

---
 fe/lbv2/lbv2.go          |  8 +++++++-
 fe/loadbalancing_test.go | 18 ++++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/fe/lbv2/lbv2.go b/fe/lbv2/lbv2.go
index dac92092..031edb03 100644
--- a/fe/lbv2/lbv2.go
+++ b/fe/lbv2/lbv2.go
@@ -293,7 +293,13 @@ type capacityAvailableScorer struct {
 }
 
 func (s *capacityAvailableScorer) Score(ctx RequestContext, n Node) float64 {
-	return 1.0 / s.pred.Utilization(n)
+	// Cap utilization low limit at 5%. Anything below that is
+	// considered equally available.
+	u := s.pred.Utilization(n)
+	if u < 0.05 {
+		u = 0.05
+	}
+	return 1.0 / u
 }
 
 func NewCapacityAvailableScorer(pred Predictor) NodeFilter {
diff --git a/fe/loadbalancing_test.go b/fe/loadbalancing_test.go
index 4ca4ec09..2b3c7a49 100644
--- a/fe/loadbalancing_test.go
+++ b/fe/loadbalancing_test.go
@@ -115,6 +115,24 @@ func TestLoadBalancer_Policies(t *testing.T) {
 	runLBTest(t, nodes, nil, "bandwidth_score,best", 1000, map[string]int{"node2": 1000})
 }
 
+func TestLoadBalancer_ZeroUtilization(t *testing.T) {
+	nodes := []*autoradio.NodeStatus{
+		&autoradio.NodeStatus{
+			Name:           "node1",
+			IcecastUp:      true,
+			BandwidthUsage: 0,
+		},
+		&autoradio.NodeStatus{
+			Name:           "node2",
+			IcecastUp:      true,
+			BandwidthUsage: 0,
+		},
+	}
+
+	// Weighted should return both nodes equally.
+	runLBTest(t, nodes, nil, "bandwidth_score,weighted", 1000, map[string]int{"node1": 500, "node2": 500})
+}
+
 func TestLoadBalancer_PoliciesIgnoreDisabledNodes(t *testing.T) {
 	nodes := []*autoradio.NodeStatus{
 		&autoradio.NodeStatus{
-- 
GitLab