From 0afe653fe1db3b4d62e91010f880d5dce0179f14 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Fri, 16 Aug 2013 12:04:36 +0200 Subject: [PATCH] =clu #3517 Guard against wrong random selection * When all weights in the map are zero total became 0, which is not valid in random pick. Treat this special case as empty WeightedRoutees, i.e. no availble targets and routing to deadLetters. --- .../src/test/scala/akka/util/ByteStringSpec.scala | 2 +- .../cluster/routing/AdaptiveLoadBalancingRouter.scala | 2 +- .../akka/cluster/routing/WeightedRouteesSpec.scala | 10 ++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/akka-actor-tests/src/test/scala/akka/util/ByteStringSpec.scala b/akka-actor-tests/src/test/scala/akka/util/ByteStringSpec.scala index f6aa43a947..3dad271e1a 100644 --- a/akka-actor-tests/src/test/scala/akka/util/ByteStringSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/util/ByteStringSpec.scala @@ -231,7 +231,7 @@ class ByteStringSpec extends WordSpec with MustMatchers with Checkers { for (i ← 0 until data.length) builder.putLongPart(data(i), nBytes)(byteOrder) reference.zipWithIndex.collect({ // Since there is no partial put on LongBuffer, we need to collect only the interesting bytes - case (r, i) if byteOrder == ByteOrder.LITTLE_ENDIAN && i % elemSize < nBytes ⇒ r + case (r, i) if byteOrder == ByteOrder.LITTLE_ENDIAN && i % elemSize < nBytes ⇒ r case (r, i) if byteOrder == ByteOrder.BIG_ENDIAN && i % elemSize >= (elemSize - nBytes) ⇒ r }).toSeq == builder.result } diff --git a/akka-cluster/src/main/scala/akka/cluster/routing/AdaptiveLoadBalancingRouter.scala b/akka-cluster/src/main/scala/akka/cluster/routing/AdaptiveLoadBalancingRouter.scala index 4910dbdb0a..d102f6ce39 100644 --- a/akka-cluster/src/main/scala/akka/cluster/routing/AdaptiveLoadBalancingRouter.scala +++ b/akka-cluster/src/main/scala/akka/cluster/routing/AdaptiveLoadBalancingRouter.scala @@ -399,7 +399,7 @@ private[cluster] class WeightedRoutees(refs: immutable.IndexedSeq[ActorRef], sel buckets } - def isEmpty: Boolean = buckets.length == 0 + def isEmpty: Boolean = buckets.length == 0 || buckets(buckets.length - 1) == 0 def total: Int = { require(!isEmpty, "WeightedRoutees must not be used when empty") diff --git a/akka-cluster/src/test/scala/akka/cluster/routing/WeightedRouteesSpec.scala b/akka-cluster/src/test/scala/akka/cluster/routing/WeightedRouteesSpec.scala index 9a7023ee6c..45c303583e 100644 --- a/akka-cluster/src/test/scala/akka/cluster/routing/WeightedRouteesSpec.scala +++ b/akka-cluster/src/test/scala/akka/cluster/routing/WeightedRouteesSpec.scala @@ -44,6 +44,16 @@ class WeightedRouteesSpec extends AkkaSpec(ConfigFactory.parseString(""" intercept[IllegalArgumentException] { empty.total } + + val empty2 = new WeightedRoutees(Vector(refA), a1, Map(a1 -> 0)) + empty2.isEmpty must be(true) + intercept[IllegalArgumentException] { + empty2.total + } + intercept[IllegalArgumentException] { + empty2(0) + } + val weighted = new WeightedRoutees(Vector(refA, refB, refC), a1, Map.empty) weighted.total must be(3) intercept[IllegalArgumentException] {