=clu #13226 Prune vector clocks from removed member

This commit is contained in:
Patrik Nordwall 2015-02-11 22:16:27 +01:00
parent f4abf80f50
commit 5cf35938d0
6 changed files with 196 additions and 6 deletions

View file

@ -0,0 +1,122 @@
/**
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.cluster
import scala.collection.immutable
import scala.language.postfixOps
import scala.concurrent.duration._
import akka.actor.Address
import akka.cluster.MemberStatus._
import akka.remote.testkit.MultiNodeConfig
import akka.remote.testkit.MultiNodeSpec
import akka.testkit._
import com.typesafe.config.ConfigFactory
import org.scalatest.BeforeAndAfter
import akka.actor.ActorSystem
import akka.actor.ActorRef
import akka.event.Logging.Info
import akka.actor.Actor
import akka.actor.Props
object NodeChurnMultiJvmSpec extends MultiNodeConfig {
val first = role("first")
val second = role("second")
val third = role("third")
commonConfig(debugConfig(on = false).
withFallback(ConfigFactory.parseString("""
akka.cluster.auto-down-unreachable-after = 1s
akka.remote.log-frame-size-exceeding = 2000b
""")).
withFallback(MultiNodeClusterSpec.clusterConfig))
class LogListener(testActor: ActorRef) extends Actor {
def receive = {
case Info(_, _, msg: String) if msg.startsWith("New maximum payload size for [akka.cluster.GossipEnvelope]")
testActor ! msg
case _
}
}
}
class NodeChurnMultiJvmNode1 extends NodeChurnSpec
class NodeChurnMultiJvmNode2 extends NodeChurnSpec
class NodeChurnMultiJvmNode3 extends NodeChurnSpec
abstract class NodeChurnSpec
extends MultiNodeSpec(NodeChurnMultiJvmSpec)
with MultiNodeClusterSpec with ImplicitSender {
import NodeChurnMultiJvmSpec._
def seedNodes: immutable.IndexedSeq[Address] = Vector(first, second, third)
override def afterAll(): Unit = {
super.afterAll()
}
val rounds = 3
override def expectedTestDuration: FiniteDuration = 45.seconds * rounds
def awaitAllMembersUp(additionaSystems: Vector[ActorSystem]): Unit = {
val numberOfMembers = roles.size + roles.size * additionaSystems.size
awaitMembersUp(numberOfMembers)
awaitAssert {
additionaSystems.foreach { s
val c = Cluster(s)
c.state.members.size should be(numberOfMembers)
c.state.members.forall(_.status == MemberStatus.Up)
}
}
}
def awaitRemoved(additionaSystems: Vector[ActorSystem]): Unit = {
awaitMembersUp(roles.size, timeout = 40.seconds)
awaitAssert {
additionaSystems.foreach { s
Cluster(s).isTerminated should be(true)
}
}
}
"Cluster with short lived members" must {
"setup stable nodes" taggedAs LongRunningTest in within(15.seconds) {
val logListener = system.actorOf(Props(classOf[LogListener], testActor), "logListener")
system.eventStream.subscribe(logListener, classOf[Info])
cluster.joinSeedNodes(seedNodes)
awaitMembersUp(roles.size)
}
"join and remove transient nodes without growing gossip payload" taggedAs LongRunningTest in {
// This test is configured with log-frame-size-exceeding and the LogListener
// will send to the testActor if unexpected increase in message payload size.
// It will fail after a while if vector clock entries of removed nodes are not pruned.
for (n 1 to rounds) {
log.info("round-" + n)
val systems = Vector.fill(5)(ActorSystem(system.name, system.settings.config))
systems.foreach { s
muteDeadLetters()(s)
Cluster(s).joinSeedNodes(seedNodes)
}
awaitAllMembersUp(systems)
enterBarrier("members-up-" + n)
systems.foreach { node
if (n % 2 == 0)
Cluster(node).down(Cluster(node).selfAddress)
else
Cluster(node).leave(Cluster(node).selfAddress)
}
awaitRemoved(systems)
enterBarrier("members-removed-" + n)
systems.foreach(_.terminate().await)
log.info("end of round-" + n)
// log listener will send to testActor if payload size exceed configured log-frame-size-exceeding
expectNoMsg(2.seconds)
}
expectNoMsg(5.seconds)
}
}
}