@@ -19,13 +19,14 @@ package org.apache.openwhisk.core.containerpool
19
19
20
20
import akka .actor .{Actor , ActorRef , ActorRefFactory , Props }
21
21
import org .apache .openwhisk .common .{Logging , LoggingMarkers , MetricEmitter , TransactionId }
22
- import org .apache .openwhisk .core .connector .MessageFeed
22
+ import org .apache .openwhisk .core .connector .{ MessageFeed , PrewarmContainerData }
23
23
import org .apache .openwhisk .core .entity .ExecManifest .ReactivePrewarmingConfig
24
24
import org .apache .openwhisk .core .entity ._
25
25
import org .apache .openwhisk .core .entity .size ._
26
26
27
27
import scala .annotation .tailrec
28
28
import scala .collection .immutable
29
+ import scala .collection .mutable .ListBuffer
29
30
import scala .concurrent .duration ._
30
31
import scala .util .{Random , Try }
31
32
@@ -37,6 +38,9 @@ case class ColdStartKey(kind: String, memory: ByteSize)
37
38
38
39
case class WorkerData (data : ContainerData , state : WorkerState )
39
40
41
+ case class PreWarmConfigList (list : List [PrewarmingConfig ])
42
+ object PrewarmQuery
43
+
40
44
case object EmitMetrics
41
45
42
46
case object AdjustPrewarmedContainer
@@ -74,6 +78,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
74
78
var busyPool = immutable.Map .empty[ActorRef , ContainerData ]
75
79
var prewarmedPool = immutable.Map .empty[ActorRef , PreWarmedData ]
76
80
var prewarmStartingPool = immutable.Map .empty[ActorRef , (String , ByteSize )]
81
+ var latestPrewarmConfig = prewarmConfig
77
82
// If all memory slots are occupied and if there is currently no container to be removed, than the actions will be
78
83
// buffered here to keep order of computation.
79
84
// Otherwise actions with small memory-limits could block actions with large memory limits.
@@ -305,6 +310,34 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
305
310
case RescheduleJob =>
306
311
freePool = freePool - sender()
307
312
busyPool = busyPool - sender()
313
+ case prewarmConfigList : PreWarmConfigList =>
314
+ logging.info(this , " update prewarm configuration request is send to invoker" )
315
+ val passedPrewarmConfig = prewarmConfigList.list
316
+ var newPrewarmConfig : List [PrewarmingConfig ] = List .empty
317
+ latestPrewarmConfig foreach { config =>
318
+ newPrewarmConfig = newPrewarmConfig :+ passedPrewarmConfig
319
+ .find(passedConfig =>
320
+ passedConfig.exec.kind == config.exec.kind && passedConfig.memoryLimit == config.memoryLimit)
321
+ .getOrElse(config)
322
+ }
323
+ latestPrewarmConfig = newPrewarmConfig
324
+ // Delete prewarmedPool firstly
325
+ prewarmedPool foreach { element =>
326
+ val actor = element._1
327
+ actor ! Remove
328
+ prewarmedPool = prewarmedPool - actor
329
+ }
330
+ latestPrewarmConfig foreach { config =>
331
+ logging.info(
332
+ this ,
333
+ s " add pre-warming ${config.initialCount} ${config.exec.kind} ${config.memoryLimit.toString}" )(
334
+ TransactionId .invokerWarmup)
335
+ (1 to config.initialCount).foreach { _ =>
336
+ prewarmContainer(config.exec, config.memoryLimit, config.reactive.map(_.ttl))
337
+ }
338
+ }
339
+ case PrewarmQuery =>
340
+ sender() ! getPrewarmContainer()
308
341
case EmitMetrics =>
309
342
emitMetrics()
310
343
@@ -335,7 +368,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
335
368
def adjustPrewarmedContainer (init : Boolean , scheduled : Boolean ): Unit = {
336
369
if (scheduled) {
337
370
// on scheduled time, remove expired prewarms
338
- ContainerPool .removeExpired(poolConfig, prewarmConfig , prewarmedPool).foreach { p =>
371
+ ContainerPool .removeExpired(poolConfig, latestPrewarmConfig , prewarmedPool).foreach { p =>
339
372
prewarmedPool = prewarmedPool - p
340
373
p ! Remove
341
374
}
@@ -348,7 +381,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
348
381
}
349
382
// fill in missing prewarms (replaces any deletes)
350
383
ContainerPool
351
- .increasePrewarms(init, scheduled, coldStartCount, prewarmConfig , prewarmedPool, prewarmStartingPool)
384
+ .increasePrewarms(init, scheduled, coldStartCount, latestPrewarmConfig , prewarmedPool, prewarmStartingPool)
352
385
.foreach { c =>
353
386
val config = c._1
354
387
val currentCount = c._2._1
@@ -382,7 +415,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
382
415
383
416
/** this is only for cold start statistics of prewarm configs, e.g. not blackbox or other configs. */
384
417
def incrementColdStartCount (kind : String , memoryLimit : ByteSize ): Unit = {
385
- prewarmConfig
418
+ latestPrewarmConfig
386
419
.filter { config =>
387
420
kind == config.exec.kind && memoryLimit == config.memoryLimit
388
421
}
@@ -423,7 +456,9 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
423
456
424
457
// get the appropriate ttl from prewarm configs
425
458
val ttl =
426
- prewarmConfig.find(pc => pc.memoryLimit == memory && pc.exec.kind == kind).flatMap(_.reactive.map(_.ttl))
459
+ latestPrewarmConfig
460
+ .find(pc => pc.memoryLimit == memory && pc.exec.kind == kind)
461
+ .flatMap(_.reactive.map(_.ttl))
427
462
prewarmContainer(action.exec, memory, ttl)
428
463
(ref, data)
429
464
}
@@ -436,6 +471,31 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
436
471
busyPool = busyPool - toDelete
437
472
}
438
473
474
+ /**
475
+ * get the prewarm container
476
+ * @return
477
+ */
478
+ def getPrewarmContainer (): ListBuffer [PrewarmContainerData ] = {
479
+ val containerDataList = prewarmedPool.values.toList
480
+
481
+ var resultList : ListBuffer [PrewarmContainerData ] = new ListBuffer [PrewarmContainerData ]()
482
+ containerDataList.foreach { prewarmData =>
483
+ val isInclude = resultList.filter { resultData =>
484
+ prewarmData.kind == resultData.kind && prewarmData.memoryLimit.toMB == resultData.memory
485
+ }.size > 0
486
+
487
+ if (isInclude) {
488
+ var resultData = resultList.filter { resultData =>
489
+ prewarmData.kind == resultData.kind && prewarmData.memoryLimit.toMB == resultData.memory
490
+ }.head
491
+ resultData.number += 1
492
+ } else {
493
+ resultList += PrewarmContainerData (prewarmData.kind, prewarmData.memoryLimit.toMB, 1 )
494
+ }
495
+ }
496
+ resultList
497
+ }
498
+
439
499
/**
440
500
* Calculate if there is enough free memory within a given pool.
441
501
*
0 commit comments