Skip to content

Commit fa5691b

Browse files
author
Brendan Doyle
committed
assign based on invoker pool size
1 parent aee8d9d commit fa5691b

File tree

2 files changed

+38
-30
lines changed

2 files changed

+38
-30
lines changed

core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/InstanceIdAssigner.scala

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,26 @@ private[invoker] class InstanceIdAssigner(connectionString: String)(implicit log
4141

4242
val rootPath = "/invokers/idAssignment/mapping"
4343
val myIdPath = s"$rootPath/$name"
44-
val assignedId = if (overwriteId.isEmpty) {
44+
val assignedId = overwriteId.map(newId => {
45+
val invokers = zkClient.getChildren.forPath(rootPath).asScala
46+
47+
if (invokers.size < newId)
48+
throw new IllegalArgumentException(s"invokerReg: cannot assign $newId to $name: not enough invokers")
49+
50+
//check if the invokerId already exists for another unique name and delete if it does
51+
invokers
52+
.map(uniqueName => {
53+
val idPath = s"$rootPath/$uniqueName"
54+
(idPath, BigInt(zkClient.getData.forPath(idPath)).intValue)
55+
})
56+
.find(_._2 == newId)
57+
.map(id => zkClient.delete().forPath(id._1))
58+
59+
zkClient.create().orSetData().forPath(myIdPath, BigInt(newId).toByteArray)
60+
61+
logger.info(this, s"invokerReg: invoker $name was assigned invokerId $newId")
62+
newId
63+
}).getOrElse({
4564
Option(zkClient.checkExists().forPath(myIdPath)) match {
4665
case None =>
4766
// path doesn't exist -> no previous mapping for this invoker
@@ -51,8 +70,11 @@ private[invoker] class InstanceIdAssigner(connectionString: String)(implicit log
5170

5271
def assignId(): Int = {
5372
val current = idCounter.getVersionedValue()
54-
if (idCounter.trySetCount(current, current.getValue() + 1)) {
55-
current.getValue()
73+
val numInvokers = Option(zkClient.checkExists().forPath(rootPath))
74+
.map(_ => zkClient.getChildren.forPath(rootPath).size())
75+
.getOrElse(0)
76+
if (idCounter.trySetCount(current, numInvokers + 1)) {
77+
numInvokers
5678
} else {
5779
assignId()
5880
}
@@ -66,33 +88,12 @@ private[invoker] class InstanceIdAssigner(connectionString: String)(implicit log
6688

6789
case Some(_) =>
6890
// path already exists -> there is a previous mapping for this invoker we should use
69-
val rawOldId = zkClient.getData().forPath(myIdPath)
91+
val rawOldId = zkClient.getData.forPath(myIdPath)
7092
val oldId = BigInt(rawOldId).intValue
7193
logger.info(this, s"invokerReg: invoker $name was assigned its previous invokerId $oldId")
7294
oldId
7395
}
74-
} else {
75-
val newId = overwriteId.get
76-
77-
//check if the invokerId already exists for another unique name
78-
val instanceIdExists = zkClient
79-
.getChildren()
80-
.forPath(rootPath)
81-
.asScala
82-
.map(uniqueName => {
83-
val idPath = s"$rootPath/$uniqueName"
84-
BigInt(zkClient.getData().forPath(idPath)).intValue
85-
})
86-
.find(_ == newId)
87-
88-
if (instanceIdExists.nonEmpty) {
89-
throw new IllegalArgumentException(s"invokerReg: an invoker with id $newId already exists in zookeeper")
90-
}
91-
92-
zkClient.create().orSetData().forPath(myIdPath, BigInt(newId).toByteArray)
93-
logger.info(this, s"invokerReg: invoker $name was assigned invokerId $newId")
94-
newId
95-
}
96+
})
9697

9798
zkClient.close()
9899
assignedId

tests/src/test/scala/org/apache/openwhisk/core/invoker/test/InstanceIdAssignerTests.scala

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,20 @@ class InstanceIdAssignerTests extends FlatSpec with Matchers with StreamLogging
5353
it should "attempt to overwrite id for unique name if overwrite set" in {
5454
val assigner = new InstanceIdAssigner(zkServer.getConnectString)
5555
assigner.setAndGetId("foo") shouldBe 0
56-
assigner.setAndGetId("foo", Some(2)) shouldBe 2
56+
assigner.setAndGetId("bar", Some(0))
5757
}
5858

59-
it should "fail to overwrite an id for unique name that already exists" in {
59+
it should "overwrite an id for unique name that already exists and reset overwritten id" in {
6060
val assigner = new InstanceIdAssigner(zkServer.getConnectString)
6161
assigner.setAndGetId("foo") shouldBe 0
62-
assigner.setAndGetId("bar") shouldBe 1
63-
assertThrows[IllegalArgumentException](assigner.setAndGetId("bar", Some(1)))
62+
assigner.setAndGetId("bar", Some(0)) shouldBe 0
63+
assigner.setAndGetId("foo") shouldBe 1
64+
assigner.setAndGetId("cat") shouldBe 2
65+
}
66+
67+
it should "fail to overwrite an id too large for the invoker pool size" in {
68+
val assigner = new InstanceIdAssigner(zkServer.getConnectString)
69+
assigner.setAndGetId("foo") shouldBe 0
70+
assertThrows[IllegalArgumentException](assigner.setAndGetId("bar", Some(2)))
6471
}
6572
}

0 commit comments

Comments
 (0)