@@ -19,18 +19,22 @@ 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
32
33
case class ColdStartKey (kind : String , memory : ByteSize )
33
34
35
+ case class PreWarmConfigList (list : List [PrewarmingConfig ])
36
+ object PrewarmQuery
37
+
34
38
case object EmitMetrics
35
39
36
40
case object AdjustPrewarmedContainer
@@ -68,6 +72,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
68
72
var busyPool = immutable.Map .empty[ActorRef , ContainerData ]
69
73
var prewarmedPool = immutable.Map .empty[ActorRef , PreWarmedData ]
70
74
var prewarmStartingPool = immutable.Map .empty[ActorRef , (String , ByteSize )]
75
+ var latestPrewarmConfig = prewarmConfig
71
76
// If all memory slots are occupied and if there is currently no container to be removed, than the actions will be
72
77
// buffered here to keep order of computation.
73
78
// Otherwise actions with small memory-limits could block actions with large memory limits.
@@ -297,6 +302,34 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
297
302
case RescheduleJob =>
298
303
freePool = freePool - sender()
299
304
busyPool = busyPool - sender()
305
+ case prewarmConfigList : PreWarmConfigList =>
306
+ logging.info(this , " update prewarm configuration request is send to invoker" )
307
+ val passedPrewarmConfig = prewarmConfigList.list
308
+ var newPrewarmConfig : List [PrewarmingConfig ] = List .empty
309
+ latestPrewarmConfig foreach { config =>
310
+ newPrewarmConfig = newPrewarmConfig :+ passedPrewarmConfig
311
+ .find(passedConfig =>
312
+ passedConfig.exec.kind == config.exec.kind && passedConfig.memoryLimit == config.memoryLimit)
313
+ .getOrElse(config)
314
+ }
315
+ latestPrewarmConfig = newPrewarmConfig
316
+ // Delete prewarmedPool firstly
317
+ prewarmedPool foreach { element =>
318
+ val actor = element._1
319
+ actor ! Remove
320
+ prewarmedPool = prewarmedPool - actor
321
+ }
322
+ latestPrewarmConfig foreach { config =>
323
+ logging.info(
324
+ this ,
325
+ s " add pre-warming ${config.initialCount} ${config.exec.kind} ${config.memoryLimit.toString}" )(
326
+ TransactionId .invokerWarmup)
327
+ (1 to config.initialCount).foreach { _ =>
328
+ prewarmContainer(config.exec, config.memoryLimit, config.reactive.map(_.ttl))
329
+ }
330
+ }
331
+ case PrewarmQuery =>
332
+ sender() ! getPrewarmContainer()
300
333
case EmitMetrics =>
301
334
emitMetrics()
302
335
@@ -327,7 +360,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
327
360
def adjustPrewarmedContainer (init : Boolean , scheduled : Boolean ): Unit = {
328
361
if (scheduled) {
329
362
// on scheduled time, remove expired prewarms
330
- ContainerPool .removeExpired(poolConfig, prewarmConfig , prewarmedPool).foreach { p =>
363
+ ContainerPool .removeExpired(poolConfig, latestPrewarmConfig , prewarmedPool).foreach { p =>
331
364
prewarmedPool = prewarmedPool - p
332
365
p ! Remove
333
366
}
@@ -340,7 +373,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
340
373
}
341
374
// fill in missing prewarms (replaces any deletes)
342
375
ContainerPool
343
- .increasePrewarms(init, scheduled, coldStartCount, prewarmConfig , prewarmedPool, prewarmStartingPool)
376
+ .increasePrewarms(init, scheduled, coldStartCount, latestPrewarmConfig , prewarmedPool, prewarmStartingPool)
344
377
.foreach { c =>
345
378
val config = c._1
346
379
val currentCount = c._2._1
@@ -380,7 +413,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
380
413
381
414
/** this is only for cold start statistics of prewarm configs, e.g. not blackbox or other configs. */
382
415
def incrementColdStartCount (kind : String , memoryLimit : ByteSize ): Unit = {
383
- prewarmConfig
416
+ latestPrewarmConfig
384
417
.filter { config =>
385
418
kind == config.exec.kind && memoryLimit == config.memoryLimit
386
419
}
@@ -421,7 +454,9 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
421
454
422
455
// get the appropriate ttl from prewarm configs
423
456
val ttl =
424
- prewarmConfig.find(pc => pc.memoryLimit == memory && pc.exec.kind == kind).flatMap(_.reactive.map(_.ttl))
457
+ latestPrewarmConfig
458
+ .find(pc => pc.memoryLimit == memory && pc.exec.kind == kind)
459
+ .flatMap(_.reactive.map(_.ttl))
425
460
prewarmContainer(action.exec, memory, ttl)
426
461
(ref, data)
427
462
}
@@ -434,6 +469,31 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef,
434
469
busyPool = busyPool - toDelete
435
470
}
436
471
472
+ /**
473
+ * get the prewarm container
474
+ * @return
475
+ */
476
+ def getPrewarmContainer (): ListBuffer [PrewarmContainerData ] = {
477
+ val containerDataList = prewarmedPool.values.toList
478
+
479
+ var resultList : ListBuffer [PrewarmContainerData ] = new ListBuffer [PrewarmContainerData ]()
480
+ containerDataList.foreach { prewarmData =>
481
+ val isInclude = resultList.filter { resultData =>
482
+ prewarmData.kind == resultData.kind && prewarmData.memoryLimit.toMB == resultData.memory
483
+ }.size > 0
484
+
485
+ if (isInclude) {
486
+ var resultData = resultList.filter { resultData =>
487
+ prewarmData.kind == resultData.kind && prewarmData.memoryLimit.toMB == resultData.memory
488
+ }.head
489
+ resultData.number += 1
490
+ } else {
491
+ resultList += PrewarmContainerData (prewarmData.kind, prewarmData.memoryLimit.toMB, 1 )
492
+ }
493
+ }
494
+ resultList
495
+ }
496
+
437
497
/**
438
498
* Calculate if there is enough free memory within a given pool.
439
499
*
0 commit comments