@@ -20,11 +20,13 @@ package org.apache.openwhisk.core.containerpool
20
20
import akka .actor .{Actor , ActorRef , ActorRefFactory , Props }
21
21
import org .apache .openwhisk .common .MetricEmitter
22
22
import org .apache .openwhisk .common .{AkkaLogging , LoggingMarkers , TransactionId }
23
- import org .apache .openwhisk .core .connector .MessageFeed
23
+ import org .apache .openwhisk .core .connector .{ MessageFeed , PrewarmContainerData }
24
24
import org .apache .openwhisk .core .entity ._
25
25
import org .apache .openwhisk .core .entity .size ._
26
+
26
27
import scala .annotation .tailrec
27
28
import scala .collection .immutable
29
+ import scala .collection .mutable .ListBuffer
28
30
import scala .concurrent .duration ._
29
31
import scala .util .Try
30
32
@@ -34,6 +36,9 @@ case object Free extends WorkerState
34
36
35
37
case class WorkerData (data : ContainerData , state : WorkerState )
36
38
39
+ case class PreWarmConfigList (list : List [PrewarmingConfig ])
40
+ object PrewarmQuery
41
+
37
42
case object EmitMetrics
38
43
39
44
/**
@@ -70,6 +75,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
70
75
var busyPool = immutable.Map .empty[ActorRef , ContainerData ]
71
76
var prewarmedPool = immutable.Map .empty[ActorRef , ContainerData ]
72
77
var prewarmStartingPool = immutable.Map .empty[ActorRef , (String , ByteSize )]
78
+ var latestPrewarmConfig = prewarmConfig
73
79
// If all memory slots are occupied and if there is currently no container to be removed, than the actions will be
74
80
// buffered here to keep order of computation.
75
81
// Otherwise actions with small memory-limits could block actions with large memory limits.
@@ -279,6 +285,28 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
279
285
case RescheduleJob =>
280
286
freePool = freePool - sender()
281
287
busyPool = busyPool - sender()
288
+ case prewarmConfigList : PreWarmConfigList =>
289
+ latestPrewarmConfig = prewarmConfigList.list
290
+ prewarmConfigList.list foreach { config =>
291
+ // Delete matched prewarm container from prewarmedPool firstly
292
+ val kind = config.exec.kind
293
+ val memory = config.memoryLimit
294
+ prewarmedPool.filter {
295
+ case (_, PreWarmedData (_, `kind`, `memory`, _)) => true
296
+ case _ => false
297
+ } foreach { element =>
298
+ val actor = element._1
299
+ actor ! Remove
300
+ prewarmedPool = prewarmedPool - actor
301
+ }
302
+ logging.info(this , s " add pre-warming ${config.count} ${config.exec.kind} ${config.memoryLimit.toString}" )(
303
+ TransactionId .invokerWarmup)
304
+ (1 to config.count).foreach { _ =>
305
+ prewarmContainer(config.exec, config.memoryLimit)
306
+ }
307
+ }
308
+ case PrewarmQuery =>
309
+ sender() ! getPrewarmContainer()
282
310
case EmitMetrics =>
283
311
emitMetrics()
284
312
}
@@ -304,7 +332,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
304
332
305
333
/** Install prewarm containers up to the configured requirements for each kind/memory combination. */
306
334
def backfillPrewarms (init : Boolean ) = {
307
- prewarmConfig .foreach { config =>
335
+ latestPrewarmConfig .foreach { config =>
308
336
val kind = config.exec.kind
309
337
val memory = config.memoryLimit
310
338
val currentCount = prewarmedPool.count {
@@ -375,6 +403,33 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
375
403
busyPool = busyPool - toDelete
376
404
}
377
405
406
+ /**
407
+ * get the prewarm container
408
+ * @return
409
+ */
410
+ def getPrewarmContainer (): ListBuffer [PrewarmContainerData ] = {
411
+ val containerDataList = prewarmedPool.values.toList.map { data =>
412
+ data.asInstanceOf [PreWarmedData ]
413
+ }
414
+
415
+ var resultList : ListBuffer [PrewarmContainerData ] = new ListBuffer [PrewarmContainerData ]()
416
+ containerDataList.foreach { prewarmData =>
417
+ val isInclude = resultList.filter { resultData =>
418
+ prewarmData.kind == resultData.kind && prewarmData.memoryLimit.toMB == resultData.memory
419
+ }.size > 0
420
+
421
+ if (isInclude) {
422
+ var resultData = resultList.filter { resultData =>
423
+ prewarmData.kind == resultData.kind && prewarmData.memoryLimit.toMB == resultData.memory
424
+ }.head
425
+ resultData.number += 1
426
+ } else {
427
+ resultList += PrewarmContainerData (prewarmData.kind, prewarmData.memoryLimit.toMB, 1 )
428
+ }
429
+ }
430
+ resultList
431
+ }
432
+
378
433
/**
379
434
* Calculate if there is enough free memory within a given pool.
380
435
*
0 commit comments