summaryrefslogtreecommitdiff
path: root/opendc-simulator/opendc-simulator-resources
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-simulator/opendc-simulator-resources')
-rw-r--r--opendc-simulator/opendc-simulator-resources/build.gradle.kts39
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/jmh/kotlin/org/opendc/simulator/resources/SimResourceBenchmarks.kt144
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt211
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt128
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregator.kt38
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt74
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCloseableProvider.kt37
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCommand.kt52
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceConsumer.kt56
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceContext.kt61
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceControllableContext.kt64
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCounters.kt48
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt42
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt373
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceEvent.kt48
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceFlow.kt29
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceInterpreter.kt99
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt106
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProviderLogic.kt79
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSource.kt72
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceState.kt43
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt57
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt115
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt102
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSystem.kt43
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt206
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimConsumerBarrier.kt52
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimSpeedConsumerAdapter.kt83
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimTraceConsumer.kt73
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimWorkConsumer.kt58
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt393
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceCountersImpl.kt42
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt351
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceDomain.kt19
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceKey.kt28
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMinTest.kt200
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceCommandTest.kt74
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceContextTest.kt160
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSourceTest.kt273
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusiveTest.kt176
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMinTest.kt150
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceTransformerTest.kt222
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimWorkConsumerTest.kt58
43 files changed, 0 insertions, 4778 deletions
diff --git a/opendc-simulator/opendc-simulator-resources/build.gradle.kts b/opendc-simulator/opendc-simulator-resources/build.gradle.kts
deleted file mode 100644
index e4ffc3ff..00000000
--- a/opendc-simulator/opendc-simulator-resources/build.gradle.kts
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-description = "Uniform resource consumption simulation model"
-
-plugins {
- `kotlin-library-conventions`
- `testing-conventions`
- `jacoco-conventions`
- `benchmark-conventions`
-}
-
-dependencies {
- api(platform(projects.opendcPlatform))
- api(libs.kotlinx.coroutines)
- implementation(projects.opendcUtils)
-
- jmhImplementation(projects.opendcSimulator.opendcSimulatorCore)
- testImplementation(projects.opendcSimulator.opendcSimulatorCore)
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/jmh/kotlin/org/opendc/simulator/resources/SimResourceBenchmarks.kt b/opendc-simulator/opendc-simulator-resources/src/jmh/kotlin/org/opendc/simulator/resources/SimResourceBenchmarks.kt
deleted file mode 100644
index b45b2a2f..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/jmh/kotlin/org/opendc/simulator/resources/SimResourceBenchmarks.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.launch
-import org.opendc.simulator.core.SimulationCoroutineScope
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.consumer.SimTraceConsumer
-import org.openjdk.jmh.annotations.*
-import java.util.concurrent.TimeUnit
-
-@State(Scope.Thread)
-@Fork(1)
-@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS)
-@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS)
-@OptIn(ExperimentalCoroutinesApi::class)
-class SimResourceBenchmarks {
- private lateinit var scope: SimulationCoroutineScope
- private lateinit var interpreter: SimResourceInterpreter
-
- @Setup
- fun setUp() {
- scope = SimulationCoroutineScope()
- interpreter = SimResourceInterpreter(scope.coroutineContext, scope.clock)
- }
-
- @State(Scope.Thread)
- class Workload {
- lateinit var trace: Sequence<SimTraceConsumer.Fragment>
-
- @Setup
- fun setUp() {
- trace = sequenceOf(
- SimTraceConsumer.Fragment(1000, 28.0),
- SimTraceConsumer.Fragment(1000, 3500.0),
- SimTraceConsumer.Fragment(1000, 0.0),
- SimTraceConsumer.Fragment(1000, 183.0),
- SimTraceConsumer.Fragment(1000, 400.0),
- SimTraceConsumer.Fragment(1000, 100.0),
- SimTraceConsumer.Fragment(1000, 3000.0),
- SimTraceConsumer.Fragment(1000, 4500.0),
- )
- }
- }
-
- @Benchmark
- fun benchmarkSource(state: Workload) {
- return scope.runBlockingSimulation {
- val provider = SimResourceSource(4200.0, interpreter)
- return@runBlockingSimulation provider.consume(SimTraceConsumer(state.trace))
- }
- }
-
- @Benchmark
- fun benchmarkForwardOverhead(state: Workload) {
- return scope.runBlockingSimulation {
- val provider = SimResourceSource(4200.0, interpreter)
- val forwarder = SimResourceForwarder()
- provider.startConsumer(forwarder)
- return@runBlockingSimulation forwarder.consume(SimTraceConsumer(state.trace))
- }
- }
-
- @Benchmark
- fun benchmarkSwitchMaxMinSingleConsumer(state: Workload) {
- return scope.runBlockingSimulation {
- val switch = SimResourceSwitchMaxMin(interpreter)
-
- switch.addInput(SimResourceSource(3000.0, interpreter))
- switch.addInput(SimResourceSource(3000.0, interpreter))
-
- val provider = switch.newOutput()
- return@runBlockingSimulation provider.consume(SimTraceConsumer(state.trace))
- }
- }
-
- @Benchmark
- fun benchmarkSwitchMaxMinTripleConsumer(state: Workload) {
- return scope.runBlockingSimulation {
- val switch = SimResourceSwitchMaxMin(interpreter)
-
- switch.addInput(SimResourceSource(3000.0, interpreter))
- switch.addInput(SimResourceSource(3000.0, interpreter))
-
- repeat(3) {
- launch {
- val provider = switch.newOutput()
- provider.consume(SimTraceConsumer(state.trace))
- }
- }
- }
- }
-
- @Benchmark
- fun benchmarkSwitchExclusiveSingleConsumer(state: Workload) {
- return scope.runBlockingSimulation {
- val switch = SimResourceSwitchExclusive()
-
- switch.addInput(SimResourceSource(3000.0, interpreter))
- switch.addInput(SimResourceSource(3000.0, interpreter))
-
- val provider = switch.newOutput()
- return@runBlockingSimulation provider.consume(SimTraceConsumer(state.trace))
- }
- }
-
- @Benchmark
- fun benchmarkSwitchExclusiveTripleConsumer(state: Workload) {
- return scope.runBlockingSimulation {
- val switch = SimResourceSwitchExclusive()
-
- switch.addInput(SimResourceSource(3000.0, interpreter))
- switch.addInput(SimResourceSource(3000.0, interpreter))
-
- repeat(2) {
- launch {
- val provider = switch.newOutput()
- provider.consume(SimTraceConsumer(state.trace))
- }
- }
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt
deleted file mode 100644
index 00648876..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * Abstract implementation of [SimResourceAggregator].
- */
-public abstract class SimAbstractResourceAggregator(
- interpreter: SimResourceInterpreter,
- parent: SimResourceSystem?
-) : SimResourceAggregator {
- /**
- * This method is invoked when the resource consumer consumes resources.
- */
- protected abstract fun doConsume(work: Double, limit: Double, deadline: Long)
-
- /**
- * This method is invoked when the resource consumer enters an idle state.
- */
- protected abstract fun doIdle(deadline: Long)
-
- /**
- * This method is invoked when the resource consumer finishes processing.
- */
- protected abstract fun doFinish()
-
- /**
- * This method is invoked when an input context is started.
- */
- protected abstract fun onInputStarted(input: Input)
-
- /**
- * This method is invoked when an input is stopped.
- */
- protected abstract fun onInputFinished(input: Input)
-
- /* SimResourceAggregator */
- override fun addInput(input: SimResourceProvider) {
- val consumer = Consumer()
- _inputs.add(input)
- _inputConsumers.add(consumer)
- input.startConsumer(consumer)
- }
-
- override val inputs: Set<SimResourceProvider>
- get() = _inputs
- private val _inputs = mutableSetOf<SimResourceProvider>()
- private val _inputConsumers = mutableListOf<Consumer>()
-
- /* SimResourceProvider */
- override val isActive: Boolean
- get() = _output.isActive
-
- override val capacity: Double
- get() = _output.capacity
-
- override val speed: Double
- get() = _output.speed
-
- override val demand: Double
- get() = _output.demand
-
- override val counters: SimResourceCounters
- get() = _output.counters
-
- override fun startConsumer(consumer: SimResourceConsumer) {
- _output.startConsumer(consumer)
- }
-
- override fun cancel() {
- _output.cancel()
- }
-
- override fun interrupt() {
- _output.interrupt()
- }
-
- private val _output = object : SimAbstractResourceProvider(interpreter, parent, initialCapacity = 0.0) {
- override fun createLogic(): SimResourceProviderLogic {
- return object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long {
- doIdle(deadline)
- return Long.MAX_VALUE
- }
-
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long {
- doConsume(work, limit, deadline)
- return Long.MAX_VALUE
- }
-
- override fun onFinish(ctx: SimResourceControllableContext) {
- doFinish()
- }
-
- override fun onUpdate(ctx: SimResourceControllableContext, work: Double, willOvercommit: Boolean) {
- updateCounters(ctx, work, willOvercommit)
- }
-
- override fun getConsumedWork(ctx: SimResourceControllableContext, work: Double, speed: Double, duration: Long): Double {
- return work - _inputConsumers.sumOf { it.remainingWork }
- }
- }
- }
-
- /**
- * Flush the progress of the output if possible.
- */
- fun flush() {
- ctx?.flush()
- }
- }
-
- /**
- * An input for the resource aggregator.
- */
- public interface Input {
- /**
- * The [SimResourceContext] associated with the input.
- */
- public val ctx: SimResourceContext
-
- /**
- * Push the specified [SimResourceCommand] to the input.
- */
- public fun push(command: SimResourceCommand)
- }
-
- /**
- * An internal [SimResourceConsumer] implementation for aggregator inputs.
- */
- private inner class Consumer : Input, SimResourceConsumer {
- /**
- * The resource context associated with the input.
- */
- override val ctx: SimResourceContext
- get() = _ctx!!
- private var _ctx: SimResourceContext? = null
-
- /**
- * The remaining work of the consumer.
- */
- val remainingWork: Double
- get() = _ctx?.remainingWork ?: 0.0
-
- /**
- * The resource command to run next.
- */
- private var command: SimResourceCommand? = null
-
- private fun updateCapacity() {
- // Adjust capacity of output resource
- _output.capacity = _inputConsumers.sumOf { it._ctx?.capacity ?: 0.0 }
- }
-
- /* Input */
- override fun push(command: SimResourceCommand) {
- this.command = command
- _ctx?.interrupt()
- }
-
- /* SimResourceConsumer */
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- var next = command
-
- return if (next != null) {
- this.command = null
- next
- } else {
- _output.flush()
-
- next = command
- this.command = null
- next ?: SimResourceCommand.Idle()
- }
- }
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- when (event) {
- SimResourceEvent.Start -> {
- _ctx = ctx
- updateCapacity()
-
- onInputStarted(this)
- }
- SimResourceEvent.Capacity -> updateCapacity()
- SimResourceEvent.Exit -> onInputFinished(this)
- else -> {}
- }
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt
deleted file mode 100644
index 4e8e803a..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.impl.SimResourceCountersImpl
-
-/**
- * Abstract implementation of the [SimResourceProvider] which can be re-used by other implementations.
- */
-public abstract class SimAbstractResourceProvider(
- private val interpreter: SimResourceInterpreter,
- private val parent: SimResourceSystem?,
- initialCapacity: Double
-) : SimResourceProvider {
- /**
- * A flag to indicate that the resource provider is active.
- */
- public override val isActive: Boolean
- get() = ctx != null
-
- /**
- * The capacity of the resource.
- */
- public override var capacity: Double = initialCapacity
- set(value) {
- field = value
- ctx?.capacity = value
- }
-
- /**
- * The current processing speed of the resource.
- */
- public override val speed: Double
- get() = ctx?.speed ?: 0.0
-
- /**
- * The resource processing speed demand at this instant.
- */
- public override val demand: Double
- get() = ctx?.demand ?: 0.0
-
- /**
- * The resource counters to track the execution metrics of the resource.
- */
- public override val counters: SimResourceCounters
- get() = _counters
- private val _counters = SimResourceCountersImpl()
-
- /**
- * The [SimResourceControllableContext] that is currently running.
- */
- protected var ctx: SimResourceControllableContext? = null
- private set
-
- /**
- * Construct the [SimResourceProviderLogic] instance for a new consumer.
- */
- protected abstract fun createLogic(): SimResourceProviderLogic
-
- /**
- * Start the specified [SimResourceControllableContext].
- */
- protected open fun start(ctx: SimResourceControllableContext) {
- ctx.start()
- }
-
- /**
- * Update the counters of the resource provider.
- */
- protected fun updateCounters(ctx: SimResourceContext, work: Double, willOvercommit: Boolean) {
- if (work <= 0.0) {
- return
- }
-
- val counters = _counters
- val remainingWork = ctx.remainingWork
- counters.demand += work
- counters.actual += work - remainingWork
-
- if (willOvercommit && remainingWork > 0.0) {
- counters.overcommit += remainingWork
- }
- }
-
- final override fun startConsumer(consumer: SimResourceConsumer) {
- check(ctx == null) { "Resource is in invalid state" }
- val ctx = interpreter.newContext(consumer, createLogic(), parent)
-
- ctx.capacity = capacity
- this.ctx = ctx
-
- start(ctx)
- }
-
- final override fun interrupt() {
- ctx?.interrupt()
- }
-
- final override fun cancel() {
- val ctx = ctx
- if (ctx != null) {
- this.ctx = null
- ctx.close()
- }
- }
-
- override fun toString(): String = "SimAbstractResourceProvider[capacity=$capacity]"
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregator.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregator.kt
deleted file mode 100644
index 00972f43..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregator.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A [SimResourceAggregator] aggregates the capacity of multiple resources into a single resource.
- */
-public interface SimResourceAggregator : SimResourceProvider {
- /**
- * The input resources that will be switched between the output providers.
- */
- public val inputs: Set<SimResourceProvider>
-
- /**
- * Add the specified [input] to the aggregator.
- */
- public fun addInput(input: SimResourceProvider)
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt
deleted file mode 100644
index 991cda7a..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A [SimResourceAggregator] that distributes the load equally across the input resources.
- */
-public class SimResourceAggregatorMaxMin(
- interpreter: SimResourceInterpreter,
- parent: SimResourceSystem? = null
-) : SimAbstractResourceAggregator(interpreter, parent) {
- private val consumers = mutableListOf<Input>()
-
- override fun doConsume(work: Double, limit: Double, deadline: Long) {
- // Sort all consumers by their capacity
- consumers.sortWith(compareBy { it.ctx.capacity })
-
- // Divide the requests over the available capacity of the input resources fairly
- for (input in consumers) {
- val inputCapacity = input.ctx.capacity
- val fraction = inputCapacity / capacity
- val grantedSpeed = limit * fraction
- val grantedWork = fraction * work
-
- val command = if (grantedWork > 0.0 && grantedSpeed > 0.0)
- SimResourceCommand.Consume(grantedWork, grantedSpeed, deadline)
- else
- SimResourceCommand.Idle()
- input.push(command)
- }
- }
-
- override fun doIdle(deadline: Long) {
- for (input in consumers) {
- input.push(SimResourceCommand.Idle(deadline))
- }
- }
-
- override fun doFinish() {
- val iterator = consumers.iterator()
- for (input in iterator) {
- iterator.remove()
- input.push(SimResourceCommand.Exit)
- }
- }
-
- override fun onInputStarted(input: Input) {
- consumers.add(input)
- }
-
- override fun onInputFinished(input: Input) {
- consumers.remove(input)
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCloseableProvider.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCloseableProvider.kt
deleted file mode 100644
index bce8274b..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCloseableProvider.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A [SimResourceProvider] that has a controllable and limited lifetime.
- *
- * This interface is used to signal that the resource provider may be closed and not reused after that point.
- */
-public interface SimResourceCloseableProvider : SimResourceProvider, AutoCloseable {
- /**
- * End the lifetime of the resource provider.
- *
- * This operation cancels the existing resource consumer and prevents the resource provider from being reused.
- */
- public override fun close()
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCommand.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCommand.kt
deleted file mode 100644
index f7f3fa4d..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCommand.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A SimResourceCommand communicates to a resource how it is consumed by a [SimResourceConsumer].
- */
-public sealed class SimResourceCommand {
- /**
- * A request to the resource to perform the specified amount of work before the given [deadline].
- *
- * @param work The amount of work to process.
- * @param limit The maximum amount of work to be processed per second.
- * @param deadline The instant at which the work needs to be fulfilled.
- */
- public data class Consume(val work: Double, val limit: Double, val deadline: Long = Long.MAX_VALUE) : SimResourceCommand() {
- init {
- require(work > 0) { "Amount of work must be positive" }
- require(limit > 0) { "Limit must be positive" }
- }
- }
-
- /**
- * An indication to the resource that the consumer will idle until the specified [deadline] or if it is interrupted.
- */
- public data class Idle(val deadline: Long = Long.MAX_VALUE) : SimResourceCommand()
-
- /**
- * An indication to the resource that the consumer has finished.
- */
- public object Exit : SimResourceCommand()
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceConsumer.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceConsumer.kt
deleted file mode 100644
index 4d937514..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceConsumer.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A [SimResourceConsumer] characterizes how a resource is consumed.
- *
- * Implementors of this interface should be considered stateful and must be assumed not to be re-usable (concurrently)
- * for multiple resource providers, unless explicitly said otherwise.
- */
-public interface SimResourceConsumer {
- /**
- * This method is invoked when a resource asks for the next [command][SimResourceCommand] to process, either because
- * the resource finished processing, reached its deadline or was interrupted.
- *
- * @param ctx The execution context in which the consumer runs.
- * @return The next command that the resource should execute.
- */
- public fun onNext(ctx: SimResourceContext): SimResourceCommand
-
- /**
- * This method is invoked when an event has occurred.
- *
- * @param ctx The execution context in which the consumer runs.
- * @param event The event that has occurred.
- */
- public fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {}
-
- /**
- * This method is invoked when a resource consumer throws an exception.
- *
- * @param ctx The execution context in which the consumer runs.
- * @param cause The cause of the failure.
- */
- public fun onFailure(ctx: SimResourceContext, cause: Throwable) {}
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceContext.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceContext.kt
deleted file mode 100644
index 0d9a6106..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceContext.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import java.time.Clock
-
-/**
- * The execution context in which a [SimResourceConsumer] runs. It facilitates the communication and control between a
- * resource and a resource consumer.
- */
-public interface SimResourceContext {
- /**
- * The virtual clock tracking simulation time.
- */
- public val clock: Clock
-
- /**
- * The resource capacity available at this instant.
- */
- public val capacity: Double
-
- /**
- * The resource processing speed at this instant.
- */
- public val speed: Double
-
- /**
- * The resource processing speed demand at this instant.
- */
- public val demand: Double
-
- /**
- * The amount of work still remaining at this instant.
- */
- public val remainingWork: Double
-
- /**
- * Ask the resource provider to interrupt its resource.
- */
- public fun interrupt()
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceControllableContext.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceControllableContext.kt
deleted file mode 100644
index ceaca39a..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceControllableContext.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A controllable [SimResourceContext].
- *
- * This interface is used by resource providers to control the resource context.
- */
-public interface SimResourceControllableContext : SimResourceContext, AutoCloseable {
- /**
- * The state of the resource context.
- */
- public val state: SimResourceState
-
- /**
- * The capacity of the resource.
- */
- public override var capacity: Double
-
- /**
- * Start the resource context.
- */
- public fun start()
-
- /**
- * Stop the resource context.
- */
- public override fun close()
-
- /**
- * Invalidate the resource context's state.
- *
- * By invalidating the resource context's current state, the state is re-computed and the current progress is
- * materialized during the next interpreter cycle. As a result, this call run asynchronously. See [flush] for the
- * synchronous variant.
- */
- public fun invalidate()
-
- /**
- * Synchronously flush the progress of the resource context and materialize its current progress.
- */
- public fun flush()
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCounters.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCounters.kt
deleted file mode 100644
index 725aa5bc..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCounters.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * An interface that tracks cumulative counts of the work performed by a resource.
- */
-public interface SimResourceCounters {
- /**
- * The amount of work that resource consumers wanted the resource to perform.
- */
- public val demand: Double
-
- /**
- * The amount of work performed by the resource.
- */
- public val actual: Double
-
- /**
- * The amount of work that could not be completed due to overcommitted resources.
- */
- public val overcommit: Double
-
- /**
- * Reset the resource counters.
- */
- public fun reset()
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt
deleted file mode 100644
index f384582f..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.interference.InterferenceKey
-
-/**
- * A [SimResourceDistributor] distributes the capacity of some resource over multiple resource consumers.
- */
-public interface SimResourceDistributor : SimResourceConsumer {
- /**
- * The output resource providers to which resource consumers can be attached.
- */
- public val outputs: Set<SimResourceCloseableProvider>
-
- /**
- * Create a new output for the distributor.
- *
- * @param key The key of the interference member to which the output belongs.
- */
- public fun newOutput(key: InterferenceKey? = null): SimResourceCloseableProvider
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt
deleted file mode 100644
index 6c1e134b..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.interference.InterferenceDomain
-import org.opendc.simulator.resources.interference.InterferenceKey
-import kotlin.math.max
-import kotlin.math.min
-
-/**
- * A [SimResourceDistributor] that distributes the capacity of a resource over consumers using max-min fair sharing.
- *
- * @param interpreter The interpreter for managing the resource contexts.
- * @param parent The parent resource system of the distributor.
- * @param interferenceDomain The interference domain of the distributor.
- */
-public class SimResourceDistributorMaxMin(
- private val interpreter: SimResourceInterpreter,
- private val parent: SimResourceSystem? = null,
- private val interferenceDomain: InterferenceDomain? = null
-) : SimResourceDistributor {
- override val outputs: Set<SimResourceCloseableProvider>
- get() = _outputs
- private val _outputs = mutableSetOf<Output>()
-
- /**
- * The resource context of the consumer.
- */
- private var ctx: SimResourceContext? = null
-
- /**
- * The active outputs.
- */
- private val activeOutputs: MutableList<Output> = mutableListOf()
-
- /**
- * The total amount of work allocated to be executed.
- */
- private var totalAllocatedWork = 0.0
-
- /**
- * The total allocated speed for the output resources.
- */
- private var totalAllocatedSpeed = 0.0
-
- /**
- * The total requested speed for the output resources.
- */
- private var totalRequestedSpeed = 0.0
-
- /**
- * The resource counters of this distributor.
- */
- public val counters: Counters
- get() = _counters
- private val _counters = object : Counters {
- override var demand: Double = 0.0
- override var actual: Double = 0.0
- override var overcommit: Double = 0.0
- override var interference: Double = 0.0
-
- override fun reset() {
- demand = 0.0
- actual = 0.0
- overcommit = 0.0
- interference = 0.0
- }
-
- override fun toString(): String = "SimResourceDistributorMaxMin.Counters[demand=$demand,actual=$actual,overcommit=$overcommit,interference=$interference]"
- }
-
- /* SimResourceDistributor */
- override fun newOutput(key: InterferenceKey?): SimResourceCloseableProvider {
- val provider = Output(ctx?.capacity ?: 0.0, key)
- _outputs.add(provider)
- return provider
- }
-
- /* SimResourceConsumer */
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- return doNext(ctx)
- }
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- when (event) {
- SimResourceEvent.Start -> {
- this.ctx = ctx
- updateCapacity(ctx)
- }
- SimResourceEvent.Exit -> {
- val iterator = _outputs.iterator()
- while (iterator.hasNext()) {
- val output = iterator.next()
-
- // Remove the output from the outputs to prevent ConcurrentModificationException when removing it
- // during the call to output.close()
- iterator.remove()
-
- output.close()
- }
- }
- SimResourceEvent.Capacity -> updateCapacity(ctx)
- else -> {}
- }
- }
-
- /**
- * Extended [SimResourceCounters] interface for the distributor.
- */
- public interface Counters : SimResourceCounters {
- /**
- * The amount of work lost due to interference.
- */
- public val interference: Double
- }
-
- /**
- * Update the counters of the distributor.
- */
- private fun updateCounters(ctx: SimResourceControllableContext, work: Double, willOvercommit: Boolean) {
- if (work <= 0.0) {
- return
- }
-
- val counters = _counters
- val remainingWork = ctx.remainingWork
-
- counters.demand += work
- counters.actual += work - remainingWork
-
- if (willOvercommit && remainingWork > 0.0) {
- counters.overcommit += remainingWork
- }
- }
-
- /**
- * Schedule the work of the outputs.
- */
- private fun doNext(ctx: SimResourceContext): SimResourceCommand {
- // If there is no work yet, mark the input as idle.
- if (activeOutputs.isEmpty()) {
- return SimResourceCommand.Idle()
- }
-
- val capacity = ctx.capacity
- var duration: Double = Double.MAX_VALUE
- var deadline: Long = Long.MAX_VALUE
- var availableSpeed = capacity
- var totalRequestedSpeed = 0.0
-
- // Pull in the work of the outputs
- val outputIterator = activeOutputs.listIterator()
- for (output in outputIterator) {
- output.pull()
-
- // Remove outputs that have finished
- if (!output.isActive) {
- outputIterator.remove()
- }
- }
-
- // Sort in-place the outputs based on their requested usage.
- // Profiling shows that it is faster than maintaining some kind of sorted set.
- activeOutputs.sort()
-
- // Divide the available input capacity fairly across the outputs using max-min fair sharing
- var remaining = activeOutputs.size
- for (output in activeOutputs) {
- val availableShare = availableSpeed / remaining--
- val grantedSpeed = min(output.allowedSpeed, availableShare)
-
- deadline = min(deadline, output.deadline)
-
- // Ignore idle computation
- if (grantedSpeed <= 0.0 || output.work <= 0.0) {
- output.actualSpeed = 0.0
- continue
- }
-
- totalRequestedSpeed += output.limit
-
- output.actualSpeed = grantedSpeed
- availableSpeed -= grantedSpeed
-
- // The duration that we want to run is that of the shortest request of an output
- duration = min(duration, output.work / grantedSpeed)
- }
-
- val targetDuration = min(duration, (deadline - interpreter.clock.millis()) / 1000.0)
- var totalRequestedWork = 0.0
- var totalAllocatedWork = 0.0
- for (output in activeOutputs) {
- val work = output.work
- val speed = output.actualSpeed
- if (speed > 0.0) {
- val outputDuration = work / speed
- totalRequestedWork += work * (duration / outputDuration)
- totalAllocatedWork += work * (targetDuration / outputDuration)
- }
- }
-
- assert(deadline >= interpreter.clock.millis()) { "Deadline already passed" }
-
- this.totalRequestedSpeed = totalRequestedSpeed
- this.totalAllocatedWork = totalAllocatedWork
- val totalAllocatedSpeed = capacity - availableSpeed
- this.totalAllocatedSpeed = totalAllocatedSpeed
-
- return if (totalAllocatedWork > 0.0 && totalAllocatedSpeed > 0.0)
- SimResourceCommand.Consume(totalAllocatedWork, totalAllocatedSpeed, deadline)
- else
- SimResourceCommand.Idle(deadline)
- }
-
- private fun updateCapacity(ctx: SimResourceContext) {
- for (output in _outputs) {
- output.capacity = ctx.capacity
- }
- }
-
- /**
- * An internal [SimResourceProvider] implementation for switch outputs.
- */
- private inner class Output(capacity: Double, private val key: InterferenceKey?) :
- SimAbstractResourceProvider(interpreter, parent, capacity),
- SimResourceCloseableProvider,
- SimResourceProviderLogic,
- Comparable<Output> {
- /**
- * A flag to indicate that the output is closed.
- */
- private var isClosed: Boolean = false
-
- /**
- * The current requested work.
- */
- var work: Double = 0.0
-
- /**
- * The requested limit.
- */
- var limit: Double = 0.0
-
- /**
- * The current deadline.
- */
- var deadline: Long = Long.MAX_VALUE
-
- /**
- * The processing speed that is allowed by the model constraints.
- */
- var allowedSpeed: Double = 0.0
-
- /**
- * The actual processing speed.
- */
- var actualSpeed: Double = 0.0
-
- /**
- * The timestamp at which we received the last command.
- */
- private var lastCommandTimestamp: Long = Long.MIN_VALUE
-
- /* SimAbstractResourceProvider */
- override fun createLogic(): SimResourceProviderLogic = this
-
- override fun start(ctx: SimResourceControllableContext) {
- check(!isClosed) { "Cannot re-use closed output" }
-
- activeOutputs += this
- interpreter.batch {
- ctx.start()
- // Interrupt the input to re-schedule the resources
- this@SimResourceDistributorMaxMin.ctx?.interrupt()
- }
- }
-
- override fun close() {
- isClosed = true
- cancel()
- _outputs.remove(this)
- }
-
- /* SimResourceProviderLogic */
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long {
- allowedSpeed = 0.0
- this.deadline = deadline
- work = 0.0
- limit = 0.0
- lastCommandTimestamp = ctx.clock.millis()
-
- return Long.MAX_VALUE
- }
-
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long {
- allowedSpeed = min(ctx.capacity, limit)
- this.work = work
- this.limit = limit
- this.deadline = deadline
- lastCommandTimestamp = ctx.clock.millis()
-
- return Long.MAX_VALUE
- }
-
- override fun onUpdate(ctx: SimResourceControllableContext, work: Double, willOvercommit: Boolean) {
- updateCounters(ctx, work, willOvercommit)
-
- this@SimResourceDistributorMaxMin.updateCounters(ctx, work, willOvercommit)
- }
-
- override fun onFinish(ctx: SimResourceControllableContext) {
- work = 0.0
- limit = 0.0
- deadline = Long.MAX_VALUE
- lastCommandTimestamp = ctx.clock.millis()
- }
-
- override fun getConsumedWork(ctx: SimResourceControllableContext, work: Double, speed: Double, duration: Long): Double {
- val totalRemainingWork = this@SimResourceDistributorMaxMin.ctx?.remainingWork ?: 0.0
-
- // Compute the fraction of compute time allocated to the output
- val fraction = actualSpeed / totalAllocatedSpeed
-
- // Compute the performance penalty due to resource interference
- val perfScore = if (interferenceDomain != null) {
- val load = totalAllocatedSpeed / requireNotNull(this@SimResourceDistributorMaxMin.ctx).capacity
- interferenceDomain.apply(key, load)
- } else {
- 1.0
- }
-
- // Compute the work that was actually granted to the output.
- val potentialConsumedWork = (totalAllocatedWork - totalRemainingWork) * fraction
-
- _counters.interference += potentialConsumedWork * max(0.0, 1 - perfScore)
-
- return potentialConsumedWork
- }
-
- /* Comparable */
- override fun compareTo(other: Output): Int = allowedSpeed.compareTo(other.allowedSpeed)
-
- /**
- * Pull the next command if necessary.
- */
- fun pull() {
- val ctx = ctx
- if (ctx != null && lastCommandTimestamp < ctx.clock.millis()) {
- ctx.flush()
- }
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceEvent.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceEvent.kt
deleted file mode 100644
index 959427f1..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceEvent.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A resource event that is communicated to the resource consumer.
- */
-public enum class SimResourceEvent {
- /**
- * This event is emitted to the consumer when it has started.
- */
- Start,
-
- /**
- * This event is emitted to the consumer when it has exited.
- */
- Exit,
-
- /**
- * This event is emitted to the consumer when it has started a new resource consumption or idle cycle.
- */
- Run,
-
- /**
- * This event is emitted to the consumer when the capacity of the resource has changed.
- */
- Capacity,
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceFlow.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceFlow.kt
deleted file mode 100644
index bbf6ad44..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceFlow.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A [SimResourceFlow] acts as both a resource consumer and resource provider at the same time, simplifying bridging
- * between different components.
- */
-public interface SimResourceFlow : SimResourceConsumer, SimResourceProvider
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceInterpreter.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceInterpreter.kt
deleted file mode 100644
index 82631377..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceInterpreter.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-import java.time.Clock
-import kotlin.coroutines.CoroutineContext
-
-/**
- * The resource interpreter is responsible for managing the interaction between resource consumer and provider.
- *
- * The interpreter centralizes the scheduling logic of state updates of resource context, allowing update propagation
- * to happen more efficiently. and overall, reducing the work necessary to transition into a steady state.
- */
-public interface SimResourceInterpreter {
- /**
- * The [Clock] associated with this interpreter.
- */
- public val clock: Clock
-
- /**
- * Create a new [SimResourceControllableContext] with the given [provider].
- *
- * @param consumer The consumer logic.
- * @param provider The logic of the resource provider.
- * @param parent The system to which the resource context belongs.
- */
- public fun newContext(
- consumer: SimResourceConsumer,
- provider: SimResourceProviderLogic,
- parent: SimResourceSystem? = null
- ): SimResourceControllableContext
-
- /**
- * Start batching the execution of resource updates until [popBatch] is called.
- *
- * This method is useful if you want to propagate multiple resources updates (e.g., starting multiple CPUs
- * simultaneously) in a single state update.
- *
- * Multiple calls to this method requires the same number of [popBatch] calls in order to properly flush the
- * resource updates. This allows nested calls to [pushBatch], but might cause issues if [popBatch] is not called
- * the same amount of times. To simplify batching, see [batch].
- */
- public fun pushBatch()
-
- /**
- * Stop the batching of resource updates and run the interpreter on the batch.
- *
- * Note that method will only flush the event once the first call to [pushBatch] has received a [popBatch] call.
- */
- public fun popBatch()
-
- public companion object {
- /**
- * Construct a new [SimResourceInterpreter] implementation.
- *
- * @param context The coroutine context to use.
- * @param clock The virtual simulation clock.
- */
- @JvmName("create")
- public operator fun invoke(context: CoroutineContext, clock: Clock): SimResourceInterpreter {
- return SimResourceInterpreterImpl(context, clock)
- }
- }
-}
-
-/**
- * Batch the execution of several interrupts into a single call.
- *
- * This method is useful if you want to propagate the start of multiple resources (e.g., CPUs) in a single update.
- */
-public inline fun SimResourceInterpreter.batch(block: () -> Unit) {
- try {
- pushBatch()
- block()
- } finally {
- popBatch()
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt
deleted file mode 100644
index b68b7261..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import kotlinx.coroutines.suspendCancellableCoroutine
-import kotlin.coroutines.resume
-import kotlin.coroutines.resumeWithException
-
-/**
- * A [SimResourceProvider] provides a resource that can be consumed by a [SimResourceConsumer].
- */
-public interface SimResourceProvider {
- /**
- * A flag to indicate that the resource provider is currently being consumed by a [SimResourceConsumer].
- */
- public val isActive: Boolean
-
- /**
- * The resource capacity available at this instant.
- */
- public val capacity: Double
-
- /**
- * The current processing speed of the resource.
- */
- public val speed: Double
-
- /**
- * The resource processing speed demand at this instant.
- */
- public val demand: Double
-
- /**
- * The resource counters to track the execution metrics of the resource.
- */
- public val counters: SimResourceCounters
-
- /**
- * Start the specified [resource consumer][consumer] in the context of this resource provider asynchronously.
- *
- * @throws IllegalStateException if there is already a consumer active or the resource lifetime has ended.
- */
- public fun startConsumer(consumer: SimResourceConsumer)
-
- /**
- * Interrupt the resource consumer. If there is no consumer active, this operation will be a no-op.
- */
- public fun interrupt()
-
- /**
- * Cancel the current resource consumer. If there is no consumer active, this operation will be a no-op.
- */
- public fun cancel()
-}
-
-/**
- * Consume the resource provided by this provider using the specified [consumer] and suspend execution until
- * the consumer has finished.
- */
-public suspend fun SimResourceProvider.consume(consumer: SimResourceConsumer) {
- return suspendCancellableCoroutine { cont ->
- startConsumer(object : SimResourceConsumer by consumer {
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- consumer.onEvent(ctx, event)
-
- if (event == SimResourceEvent.Exit && !cont.isCompleted) {
- cont.resume(Unit)
- }
- }
-
- override fun onFailure(ctx: SimResourceContext, cause: Throwable) {
- try {
- consumer.onFailure(ctx, cause)
- cont.resumeWithException(cause)
- } catch (e: Throwable) {
- e.addSuppressed(cause)
- cont.resumeWithException(e)
- }
- }
-
- override fun toString(): String = "SimSuspendingResourceConsumer"
- })
-
- cont.invokeOnCancellation { cancel() }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProviderLogic.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProviderLogic.kt
deleted file mode 100644
index 2fe1b00f..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProviderLogic.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * The logic of a resource provider.
- */
-public interface SimResourceProviderLogic {
- /**
- * This method is invoked when the resource is reported to idle until the specified [deadline].
- *
- * @param ctx The context in which the provider runs.
- * @param deadline The deadline that was requested by the resource consumer.
- * @return The instant at which to resume the consumer.
- */
- public fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long
-
- /**
- * This method is invoked when the resource will be consumed until the specified amount of [work] was processed
- * or [deadline] is reached.
- *
- * @param ctx The context in which the provider runs.
- * @param work The amount of work that was requested by the resource consumer.
- * @param limit The limit on the work rate of the resource consumer.
- * @param deadline The deadline that was requested by the resource consumer.
- * @return The instant at which to resume the consumer.
- */
- public fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long
-
- /**
- * This method is invoked when the progress of the resource consumer is materialized.
- *
- * @param ctx The context in which the provider runs.
- * @param work The amount of work that was requested by the resource consumer.
- * @param willOvercommit A flag to indicate that the remaining work is overcommitted.
- */
- public fun onUpdate(ctx: SimResourceControllableContext, work: Double, willOvercommit: Boolean) {}
-
- /**
- * This method is invoked when the resource consumer has finished.
- */
- public fun onFinish(ctx: SimResourceControllableContext)
-
- /**
- * Compute the amount of work that was consumed over the specified [duration].
- *
- * @param work The total size of the resource consumption.
- * @param speed The speed of the resource provider.
- * @param duration The duration from the start of the consumption until now.
- * @return The amount of work that was consumed by the resource provider.
- */
- public fun getConsumedWork(ctx: SimResourceControllableContext, work: Double, speed: Double, duration: Long): Double {
- return if (duration > 0L) {
- return (duration / 1000.0) * speed
- } else {
- work
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSource.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSource.kt
deleted file mode 100644
index 2d53198a..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSource.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import kotlin.math.ceil
-import kotlin.math.min
-
-/**
- * A [SimResourceSource] represents a source for some resource that provides bounded processing capacity.
- *
- * @param initialCapacity The initial capacity of the resource.
- * @param interpreter The interpreter that is used for managing the resource contexts.
- * @param parent The parent resource system.
- */
-public class SimResourceSource(
- initialCapacity: Double,
- private val interpreter: SimResourceInterpreter,
- private val parent: SimResourceSystem? = null
-) : SimAbstractResourceProvider(interpreter, parent, initialCapacity) {
- override fun createLogic(): SimResourceProviderLogic {
- return object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long {
- return deadline
- }
-
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long {
- return if (work.isInfinite()) {
- Long.MAX_VALUE
- } else {
- min(deadline, ctx.clock.millis() + getDuration(work, speed))
- }
- }
-
- override fun onUpdate(ctx: SimResourceControllableContext, work: Double, willOvercommit: Boolean) {
- updateCounters(ctx, work, willOvercommit)
- }
-
- override fun onFinish(ctx: SimResourceControllableContext) {
- cancel()
- }
- }
- }
-
- override fun toString(): String = "SimResourceSource[capacity=$capacity]"
-
- /**
- * Compute the duration that a resource consumption will take with the specified [speed].
- */
- private fun getDuration(work: Double, speed: Double): Long {
- return ceil(work / speed * 1000).toLong()
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceState.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceState.kt
deleted file mode 100644
index c72951d0..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceState.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * The state of a resource provider.
- */
-public enum class SimResourceState {
- /**
- * The resource provider is pending and the resource is waiting to be consumed.
- */
- Pending,
-
- /**
- * The resource provider is active and the resource is currently being consumed.
- */
- Active,
-
- /**
- * The resource provider is stopped and the resource cannot be consumed anymore.
- */
- Stopped
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt
deleted file mode 100644
index d2aab634..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.interference.InterferenceKey
-
-/**
- * A [SimResourceSwitch] enables switching of capacity of multiple resources between multiple consumers.
- */
-public interface SimResourceSwitch : AutoCloseable {
- /**
- * The output resource providers to which resource consumers can be attached.
- */
- public val outputs: Set<SimResourceCloseableProvider>
-
- /**
- * The input resources that will be switched between the output providers.
- */
- public val inputs: Set<SimResourceProvider>
-
- /**
- * The resource counters to track the execution metrics of all switch resources.
- */
- public val counters: SimResourceCounters
-
- /**
- * Create a new output on the switch.
- *
- * @param key The key of the interference member to which the output belongs.
- */
- public fun newOutput(key: InterferenceKey? = null): SimResourceCloseableProvider
-
- /**
- * Add the specified [input] to the switch.
- */
- public fun addInput(input: SimResourceProvider)
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt
deleted file mode 100644
index fbb541e5..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.interference.InterferenceKey
-import java.util.ArrayDeque
-
-/**
- * A [SimResourceSwitch] implementation that allocates outputs to the inputs of the switch exclusively. This means that
- * a single output is directly connected to an input and that the switch can only support as much outputs as inputs.
- */
-public class SimResourceSwitchExclusive : SimResourceSwitch {
- /**
- * A flag to indicate that the switch is closed.
- */
- private var isClosed: Boolean = false
-
- private val _outputs = mutableSetOf<Provider>()
- override val outputs: Set<SimResourceCloseableProvider>
- get() = _outputs
-
- private val availableResources = ArrayDeque<SimResourceTransformer>()
-
- private val _inputs = mutableSetOf<SimResourceProvider>()
- override val inputs: Set<SimResourceProvider>
- get() = _inputs
-
- override val counters: SimResourceCounters = object : SimResourceCounters {
- override val demand: Double
- get() = _inputs.sumOf { it.counters.demand }
- override val actual: Double
- get() = _inputs.sumOf { it.counters.actual }
- override val overcommit: Double
- get() = _inputs.sumOf { it.counters.overcommit }
-
- override fun reset() {
- for (input in _inputs) {
- input.counters.reset()
- }
- }
-
- override fun toString(): String = "SimResourceCounters[demand=$demand,actual=$actual,overcommit=$overcommit]"
- }
-
- /**
- * Add an output to the switch.
- */
- override fun newOutput(key: InterferenceKey?): SimResourceCloseableProvider {
- check(!isClosed) { "Switch has been closed" }
- check(availableResources.isNotEmpty()) { "No capacity to serve request" }
- val forwarder = availableResources.poll()
- val output = Provider(forwarder)
- _outputs += output
- return output
- }
-
- override fun addInput(input: SimResourceProvider) {
- check(!isClosed) { "Switch has been closed" }
-
- if (input in inputs) {
- return
- }
-
- val forwarder = SimResourceForwarder()
-
- _inputs += input
- availableResources += forwarder
-
- input.startConsumer(object : SimResourceConsumer by forwarder {
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- if (event == SimResourceEvent.Exit) {
- // De-register the input after it has finished
- _inputs -= input
- }
-
- forwarder.onEvent(ctx, event)
- }
- })
- }
-
- override fun close() {
- isClosed = true
-
- // Cancel all upstream subscriptions
- _inputs.forEach(SimResourceProvider::cancel)
- }
-
- private inner class Provider(private val forwarder: SimResourceTransformer) : SimResourceCloseableProvider, SimResourceProvider by forwarder {
- override fun close() {
- // We explicitly do not close the forwarder here in order to re-use it across output resources.
- _outputs -= this
- availableResources += forwarder
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt
deleted file mode 100644
index e368609f..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.interference.InterferenceDomain
-import org.opendc.simulator.resources.interference.InterferenceKey
-
-/**
- * A [SimResourceSwitch] implementation that switches resource consumptions over the available resources using max-min
- * fair sharing.
- *
- * @param interpreter The interpreter for managing the resource contexts.
- * @param parent The parent resource system of the switch.
- * @param interferenceDomain The interference domain of the switch.
- */
-public class SimResourceSwitchMaxMin(
- interpreter: SimResourceInterpreter,
- parent: SimResourceSystem? = null,
- interferenceDomain: InterferenceDomain? = null
-) : SimResourceSwitch {
- /**
- * The output resource providers to which resource consumers can be attached.
- */
- override val outputs: Set<SimResourceCloseableProvider>
- get() = distributor.outputs
-
- /**
- * The input resources that will be switched between the output providers.
- */
- override val inputs: Set<SimResourceProvider>
- get() = aggregator.inputs
-
- /**
- * The resource counters to track the execution metrics of all switch resources.
- */
- override val counters: SimResourceDistributorMaxMin.Counters
- get() = distributor.counters
-
- /**
- * A flag to indicate that the switch was closed.
- */
- private var isClosed = false
-
- /**
- * The aggregator to aggregate the resources.
- */
- private val aggregator = SimResourceAggregatorMaxMin(interpreter, parent)
-
- /**
- * The distributor to distribute the aggregated resources.
- */
- private val distributor = SimResourceDistributorMaxMin(interpreter, parent, interferenceDomain)
-
- init {
- aggregator.startConsumer(distributor)
- }
-
- /**
- * Add an output to the switch.
- */
- override fun newOutput(key: InterferenceKey?): SimResourceCloseableProvider {
- check(!isClosed) { "Switch has been closed" }
-
- return distributor.newOutput(key)
- }
-
- /**
- * Add the specified [input] to the switch.
- */
- override fun addInput(input: SimResourceProvider) {
- check(!isClosed) { "Switch has been closed" }
-
- aggregator.addInput(input)
- }
-
- override fun close() {
- if (!isClosed) {
- isClosed = true
- aggregator.cancel()
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSystem.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSystem.kt
deleted file mode 100644
index 609262cb..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSystem.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-/**
- * A system of possible multiple sub-resources.
- *
- * This interface is used to model hierarchies of resource providers, which can listen efficiently to changes of the
- * resource provider.
- */
-public interface SimResourceSystem {
- /**
- * The parent system to which this system belongs or `null` if it has no parent.
- */
- public val parent: SimResourceSystem?
-
- /**
- * This method is invoked when the system has converged to a steady-state.
- *
- * @param timestamp The timestamp at which the system converged.
- */
- public fun onConverge(timestamp: Long)
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt
deleted file mode 100644
index cec27e1c..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.opendc.simulator.resources.impl.SimResourceCountersImpl
-
-/**
- * A [SimResourceFlow] that transforms the resource commands emitted by the resource commands to the resource provider.
- *
- * @param isCoupled A flag to indicate that the transformer will exit when the resource consumer exits.
- * @param transform The function to transform the received resource command.
- */
-public class SimResourceTransformer(
- private val isCoupled: Boolean = false,
- private val transform: (SimResourceContext, SimResourceCommand) -> SimResourceCommand
-) : SimResourceFlow, AutoCloseable {
- /**
- * The [SimResourceContext] in which the forwarder runs.
- */
- private var ctx: SimResourceContext? = null
-
- /**
- * The delegate [SimResourceConsumer].
- */
- private var delegate: SimResourceConsumer? = null
-
- /**
- * A flag to indicate that the delegate was started.
- */
- private var hasDelegateStarted: Boolean = false
-
- override val isActive: Boolean
- get() = delegate != null
-
- override val capacity: Double
- get() = ctx?.capacity ?: 0.0
-
- override val speed: Double
- get() = ctx?.speed ?: 0.0
-
- override val demand: Double
- get() = ctx?.demand ?: 0.0
-
- override val counters: SimResourceCounters
- get() = _counters
- private val _counters = SimResourceCountersImpl()
-
- override fun startConsumer(consumer: SimResourceConsumer) {
- check(delegate == null) { "Resource transformer already active" }
-
- delegate = consumer
-
- // Interrupt the provider to replace the consumer
- interrupt()
- }
-
- override fun interrupt() {
- ctx?.interrupt()
- }
-
- override fun cancel() {
- val delegate = delegate
- val ctx = ctx
-
- if (delegate != null) {
- this.delegate = null
-
- if (ctx != null) {
- delegate.onEvent(ctx, SimResourceEvent.Exit)
- }
- }
- }
-
- override fun close() {
- val ctx = ctx
-
- if (ctx != null) {
- this.ctx = null
- ctx.interrupt()
- }
- }
-
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- val delegate = delegate
-
- if (!hasDelegateStarted) {
- start()
- }
-
- updateCounters(ctx)
-
- return if (delegate != null) {
- val command = transform(ctx, delegate.onNext(ctx))
-
- _work = if (command is SimResourceCommand.Consume) command.work else 0.0
-
- if (command == SimResourceCommand.Exit) {
- // Warning: resumption of the continuation might change the entire state of the forwarder. Make sure we
- // reset beforehand the existing state and check whether it has been updated afterwards
- reset()
-
- delegate.onEvent(ctx, SimResourceEvent.Exit)
-
- if (isCoupled)
- SimResourceCommand.Exit
- else
- onNext(ctx)
- } else {
- command
- }
- } else {
- SimResourceCommand.Idle()
- }
- }
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- when (event) {
- SimResourceEvent.Start -> {
- this.ctx = ctx
- }
- SimResourceEvent.Exit -> {
- this.ctx = null
-
- val delegate = delegate
- if (delegate != null) {
- reset()
- delegate.onEvent(ctx, SimResourceEvent.Exit)
- }
- }
- else -> delegate?.onEvent(ctx, event)
- }
- }
-
- override fun onFailure(ctx: SimResourceContext, cause: Throwable) {
- this.ctx = null
-
- val delegate = delegate
- if (delegate != null) {
- reset()
- delegate.onFailure(ctx, cause)
- }
- }
-
- /**
- * Start the delegate.
- */
- private fun start() {
- val delegate = delegate ?: return
- delegate.onEvent(checkNotNull(ctx), SimResourceEvent.Start)
-
- hasDelegateStarted = true
- }
-
- /**
- * Reset the delegate.
- */
- private fun reset() {
- delegate = null
- hasDelegateStarted = false
- }
-
- /**
- * Counter to track the current submitted work.
- */
- private var _work = 0.0
-
- /**
- * Update the resource counters for the transformer.
- */
- private fun updateCounters(ctx: SimResourceContext) {
- val counters = _counters
- val remainingWork = ctx.remainingWork
- counters.demand += _work
- counters.actual += _work - remainingWork
- counters.overcommit += remainingWork
- }
-}
-
-/**
- * Constructs a [SimResourceTransformer] that forwards the received resource command with an identity transform.
- *
- * @param isCoupled A flag to indicate that the transformer will exit when the resource consumer exits.
- */
-public fun SimResourceForwarder(isCoupled: Boolean = false): SimResourceTransformer {
- return SimResourceTransformer(isCoupled) { _, command -> command }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimConsumerBarrier.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimConsumerBarrier.kt
deleted file mode 100644
index 52a42241..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimConsumerBarrier.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.consumer
-
-/**
- * The [SimConsumerBarrier] is a barrier that allows consumers to wait for a select number of other consumers to
- * complete, before proceeding its operation.
- */
-public class SimConsumerBarrier(public val parties: Int) {
- private var counter = 0
-
- /**
- * Enter the barrier and determine whether the caller is the last to reach the barrier.
- *
- * @return `true` if the caller is the last to reach the barrier, `false` otherwise.
- */
- public fun enter(): Boolean {
- val last = ++counter == parties
- if (last) {
- counter = 0
- return true
- }
- return false
- }
-
- /**
- * Reset the barrier.
- */
- public fun reset() {
- counter = 0
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimSpeedConsumerAdapter.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimSpeedConsumerAdapter.kt
deleted file mode 100644
index 4f4ebb14..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimSpeedConsumerAdapter.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.consumer
-
-import org.opendc.simulator.resources.SimResourceCommand
-import org.opendc.simulator.resources.SimResourceConsumer
-import org.opendc.simulator.resources.SimResourceContext
-import org.opendc.simulator.resources.SimResourceEvent
-import kotlin.math.min
-
-/**
- * Helper class to expose an observable [speed] field describing the speed of the consumer.
- */
-public class SimSpeedConsumerAdapter(
- private val delegate: SimResourceConsumer,
- private val callback: (Double) -> Unit = {}
-) : SimResourceConsumer by delegate {
- /**
- * The resource processing speed at this instant.
- */
- public var speed: Double = 0.0
- private set(value) {
- if (field != value) {
- callback(value)
- field = value
- }
- }
-
- init {
- callback(0.0)
- }
-
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- return delegate.onNext(ctx)
- }
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- val oldSpeed = speed
-
- delegate.onEvent(ctx, event)
-
- when (event) {
- SimResourceEvent.Run -> speed = ctx.speed
- SimResourceEvent.Capacity -> {
- // Check if the consumer interrupted the consumer and updated the resource consumption. If not, we might
- // need to update the current speed.
- if (oldSpeed == speed) {
- speed = min(ctx.capacity, speed)
- }
- }
- SimResourceEvent.Exit -> speed = 0.0
- else -> {}
- }
- }
-
- override fun onFailure(ctx: SimResourceContext, cause: Throwable) {
- speed = 0.0
-
- delegate.onFailure(ctx, cause)
- }
-
- override fun toString(): String = "SimSpeedConsumerAdapter[delegate=$delegate]"
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimTraceConsumer.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimTraceConsumer.kt
deleted file mode 100644
index 2e94e1c1..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimTraceConsumer.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.consumer
-
-import org.opendc.simulator.resources.SimResourceCommand
-import org.opendc.simulator.resources.SimResourceConsumer
-import org.opendc.simulator.resources.SimResourceContext
-import org.opendc.simulator.resources.SimResourceEvent
-
-/**
- * A [SimResourceConsumer] that replays a workload trace consisting of multiple fragments, each indicating the resource
- * consumption for some period of time.
- */
-public class SimTraceConsumer(private val trace: Sequence<Fragment>) : SimResourceConsumer {
- private var iterator: Iterator<Fragment>? = null
-
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- val iterator = checkNotNull(iterator)
- return if (iterator.hasNext()) {
- val now = ctx.clock.millis()
- val fragment = iterator.next()
- val work = (fragment.duration / 1000) * fragment.usage
- val deadline = now + fragment.duration
-
- assert(deadline >= now) { "Deadline already passed" }
-
- if (work > 0.0)
- SimResourceCommand.Consume(work, fragment.usage, deadline)
- else
- SimResourceCommand.Idle(deadline)
- } else {
- SimResourceCommand.Exit
- }
- }
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- when (event) {
- SimResourceEvent.Start -> {
- check(iterator == null) { "Consumer already running" }
- iterator = trace.iterator()
- }
- SimResourceEvent.Exit -> {
- iterator = null
- }
- else -> {}
- }
- }
-
- /**
- * A fragment of the workload.
- */
- public data class Fragment(val duration: Long, val usage: Double)
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimWorkConsumer.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimWorkConsumer.kt
deleted file mode 100644
index faa693c4..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/consumer/SimWorkConsumer.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.consumer
-
-import org.opendc.simulator.resources.SimResourceCommand
-import org.opendc.simulator.resources.SimResourceConsumer
-import org.opendc.simulator.resources.SimResourceContext
-
-/**
- * A [SimResourceConsumer] that consumes the specified amount of work at the specified utilization.
- */
-public class SimWorkConsumer(
- private val work: Double,
- private val utilization: Double
-) : SimResourceConsumer {
-
- init {
- require(work >= 0.0) { "Work must be positive" }
- require(utilization > 0.0 && utilization <= 1.0) { "Utilization must be in (0, 1]" }
- }
-
- private var isFirst = true
-
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- val limit = ctx.capacity * utilization
- val work = if (isFirst) {
- isFirst = false
- work
- } else {
- ctx.remainingWork
- }
- return if (work > 0.0) {
- SimResourceCommand.Consume(work, limit)
- } else {
- SimResourceCommand.Exit
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt
deleted file mode 100644
index b79998a3..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.impl
-
-import org.opendc.simulator.resources.*
-import java.time.Clock
-import kotlin.math.max
-import kotlin.math.min
-
-/**
- * Implementation of a [SimResourceContext] managing the communication between resources and resource consumers.
- */
-internal class SimResourceContextImpl(
- override val parent: SimResourceSystem?,
- private val interpreter: SimResourceInterpreterImpl,
- private val consumer: SimResourceConsumer,
- private val logic: SimResourceProviderLogic
-) : SimResourceControllableContext, SimResourceSystem {
- /**
- * The clock of the context.
- */
- override val clock: Clock
- get() = _clock
- private val _clock = interpreter.clock
-
- /**
- * The capacity of the resource.
- */
- override var capacity: Double = 0.0
- set(value) {
- val oldValue = field
-
- // Only changes will be propagated
- if (value != oldValue) {
- field = value
- onCapacityChange()
- }
- }
-
- /**
- * The amount of work still remaining at this instant.
- */
- override val remainingWork: Double
- get() = getRemainingWork(_clock.millis())
-
- /**
- * A flag to indicate the state of the context.
- */
- override val state: SimResourceState
- get() = _state
- private var _state = SimResourceState.Pending
-
- /**
- * The current processing speed of the resource.
- */
- override val speed: Double
- get() = _speed
- private var _speed = 0.0
-
- /**
- * The current resource processing demand.
- */
- override val demand: Double
- get() = _limit
-
- /**
- * The current state of the resource context.
- */
- private var _timestamp: Long = Long.MIN_VALUE
- private var _work: Double = 0.0
- private var _limit: Double = 0.0
- private var _deadline: Long = Long.MAX_VALUE
-
- /**
- * The update flag indicating why the update was triggered.
- */
- private var _flag: Int = 0
-
- /**
- * The current pending update.
- */
- private var _pendingUpdate: SimResourceInterpreterImpl.Update? = null
-
- override fun start() {
- check(_state == SimResourceState.Pending) { "Consumer is already started" }
- interpreter.batch {
- consumer.onEvent(this, SimResourceEvent.Start)
- _state = SimResourceState.Active
- interrupt()
- }
- }
-
- override fun close() {
- if (_state != SimResourceState.Stopped) {
- interpreter.batch {
- _state = SimResourceState.Stopped
- doStop()
- }
- }
- }
-
- override fun interrupt() {
- if (_state == SimResourceState.Stopped) {
- return
- }
-
- _flag = _flag or FLAG_INTERRUPT
- scheduleUpdate()
- }
-
- override fun invalidate() {
- if (_state == SimResourceState.Stopped) {
- return
- }
-
- _flag = _flag or FLAG_INVALIDATE
- scheduleUpdate()
- }
-
- override fun flush() {
- if (_state == SimResourceState.Stopped) {
- return
- }
-
- interpreter.scheduleSync(this)
- }
-
- /**
- * Determine whether the state of the resource context should be updated.
- */
- fun requiresUpdate(timestamp: Long): Boolean {
- // Either the resource context is flagged or there is a pending update at this timestamp
- return _flag != 0 || _pendingUpdate?.timestamp == timestamp
- }
-
- /**
- * Update the state of the resource context.
- */
- fun doUpdate(timestamp: Long) {
- try {
- val oldState = _state
- val newState = doUpdate(timestamp, oldState)
-
- _state = newState
- _flag = 0
-
- when (newState) {
- SimResourceState.Pending ->
- if (oldState != SimResourceState.Pending) {
- throw IllegalStateException("Illegal transition to pending state")
- }
- SimResourceState.Stopped ->
- if (oldState != SimResourceState.Stopped) {
- doStop()
- }
- else -> {}
- }
- } catch (cause: Throwable) {
- doFail(cause)
- } finally {
- _remainingWorkFlush = Long.MIN_VALUE
- _timestamp = timestamp
- }
- }
-
- override fun onConverge(timestamp: Long) {
- if (_state == SimResourceState.Active) {
- consumer.onEvent(this, SimResourceEvent.Run)
- }
- }
-
- override fun toString(): String = "SimResourceContextImpl[capacity=$capacity]"
-
- /**
- * Update the state of the resource context.
- */
- private fun doUpdate(timestamp: Long, state: SimResourceState): SimResourceState {
- return when (state) {
- // Resource context is not active, so its state will not update
- SimResourceState.Pending, SimResourceState.Stopped -> state
- SimResourceState.Active -> {
- val isInterrupted = _flag and FLAG_INTERRUPT != 0
- val remainingWork = getRemainingWork(timestamp)
- val isConsume = _limit > 0.0
- val reachedDeadline = _deadline <= timestamp
-
- // Update the resource counters only if there is some progress
- if (timestamp > _timestamp) {
- logic.onUpdate(this, _work, reachedDeadline)
- }
-
- // We should only continue processing the next command if:
- // 1. The resource consumption was finished.
- // 2. The resource capacity cannot satisfy the demand.
- // 3. The resource consumer should be interrupted (e.g., someone called .interrupt())
- if ((isConsume && remainingWork == 0.0) || reachedDeadline || isInterrupted) {
- when (val command = consumer.onNext(this)) {
- is SimResourceCommand.Idle -> interpretIdle(timestamp, command.deadline)
- is SimResourceCommand.Consume -> interpretConsume(timestamp, command.work, command.limit, command.deadline)
- is SimResourceCommand.Exit -> interpretExit()
- }
- } else if (isConsume) {
- interpretConsume(timestamp, remainingWork, _limit, _deadline)
- } else {
- interpretIdle(timestamp, _deadline)
- }
- }
- }
- }
-
- /**
- * Stop the resource context.
- */
- private fun doStop() {
- try {
- consumer.onEvent(this, SimResourceEvent.Exit)
- logic.onFinish(this)
- } catch (cause: Throwable) {
- doFail(cause)
- }
- }
-
- /**
- * Fail the resource consumer.
- */
- private fun doFail(cause: Throwable) {
- try {
- consumer.onFailure(this, cause)
- } catch (e: Throwable) {
- e.addSuppressed(cause)
- e.printStackTrace()
- }
-
- logic.onFinish(this)
- }
-
- /**
- * Interpret the [SimResourceCommand.Consume] command.
- */
- private fun interpretConsume(now: Long, work: Double, limit: Double, deadline: Long): SimResourceState {
- require(deadline >= now) { "Deadline already passed" }
-
- _speed = min(capacity, limit)
- _work = work
- _limit = limit
- _deadline = deadline
-
- val timestamp = logic.onConsume(this, work, limit, deadline)
- scheduleUpdate(timestamp)
-
- return SimResourceState.Active
- }
-
- /**
- * Interpret the [SimResourceCommand.Idle] command.
- */
- private fun interpretIdle(now: Long, deadline: Long): SimResourceState {
- require(deadline >= now) { "Deadline already passed" }
-
- _speed = 0.0
- _work = 0.0
- _limit = 0.0
- _deadline = deadline
-
- val timestamp = logic.onIdle(this, deadline)
- scheduleUpdate(timestamp)
-
- return SimResourceState.Active
- }
-
- /**
- * Interpret the [SimResourceCommand.Exit] command.
- */
- private fun interpretExit(): SimResourceState {
- _speed = 0.0
- _work = 0.0
- _limit = 0.0
- _deadline = Long.MAX_VALUE
-
- return SimResourceState.Stopped
- }
-
- private var _remainingWork: Double = 0.0
- private var _remainingWorkFlush: Long = Long.MIN_VALUE
-
- /**
- * Obtain the remaining work at the given timestamp.
- */
- private fun getRemainingWork(now: Long): Double {
- return if (_remainingWorkFlush < now) {
- _remainingWorkFlush = now
- computeRemainingWork(now).also { _remainingWork = it }
- } else {
- _remainingWork
- }
- }
-
- /**
- * Compute the remaining work based on the current state.
- */
- private fun computeRemainingWork(now: Long): Double {
- return if (_work > 0.0)
- max(0.0, _work - logic.getConsumedWork(this, _work, speed, now - _timestamp))
- else 0.0
- }
-
- /**
- * Indicate that the capacity of the resource has changed.
- */
- private fun onCapacityChange() {
- // Do not inform the consumer if it has not been started yet
- if (state != SimResourceState.Active) {
- return
- }
-
- val isThrottled = speed > capacity
-
- interpreter.batch {
- // Inform the consumer of the capacity change. This might already trigger an interrupt.
- consumer.onEvent(this, SimResourceEvent.Capacity)
-
- // Optimization: only invalidate context if the new capacity cannot satisfy the active resource command.
- if (isThrottled) {
- invalidate()
- }
- }
- }
-
- /**
- * Schedule an update for this resource context.
- */
- private fun scheduleUpdate() {
- // Cancel the pending update
- val pendingUpdate = _pendingUpdate
- if (pendingUpdate != null) {
- _pendingUpdate = null
- pendingUpdate.cancel()
- }
-
- interpreter.scheduleImmediate(this)
- }
-
- /**
- * Schedule a delayed update for this resource context.
- */
- private fun scheduleUpdate(timestamp: Long) {
- val pendingUpdate = _pendingUpdate
- if (pendingUpdate != null) {
- if (pendingUpdate.timestamp == timestamp) {
- // Fast-path: A pending update for the same timestamp already exists
- return
- } else {
- // Cancel the old pending update
- _pendingUpdate = null
- pendingUpdate.cancel()
- }
- }
-
- if (timestamp != Long.MAX_VALUE) {
- _pendingUpdate = interpreter.scheduleDelayed(this, timestamp)
- }
- }
-
- /**
- * A flag to indicate that the context should be invalidated.
- */
- private val FLAG_INVALIDATE = 0b01
-
- /**
- * A flag to indicate that the context should be interrupted.
- */
- private val FLAG_INTERRUPT = 0b10
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceCountersImpl.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceCountersImpl.kt
deleted file mode 100644
index 827019c5..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceCountersImpl.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.impl
-
-import org.opendc.simulator.resources.SimResourceCounters
-
-/**
- * Mutable implementation of the [SimResourceCounters] interface.
- */
-internal class SimResourceCountersImpl : SimResourceCounters {
- override var demand: Double = 0.0
- override var actual: Double = 0.0
- override var overcommit: Double = 0.0
-
- override fun reset() {
- demand = 0.0
- actual = 0.0
- overcommit = 0.0
- }
-
- override fun toString(): String = "SimResourceCounters[demand=$demand,actual=$actual,overcommit=$overcommit]"
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt
deleted file mode 100644
index c3dcebd0..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.impl
-
-import kotlinx.coroutines.Delay
-import kotlinx.coroutines.DisposableHandle
-import kotlinx.coroutines.InternalCoroutinesApi
-import kotlinx.coroutines.Runnable
-import org.opendc.simulator.resources.*
-import java.time.Clock
-import java.util.*
-import kotlin.coroutines.ContinuationInterceptor
-import kotlin.coroutines.CoroutineContext
-
-/**
- * A [SimResourceInterpreter] queues all interrupts that occur during execution to be executed after.
- *
- * @param context The coroutine context to use.
- * @param clock The virtual simulation clock.
- */
-internal class SimResourceInterpreterImpl(private val context: CoroutineContext, override val clock: Clock) : SimResourceInterpreter {
- /**
- * The [Delay] instance that provides scheduled execution of [Runnable]s.
- */
- @OptIn(InternalCoroutinesApi::class)
- private val delay = requireNotNull(context[ContinuationInterceptor] as? Delay) { "Invalid CoroutineDispatcher: no delay implementation" }
-
- /**
- * The queue of resource updates that are scheduled for immediate execution.
- */
- private val queue = ArrayDeque<SimResourceContextImpl>()
-
- /**
- * A priority queue containing the resource updates to be scheduled in the future.
- */
- private val futureQueue = PriorityQueue<Update>(compareBy { it.timestamp })
-
- /**
- * The stack of interpreter invocations to occur in the future.
- */
- private val futureInvocations = ArrayDeque<Invocation>()
-
- /**
- * The systems that have been visited during the interpreter cycle.
- */
- private val visited = linkedSetOf<SimResourceSystem>()
-
- /**
- * The index in the batch stack.
- */
- private var batchIndex = 0
-
- /**
- * A flag to indicate that the interpreter is currently active.
- */
- private val isRunning: Boolean
- get() = batchIndex > 0
-
- /**
- * Enqueue the specified [ctx] to be updated immediately during the active interpreter cycle.
- *
- * This method should be used when the state of a resource context is invalidated/interrupted and needs to be
- * re-computed. In case no interpreter is currently active, the interpreter will be started.
- */
- fun scheduleImmediate(ctx: SimResourceContextImpl) {
- queue.add(ctx)
-
- // In-case the interpreter is already running in the call-stack, return immediately. The changes will be picked
- // up by the active interpreter.
- if (isRunning) {
- return
- }
-
- try {
- batchIndex++
- runInterpreter()
- } finally {
- batchIndex--
- }
- }
-
- /**
- * Update the specified [ctx] synchronously.
- */
- fun scheduleSync(ctx: SimResourceContextImpl) {
- ctx.doUpdate(clock.millis())
-
- if (visited.add(ctx)) {
- collectAncestors(ctx, visited)
- }
-
- // In-case the interpreter is already running in the call-stack, return immediately. The changes will be picked
- // up by the active interpreter.
- if (isRunning) {
- return
- }
-
- try {
- batchIndex++
- runInterpreter()
- } finally {
- batchIndex--
- }
- }
-
- /**
- * Schedule the interpreter to run at [timestamp] to update the resource contexts.
- *
- * This method will override earlier calls to this method for the same [ctx].
- *
- * @param ctx The resource context to which the event applies.
- * @param timestamp The timestamp when the interrupt should happen.
- */
- fun scheduleDelayed(ctx: SimResourceContextImpl, timestamp: Long): Update {
- val now = clock.millis()
- val futureQueue = futureQueue
-
- require(timestamp >= now) { "Timestamp must be in the future" }
-
- val update = allocUpdate(ctx, timestamp)
- futureQueue.add(update)
-
- // Optimization: Check if we need to push the interruption forward. Note that we check by timer reference.
- if (futureQueue.peek() === update) {
- trySchedule(futureQueue, futureInvocations)
- }
-
- return update
- }
-
- override fun newContext(
- consumer: SimResourceConsumer,
- provider: SimResourceProviderLogic,
- parent: SimResourceSystem?
- ): SimResourceControllableContext = SimResourceContextImpl(parent, this, consumer, provider)
-
- override fun pushBatch() {
- batchIndex++
- }
-
- override fun popBatch() {
- try {
- // Flush the work if the platform is not already running
- if (batchIndex == 1 && queue.isNotEmpty()) {
- runInterpreter()
- }
- } finally {
- batchIndex--
- }
- }
-
- /**
- * Interpret all actions that are scheduled for the current timestamp.
- */
- private fun runInterpreter() {
- val now = clock.millis()
- val queue = queue
- val futureQueue = futureQueue
- val futureInvocations = futureInvocations
- val visited = visited
-
- // Execute all scheduled updates at current timestamp
- while (true) {
- val update = futureQueue.peek() ?: break
-
- assert(update.timestamp >= now) { "Internal inconsistency: found update of the past" }
-
- if (update.timestamp > now && !update.isCancelled) {
- // Schedule a task for the next event to occur.
- trySchedule(futureQueue, futureInvocations)
- break
- }
-
- futureQueue.poll()
-
- val shouldExecute = !update.isCancelled && update.ctx.requiresUpdate(now)
- if (shouldExecute) {
- update.ctx.doUpdate(now)
-
- if (visited.add(update.ctx)) {
- collectAncestors(update.ctx, visited)
- }
- }
-
- updatePool.add(update)
- }
-
- // Repeat execution of all immediate updates until the system has converged to a steady-state
- // We have to take into account that the onConverge callback can also trigger new actions.
- do {
- // Execute all immediate updates
- while (true) {
- val ctx = queue.poll() ?: break
- val shouldExecute = ctx.requiresUpdate(now)
-
- if (shouldExecute) {
- ctx.doUpdate(now)
-
- if (visited.add(ctx)) {
- collectAncestors(ctx, visited)
- }
- }
- }
-
- for (system in visited) {
- system.onConverge(now)
- }
-
- visited.clear()
- } while (queue.isNotEmpty())
- }
-
- /**
- * Try to schedule the next interpreter event.
- */
- private fun trySchedule(queue: PriorityQueue<Update>, scheduled: ArrayDeque<Invocation>) {
- val nextTimer = queue.peek()
- val now = clock.millis()
-
- // Check whether we need to update our schedule:
- if (nextTimer == null) {
- // Case 1: all timers are cancelled
- for (invocation in scheduled) {
- invocation.cancel()
- }
- scheduled.clear()
- return
- }
-
- while (true) {
- val invocation = scheduled.peekFirst()
- if (invocation == null || invocation.timestamp > nextTimer.timestamp) {
- // Case 2: A new timer was registered ahead of the other timers.
- // Solution: Schedule a new scheduler invocation
- val nextTimestamp = nextTimer.timestamp
- @OptIn(InternalCoroutinesApi::class)
- val handle = delay.invokeOnTimeout(
- nextTimestamp - now,
- {
- try {
- batchIndex++
- runInterpreter()
- } finally {
- batchIndex--
- }
- },
- context
- )
- scheduled.addFirst(Invocation(nextTimestamp, handle))
- break
- } else if (invocation.timestamp < nextTimer.timestamp) {
- // Case 2: A timer was cancelled and the head of the timer queue is now later than excepted
- // Solution: Cancel the next scheduler invocation
- invocation.cancel()
- scheduled.pollFirst()
- } else {
- break
- }
- }
- }
-
- /**
- * Collect all the ancestors of the specified [system].
- */
- private tailrec fun collectAncestors(system: SimResourceSystem, systems: MutableSet<SimResourceSystem>) {
- val parent = system.parent
- if (parent != null) {
- systems.add(parent)
- collectAncestors(parent, systems)
- }
- }
-
- /**
- * The pool of existing updates.
- */
- private val updatePool = ArrayDeque<Update>()
-
- /**
- * Allocate an [Update] object.
- */
- private fun allocUpdate(ctx: SimResourceContextImpl, timestamp: Long): Update {
- val update = updatePool.poll()
- return if (update != null) {
- update.ctx = ctx
- update.timestamp = timestamp
- update.isCancelled = false
- update
- } else {
- Update(ctx, timestamp)
- }
- }
-
- /**
- * A future interpreter invocation.
- *
- * This class is used to keep track of the future scheduler invocations created using the [Delay] instance. In case
- * the invocation is not needed anymore, it can be cancelled via [cancel].
- */
- private data class Invocation(
- @JvmField val timestamp: Long,
- private val disposableHandle: DisposableHandle
- ) {
- /**
- * Cancel the interpreter invocation.
- */
- fun cancel() = disposableHandle.dispose()
- }
-
- /**
- * An update call for [ctx] that is scheduled for [timestamp].
- *
- * This class represents an update in the future at [timestamp] requested by [ctx]. A deferred update might be
- * cancelled if the resource context was invalidated in the meantime.
- */
- class Update(@JvmField var ctx: SimResourceContextImpl, @JvmField var timestamp: Long) {
- /**
- * A flag to indicate that the task has been cancelled.
- */
- @JvmField
- var isCancelled: Boolean = false
-
- /**
- * Cancel the update.
- */
- fun cancel() {
- isCancelled = true
- }
-
- override fun toString(): String = "Update[ctx=$ctx,timestamp=$timestamp]"
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceDomain.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceDomain.kt
deleted file mode 100644
index 1066777f..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceDomain.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.opendc.simulator.resources.interference
-
-import org.opendc.simulator.resources.SimResourceConsumer
-
-/**
- * An interference domain represents a system of resources where [resource consumers][SimResourceConsumer] may incur
- * performance variability due to operating on the same resources and therefore causing interference.
- */
-public interface InterferenceDomain {
- /**
- * Compute the performance score of a participant in this interference domain.
- *
- * @param key The participant to obtain the score of or `null` if the participant has no key.
- * @param load The overall load on the interference domain.
- * @return A score representing the performance score to be applied to the resource consumer, with 1
- * meaning no influence, <1 means that performance degrades, and >1 means that performance improves.
- */
- public fun apply(key: InterferenceKey?, load: Double): Double
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceKey.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceKey.kt
deleted file mode 100644
index 8b12e7b4..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/interference/InterferenceKey.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources.interference
-
-/**
- * A key that uniquely identifies a participant of an interference domain.
- */
-public interface InterferenceKey
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMinTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMinTest.kt
deleted file mode 100644
index 2f01a8c4..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMinTest.kt
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.verify
-import kotlinx.coroutines.*
-import org.junit.jupiter.api.Assertions.*
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertAll
-import org.junit.jupiter.api.assertThrows
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.consumer.SimSpeedConsumerAdapter
-import org.opendc.simulator.resources.consumer.SimWorkConsumer
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-
-/**
- * Test suite for the [SimResourceAggregatorMaxMin] class.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class SimResourceAggregatorMaxMinTest {
- @Test
- fun testSingleCapacity() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val aggregator = SimResourceAggregatorMaxMin(scheduler)
- val forwarder = SimResourceForwarder()
- val sources = listOf(
- forwarder,
- SimResourceSource(1.0, scheduler)
- )
- sources.forEach(aggregator::addInput)
-
- val consumer = SimWorkConsumer(1.0, 0.5)
- val usage = mutableListOf<Double>()
- val source = SimResourceSource(1.0, scheduler)
- val adapter = SimSpeedConsumerAdapter(forwarder, usage::add)
- source.startConsumer(adapter)
-
- aggregator.consume(consumer)
- yield()
-
- assertAll(
- { assertEquals(1000, clock.millis()) },
- { assertEquals(listOf(0.0, 0.5, 0.0), usage) }
- )
- }
-
- @Test
- fun testDoubleCapacity() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val aggregator = SimResourceAggregatorMaxMin(scheduler)
- val sources = listOf(
- SimResourceSource(1.0, scheduler),
- SimResourceSource(1.0, scheduler)
- )
- sources.forEach(aggregator::addInput)
-
- val consumer = SimWorkConsumer(2.0, 1.0)
- val usage = mutableListOf<Double>()
- val adapter = SimSpeedConsumerAdapter(consumer, usage::add)
-
- aggregator.consume(adapter)
- yield()
- assertAll(
- { assertEquals(1000, clock.millis()) },
- { assertEquals(listOf(0.0, 2.0, 0.0), usage) }
- )
- }
-
- @Test
- fun testOvercommit() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val aggregator = SimResourceAggregatorMaxMin(scheduler)
- val sources = listOf(
- SimResourceSource(1.0, scheduler),
- SimResourceSource(1.0, scheduler)
- )
- sources.forEach(aggregator::addInput)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(4.0, 4.0, 1000))
- .andThen(SimResourceCommand.Exit)
-
- aggregator.consume(consumer)
- yield()
- assertEquals(1000, clock.millis())
-
- verify(exactly = 2) { consumer.onNext(any()) }
- }
-
- @Test
- fun testException() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val aggregator = SimResourceAggregatorMaxMin(scheduler)
- val sources = listOf(
- SimResourceSource(1.0, scheduler),
- SimResourceSource(1.0, scheduler)
- )
- sources.forEach(aggregator::addInput)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(1.0, 1.0))
- .andThenThrows(IllegalStateException("Test Exception"))
-
- assertThrows<IllegalStateException> { aggregator.consume(consumer) }
- yield()
- assertFalse(sources[0].isActive)
- }
-
- @Test
- fun testAdjustCapacity() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val aggregator = SimResourceAggregatorMaxMin(scheduler)
- val sources = listOf(
- SimResourceSource(1.0, scheduler),
- SimResourceSource(1.0, scheduler)
- )
- sources.forEach(aggregator::addInput)
-
- val consumer = SimWorkConsumer(4.0, 1.0)
- coroutineScope {
- launch { aggregator.consume(consumer) }
- delay(1000)
- sources[0].capacity = 0.5
- }
- yield()
- assertEquals(2334, clock.millis())
- }
-
- @Test
- fun testFailOverCapacity() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val aggregator = SimResourceAggregatorMaxMin(scheduler)
- val sources = listOf(
- SimResourceSource(1.0, scheduler),
- SimResourceSource(1.0, scheduler)
- )
- sources.forEach(aggregator::addInput)
-
- val consumer = SimWorkConsumer(1.0, 0.5)
- coroutineScope {
- launch { aggregator.consume(consumer) }
- delay(500)
- sources[0].capacity = 0.5
- }
- yield()
- assertEquals(1000, clock.millis())
- }
-
- @Test
- fun testCounters() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val aggregator = SimResourceAggregatorMaxMin(scheduler)
- val sources = listOf(
- SimResourceSource(1.0, scheduler),
- SimResourceSource(1.0, scheduler)
- )
- sources.forEach(aggregator::addInput)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(4.0, 4.0, 1000))
- .andThen(SimResourceCommand.Exit)
-
- aggregator.consume(consumer)
- yield()
- assertEquals(1000, clock.millis())
- assertEquals(2.0, aggregator.counters.actual) { "Actual work mismatch" }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceCommandTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceCommandTest.kt
deleted file mode 100644
index 02d456ff..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceCommandTest.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertDoesNotThrow
-import org.junit.jupiter.api.assertThrows
-
-/**
- * Test suite for [SimResourceCommand].
- */
-class SimResourceCommandTest {
- @Test
- fun testZeroWork() {
- assertThrows<IllegalArgumentException> {
- SimResourceCommand.Consume(0.0, 1.0)
- }
- }
-
- @Test
- fun testNegativeWork() {
- assertThrows<IllegalArgumentException> {
- SimResourceCommand.Consume(-1.0, 1.0)
- }
- }
-
- @Test
- fun testZeroLimit() {
- assertThrows<IllegalArgumentException> {
- SimResourceCommand.Consume(1.0, 0.0)
- }
- }
-
- @Test
- fun testNegativeLimit() {
- assertThrows<IllegalArgumentException> {
- SimResourceCommand.Consume(1.0, -1.0, 1)
- }
- }
-
- @Test
- fun testConsumeCorrect() {
- assertDoesNotThrow {
- SimResourceCommand.Consume(1.0, 1.0)
- }
- }
-
- @Test
- fun testIdleCorrect() {
- assertDoesNotThrow {
- SimResourceCommand.Idle(1)
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceContextTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceContextTest.kt
deleted file mode 100644
index 6cb507ce..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceContextTest.kt
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import io.mockk.*
-import kotlinx.coroutines.*
-import org.junit.jupiter.api.*
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.impl.SimResourceContextImpl
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-
-/**
- * A test suite for the [SimResourceContextImpl] class.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-class SimResourceContextTest {
- @Test
- fun testFlushWithoutCommand() = runBlockingSimulation {
- val interpreter = SimResourceInterpreterImpl(coroutineContext, clock)
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Consume(10.0, 1.0) andThen SimResourceCommand.Exit
-
- val logic = object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long = deadline
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long = deadline
- override fun onFinish(ctx: SimResourceControllableContext) {}
- }
- val context = SimResourceContextImpl(null, interpreter, consumer, logic)
-
- context.doUpdate(interpreter.clock.millis())
- }
-
- @Test
- fun testIntermediateFlush() = runBlockingSimulation {
- val interpreter = SimResourceInterpreterImpl(coroutineContext, clock)
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Consume(10.0, 1.0) andThen SimResourceCommand.Exit
-
- val logic = spyk(object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long = deadline
- override fun onFinish(ctx: SimResourceControllableContext) {}
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long = deadline
- })
- val context = spyk(SimResourceContextImpl(null, interpreter, consumer, logic))
-
- context.start()
- delay(1) // Delay 1 ms to prevent hitting the fast path
- context.doUpdate(interpreter.clock.millis())
-
- verify(exactly = 2) { logic.onConsume(any(), any(), any(), any()) }
- }
-
- @Test
- fun testIntermediateFlushIdle() = runBlockingSimulation {
- val interpreter = SimResourceInterpreterImpl(coroutineContext, clock)
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Idle(10) andThen SimResourceCommand.Exit
-
- val logic = spyk(object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long = deadline
- override fun onFinish(ctx: SimResourceControllableContext) {}
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long = deadline
- })
- val context = spyk(SimResourceContextImpl(null, interpreter, consumer, logic))
-
- context.start()
- delay(5)
- context.invalidate()
- delay(5)
- context.invalidate()
-
- assertAll(
- { verify(exactly = 2) { logic.onIdle(any(), any()) } },
- { verify(exactly = 1) { logic.onFinish(any()) } }
- )
- }
-
- @Test
- fun testDoubleStart() = runBlockingSimulation {
- val interpreter = SimResourceInterpreterImpl(coroutineContext, clock)
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Idle(10) andThen SimResourceCommand.Exit
-
- val logic = object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long = deadline
- override fun onFinish(ctx: SimResourceControllableContext) {}
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long = deadline
- }
- val context = SimResourceContextImpl(null, interpreter, consumer, logic)
-
- context.start()
-
- assertThrows<IllegalStateException> {
- context.start()
- }
- }
-
- @Test
- fun testIdempodentCapacityChange() = runBlockingSimulation {
- val interpreter = SimResourceInterpreterImpl(coroutineContext, clock)
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Consume(10.0, 1.0) andThen SimResourceCommand.Exit
-
- val logic = object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long = deadline
- override fun onFinish(ctx: SimResourceControllableContext) {}
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long = deadline
- }
-
- val context = SimResourceContextImpl(null, interpreter, consumer, logic)
- context.capacity = 4200.0
- context.start()
- context.capacity = 4200.0
-
- verify(exactly = 0) { consumer.onEvent(any(), SimResourceEvent.Capacity) }
- }
-
- @Test
- fun testFailureNoInfiniteLoop() = runBlockingSimulation {
- val interpreter = SimResourceInterpreterImpl(coroutineContext, clock)
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Exit
- every { consumer.onEvent(any(), SimResourceEvent.Exit) } throws IllegalStateException("onEvent")
- every { consumer.onFailure(any(), any()) } throws IllegalStateException("onFailure")
-
- val logic = spyk(object : SimResourceProviderLogic {
- override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long = deadline
- override fun onFinish(ctx: SimResourceControllableContext) {}
- override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long = deadline
- })
-
- val context = SimResourceContextImpl(null, interpreter, consumer, logic)
-
- context.start()
-
- delay(1)
-
- verify(exactly = 1) { consumer.onFailure(any(), any()) }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSourceTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSourceTest.kt
deleted file mode 100644
index 4895544d..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSourceTest.kt
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.spyk
-import io.mockk.verify
-import kotlinx.coroutines.*
-import org.junit.jupiter.api.*
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.consumer.SimSpeedConsumerAdapter
-import org.opendc.simulator.resources.consumer.SimWorkConsumer
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-
-/**
- * A test suite for the [SimResourceSource] class.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-class SimResourceSourceTest {
- @Test
- fun testSpeed() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(1000 * capacity, capacity))
- .andThen(SimResourceCommand.Exit)
-
- val res = mutableListOf<Double>()
- val adapter = SimSpeedConsumerAdapter(consumer, res::add)
-
- provider.consume(adapter)
-
- assertEquals(listOf(0.0, capacity, 0.0), res) { "Speed is reported correctly" }
- }
-
- @Test
- fun testAdjustCapacity() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val provider = SimResourceSource(1.0, scheduler)
-
- val consumer = spyk(SimWorkConsumer(2.0, 1.0))
-
- coroutineScope {
- launch { provider.consume(consumer) }
- delay(1000)
- provider.capacity = 0.5
- }
- assertEquals(3000, clock.millis())
- verify(exactly = 1) { consumer.onEvent(any(), SimResourceEvent.Capacity) }
- }
-
- @Test
- fun testSpeedLimit() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(1000 * capacity, 2 * capacity))
- .andThen(SimResourceCommand.Exit)
-
- val res = mutableListOf<Double>()
- val adapter = SimSpeedConsumerAdapter(consumer, res::add)
-
- provider.consume(adapter)
-
- assertEquals(listOf(0.0, capacity, 0.0), res) { "Speed is reported correctly" }
- }
-
- /**
- * Test to see whether no infinite recursion occurs when interrupting during [SimResourceConsumer.onStart] or
- * [SimResourceConsumer.onNext].
- */
- @Test
- fun testIntermediateInterrupt() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = object : SimResourceConsumer {
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- return SimResourceCommand.Exit
- }
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- ctx.interrupt()
- }
- }
-
- provider.consume(consumer)
- }
-
- @Test
- fun testInterrupt() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
- lateinit var resCtx: SimResourceContext
-
- val consumer = object : SimResourceConsumer {
- var isFirst = true
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- when (event) {
- SimResourceEvent.Start -> resCtx = ctx
- else -> {}
- }
- }
-
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- assertEquals(0.0, ctx.remainingWork)
- return if (isFirst) {
- isFirst = false
- SimResourceCommand.Consume(4.0, 1.0)
- } else {
- SimResourceCommand.Exit
- }
- }
- }
-
- launch {
- yield()
- resCtx.interrupt()
- }
- provider.consume(consumer)
-
- assertEquals(0, clock.millis())
- }
-
- @Test
- fun testFailure() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onEvent(any(), eq(SimResourceEvent.Start)) }
- .throws(IllegalStateException())
-
- assertThrows<IllegalStateException> {
- provider.consume(consumer)
- }
- }
-
- @Test
- fun testExceptionPropagationOnNext() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(1.0, 1.0))
- .andThenThrows(IllegalStateException())
-
- assertThrows<IllegalStateException> {
- provider.consume(consumer)
- }
- }
-
- @Test
- fun testConcurrentConsumption() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(1.0, 1.0))
- .andThenThrows(IllegalStateException())
-
- assertThrows<IllegalStateException> {
- coroutineScope {
- launch { provider.consume(consumer) }
- provider.consume(consumer)
- }
- }
- }
-
- @Test
- fun testCancelDuringConsumption() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Consume(1.0, 1.0))
- .andThenThrows(IllegalStateException())
-
- launch { provider.consume(consumer) }
- delay(500)
- provider.cancel()
-
- assertEquals(500, clock.millis())
- }
-
- @Test
- fun testIdle() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Idle(clock.millis() + 500))
- .andThen(SimResourceCommand.Exit)
-
- provider.consume(consumer)
-
- assertEquals(500, clock.millis())
- }
-
- @Test
- fun testInfiniteSleep() {
- assertThrows<IllegalStateException> {
- runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Idle())
- .andThenThrows(IllegalStateException())
-
- provider.consume(consumer)
- }
- }
- }
-
- @Test
- fun testIncorrectDeadline() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val capacity = 4200.0
- val provider = SimResourceSource(capacity, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) }
- .returns(SimResourceCommand.Idle(2))
- .andThen(SimResourceCommand.Exit)
-
- delay(10)
-
- assertThrows<IllegalArgumentException> { provider.consume(consumer) }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusiveTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusiveTest.kt
deleted file mode 100644
index ad8d82e3..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusiveTest.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import io.mockk.every
-import io.mockk.mockk
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.yield
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertAll
-import org.junit.jupiter.api.assertThrows
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.consumer.SimSpeedConsumerAdapter
-import org.opendc.simulator.resources.consumer.SimTraceConsumer
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-
-/**
- * Test suite for the [SimResourceSwitchExclusive] class.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class SimResourceSwitchExclusiveTest {
- /**
- * Test a trace workload.
- */
- @Test
- fun testTrace() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val speed = mutableListOf<Double>()
-
- val duration = 5 * 60L
- val workload =
- SimTraceConsumer(
- sequenceOf(
- SimTraceConsumer.Fragment(duration * 1000, 28.0),
- SimTraceConsumer.Fragment(duration * 1000, 3500.0),
- SimTraceConsumer.Fragment(duration * 1000, 0.0),
- SimTraceConsumer.Fragment(duration * 1000, 183.0)
- ),
- )
-
- val switch = SimResourceSwitchExclusive()
- val source = SimResourceSource(3200.0, scheduler)
- val forwarder = SimResourceForwarder()
- val adapter = SimSpeedConsumerAdapter(forwarder, speed::add)
- source.startConsumer(adapter)
- switch.addInput(forwarder)
-
- val provider = switch.newOutput()
-
- try {
- provider.consume(workload)
- yield()
- } finally {
- provider.close()
- }
-
- assertAll(
- { assertEquals(listOf(0.0, 28.0, 3200.0, 0.0, 183.0, 0.0), speed) { "Correct speed" } },
- { assertEquals(5 * 60L * 4000, clock.millis()) { "Took enough time" } }
- )
- }
-
- /**
- * Test runtime workload on hypervisor.
- */
- @Test
- fun testRuntimeWorkload() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val duration = 5 * 60L * 1000
- val workload = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { workload.onNext(any()) } returns SimResourceCommand.Consume(duration / 1000.0, 1.0) andThen SimResourceCommand.Exit
-
- val switch = SimResourceSwitchExclusive()
- val source = SimResourceSource(3200.0, scheduler)
-
- switch.addInput(source)
-
- val provider = switch.newOutput()
-
- try {
- provider.consume(workload)
- yield()
- } finally {
- provider.close()
- }
- assertEquals(duration, clock.millis()) { "Took enough time" }
- }
-
- /**
- * Test two workloads running sequentially.
- */
- @Test
- fun testTwoWorkloads() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val duration = 5 * 60L * 1000
- val workload = object : SimResourceConsumer {
- var isFirst = true
-
- override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) {
- when (event) {
- SimResourceEvent.Start -> isFirst = true
- else -> {}
- }
- }
-
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- return if (isFirst) {
- isFirst = false
- SimResourceCommand.Consume(duration / 1000.0, 1.0)
- } else {
- SimResourceCommand.Exit
- }
- }
- }
-
- val switch = SimResourceSwitchExclusive()
- val source = SimResourceSource(3200.0, scheduler)
-
- switch.addInput(source)
-
- val provider = switch.newOutput()
-
- try {
- provider.consume(workload)
- yield()
- provider.consume(workload)
- } finally {
- provider.close()
- }
- assertEquals(duration * 2, clock.millis()) { "Took enough time" }
- }
-
- /**
- * Test concurrent workloads on the machine.
- */
- @Test
- fun testConcurrentWorkloadFails() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val duration = 5 * 60L * 1000
- val workload = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { workload.onNext(any()) } returns SimResourceCommand.Consume(duration / 1000.0, 1.0) andThen SimResourceCommand.Exit
-
- val switch = SimResourceSwitchExclusive()
- val source = SimResourceSource(3200.0, scheduler)
-
- switch.addInput(source)
-
- switch.newOutput()
- assertThrows<IllegalStateException> { switch.newOutput() }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMinTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMinTest.kt
deleted file mode 100644
index e4292ec0..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMinTest.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import io.mockk.every
-import io.mockk.mockk
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.yield
-import org.junit.jupiter.api.*
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.consumer.SimTraceConsumer
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-
-/**
- * Test suite for the [SimResourceSwitch] implementations
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class SimResourceSwitchMaxMinTest {
- @Test
- fun testSmoke() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val switch = SimResourceSwitchMaxMin(scheduler)
-
- val sources = List(2) { SimResourceSource(2000.0, scheduler) }
- sources.forEach { switch.addInput(it) }
-
- val provider = switch.newOutput()
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Consume(1.0, 1.0) andThen SimResourceCommand.Exit
-
- try {
- provider.consume(consumer)
- yield()
- } finally {
- switch.close()
- }
- }
-
- /**
- * Test overcommitting of resources via the hypervisor with a single VM.
- */
- @Test
- fun testOvercommittedSingle() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val duration = 5 * 60L
- val workload =
- SimTraceConsumer(
- sequenceOf(
- SimTraceConsumer.Fragment(duration * 1000, 28.0),
- SimTraceConsumer.Fragment(duration * 1000, 3500.0),
- SimTraceConsumer.Fragment(duration * 1000, 0.0),
- SimTraceConsumer.Fragment(duration * 1000, 183.0)
- ),
- )
-
- val switch = SimResourceSwitchMaxMin(scheduler)
- val provider = switch.newOutput()
-
- try {
- switch.addInput(SimResourceSource(3200.0, scheduler))
- provider.consume(workload)
- yield()
- } finally {
- switch.close()
- }
-
- assertAll(
- { assertEquals(1113300.0, switch.counters.demand, "Requested work does not match") },
- { assertEquals(1023300.0, switch.counters.actual, "Actual work does not match") },
- { assertEquals(90000.0, switch.counters.overcommit, "Overcommitted work does not match") },
- { assertEquals(1200000, clock.millis()) }
- )
- }
-
- /**
- * Test overcommitting of resources via the hypervisor with two VMs.
- */
- @Test
- fun testOvercommittedDual() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
-
- val duration = 5 * 60L
- val workloadA =
- SimTraceConsumer(
- sequenceOf(
- SimTraceConsumer.Fragment(duration * 1000, 28.0),
- SimTraceConsumer.Fragment(duration * 1000, 3500.0),
- SimTraceConsumer.Fragment(duration * 1000, 0.0),
- SimTraceConsumer.Fragment(duration * 1000, 183.0)
- ),
- )
- val workloadB =
- SimTraceConsumer(
- sequenceOf(
- SimTraceConsumer.Fragment(duration * 1000, 28.0),
- SimTraceConsumer.Fragment(duration * 1000, 3100.0),
- SimTraceConsumer.Fragment(duration * 1000, 0.0),
- SimTraceConsumer.Fragment(duration * 1000, 73.0)
- )
- )
-
- val switch = SimResourceSwitchMaxMin(scheduler)
- val providerA = switch.newOutput()
- val providerB = switch.newOutput()
-
- try {
- switch.addInput(SimResourceSource(3200.0, scheduler))
-
- coroutineScope {
- launch { providerA.consume(workloadA) }
- providerB.consume(workloadB)
- }
-
- yield()
- } finally {
- switch.close()
- }
- assertAll(
- { assertEquals(2073600.0, switch.counters.demand, "Requested work does not match") },
- { assertEquals(1053600.0, switch.counters.actual, "Granted work does not match") },
- { assertEquals(1020000.0, switch.counters.overcommit, "Overcommitted work does not match") },
- { assertEquals(1200000, clock.millis()) }
- )
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceTransformerTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceTransformerTest.kt
deleted file mode 100644
index cf69b7b5..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimResourceTransformerTest.kt
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.spyk
-import io.mockk.verify
-import kotlinx.coroutines.*
-import org.junit.jupiter.api.Assertions.*
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.consumer.SimWorkConsumer
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-
-/**
- * A test suite for the [SimResourceTransformer] class.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class SimResourceTransformerTest {
- @Test
- fun testCancelImmediately() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(2000.0, scheduler)
-
- launch { source.consume(forwarder) }
-
- forwarder.consume(object : SimResourceConsumer {
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- return SimResourceCommand.Exit
- }
- })
-
- forwarder.close()
- source.cancel()
- }
-
- @Test
- fun testCancel() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(2000.0, scheduler)
-
- launch { source.consume(forwarder) }
-
- forwarder.consume(object : SimResourceConsumer {
- var isFirst = true
-
- override fun onNext(ctx: SimResourceContext): SimResourceCommand {
- return if (isFirst) {
- isFirst = false
- SimResourceCommand.Consume(10.0, 1.0)
- } else {
- SimResourceCommand.Exit
- }
- }
- })
-
- forwarder.close()
- source.cancel()
- }
-
- @Test
- fun testState() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
- val consumer = object : SimResourceConsumer {
- override fun onNext(ctx: SimResourceContext): SimResourceCommand = SimResourceCommand.Exit
- }
-
- assertFalse(forwarder.isActive)
-
- forwarder.startConsumer(consumer)
- assertTrue(forwarder.isActive)
-
- assertThrows<IllegalStateException> { forwarder.startConsumer(consumer) }
-
- forwarder.cancel()
- assertFalse(forwarder.isActive)
-
- forwarder.close()
- assertFalse(forwarder.isActive)
- }
-
- @Test
- fun testCancelPendingDelegate() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Exit
-
- forwarder.startConsumer(consumer)
- forwarder.cancel()
-
- verify(exactly = 0) { consumer.onEvent(any(), SimResourceEvent.Exit) }
- }
-
- @Test
- fun testCancelStartedDelegate() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(2000.0, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Idle(10)
-
- source.startConsumer(forwarder)
- yield()
- forwarder.startConsumer(consumer)
- yield()
- forwarder.cancel()
-
- verify(exactly = 1) { consumer.onEvent(any(), SimResourceEvent.Start) }
- verify(exactly = 1) { consumer.onEvent(any(), SimResourceEvent.Exit) }
- }
-
- @Test
- fun testCancelPropagation() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(2000.0, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Idle(10)
-
- source.startConsumer(forwarder)
- yield()
- forwarder.startConsumer(consumer)
- yield()
- source.cancel()
-
- verify(exactly = 1) { consumer.onEvent(any(), SimResourceEvent.Start) }
- verify(exactly = 1) { consumer.onEvent(any(), SimResourceEvent.Exit) }
- }
-
- @Test
- fun testExitPropagation() = runBlockingSimulation {
- val forwarder = SimResourceForwarder(isCoupled = true)
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(2000.0, scheduler)
-
- val consumer = mockk<SimResourceConsumer>(relaxUnitFun = true)
- every { consumer.onNext(any()) } returns SimResourceCommand.Exit
-
- source.startConsumer(forwarder)
- forwarder.consume(consumer)
- yield()
-
- assertFalse(forwarder.isActive)
- }
-
- @Test
- fun testAdjustCapacity() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(1.0, scheduler)
-
- val consumer = spyk(SimWorkConsumer(2.0, 1.0))
- source.startConsumer(forwarder)
-
- coroutineScope {
- launch { forwarder.consume(consumer) }
- delay(1000)
- source.capacity = 0.5
- }
-
- assertEquals(3000, clock.millis())
- verify(exactly = 1) { consumer.onEvent(any(), SimResourceEvent.Capacity) }
- }
-
- @Test
- fun testTransformExit() = runBlockingSimulation {
- val forwarder = SimResourceTransformer { _, _ -> SimResourceCommand.Exit }
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(1.0, scheduler)
-
- val consumer = spyk(SimWorkConsumer(2.0, 1.0))
- source.startConsumer(forwarder)
- forwarder.consume(consumer)
-
- assertEquals(0, clock.millis())
- verify(exactly = 1) { consumer.onNext(any()) }
- }
-
- @Test
- fun testCounters() = runBlockingSimulation {
- val forwarder = SimResourceForwarder()
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val source = SimResourceSource(1.0, scheduler)
-
- val consumer = SimWorkConsumer(2.0, 1.0)
- source.startConsumer(forwarder)
-
- forwarder.consume(consumer)
-
- assertEquals(source.counters.actual, forwarder.counters.actual) { "Actual work" }
- assertEquals(source.counters.demand, forwarder.counters.demand) { "Work demand" }
- assertEquals(source.counters.overcommit, forwarder.counters.overcommit) { "Overcommitted work" }
- assertEquals(2000, clock.millis())
- }
-}
diff --git a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimWorkConsumerTest.kt b/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimWorkConsumerTest.kt
deleted file mode 100644
index 42648cf1..00000000
--- a/opendc-simulator/opendc-simulator-resources/src/test/kotlin/org/opendc/simulator/resources/SimWorkConsumerTest.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2021 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.resources
-
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import org.opendc.simulator.core.runBlockingSimulation
-import org.opendc.simulator.resources.consumer.SimWorkConsumer
-import org.opendc.simulator.resources.impl.SimResourceInterpreterImpl
-
-/**
- * A test suite for the [SimWorkConsumer] class.
- */
-@OptIn(ExperimentalCoroutinesApi::class)
-internal class SimWorkConsumerTest {
- @Test
- fun testSmoke() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val provider = SimResourceSource(1.0, scheduler)
-
- val consumer = SimWorkConsumer(1.0, 1.0)
-
- provider.consume(consumer)
- assertEquals(1000, clock.millis())
- }
-
- @Test
- fun testUtilization() = runBlockingSimulation {
- val scheduler = SimResourceInterpreterImpl(coroutineContext, clock)
- val provider = SimResourceSource(1.0, scheduler)
-
- val consumer = SimWorkConsumer(1.0, 0.5)
-
- provider.consume(consumer)
- assertEquals(2000, clock.millis())
- }
-}