From 8666a78b86a40c1d8dab28dd18e841318c01f97f Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Tue, 24 Oct 2017 17:00:44 +0200 Subject: bug(#3): Add timeout for experiments This change adds a timeout for experiments, which allows the user to set an upper bound on the duration of an experiment. Closes #3 --- .../kotlin/nl/atlarge/opendc/platform/Experiment.kt | 11 +++++++++++ .../nl/atlarge/opendc/platform/JpaExperiment.kt | 20 ++++++++++++++++++-- .../nl/atlarge/opendc/platform/JpaPlatformRunner.kt | 3 ++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt index 225b2813..6aed5364 100644 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt +++ b/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt @@ -25,6 +25,7 @@ package nl.atlarge.opendc.platform import nl.atlarge.opendc.kernel.Kernel +import nl.atlarge.opendc.kernel.time.Duration /** * A blueprint for a reproducible simulation in a pre-defined setting. @@ -36,6 +37,16 @@ interface Experiment { * Run the experiment on the specified simulation [Kernel]. * * @param kernel The simulation kernel to run the experiment. + * @return The result of the experiment. */ fun run(kernel: Kernel): T + + /** + * Run the experiment on the specified simulation [Kernel]. + * + * @param kernel The simulation kernel to run the experiment. + * @param timeout The maximum duration of the experiment before returning to the caller. + * @return The result of the experiment or `null`. + */ + fun run(kernel: Kernel, timeout: Duration): T? } diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperiment.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperiment.kt index 59b28d0b..9e0e0565 100644 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperiment.kt +++ b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperiment.kt @@ -33,6 +33,7 @@ import nl.atlarge.opendc.integration.jpa.schema.TaskState as InternalTaskState import nl.atlarge.opendc.integration.jpa.schema.Experiment as InternalExperiment import nl.atlarge.opendc.integration.jpa.schema.Task as InternalTask import nl.atlarge.opendc.kernel.Kernel +import nl.atlarge.opendc.kernel.time.Duration import nl.atlarge.opendc.platform.workload.TaskState import nl.atlarge.opendc.topology.JpaTopologyFactory import nl.atlarge.opendc.topology.container.Rack @@ -60,9 +61,10 @@ class JpaExperiment(private val manager: EntityManager, * Run the experiment on the specified simulation [Kernel]. * * @param kernel The simulation kernel to run the experiment. - * @throws IllegalStateException if the simulation is already running or finished. + * @param timeout The maximum duration of the experiment before returning to the caller. + * @return The result of the experiment or `null`. */ - override fun run(kernel: Kernel) { + override fun run(kernel: Kernel, timeout: Duration): Unit? { if (experiment.state != ExperimentState.CLAIMED) { throw IllegalStateException("The experiment is in illegal state ${experiment.state}") } @@ -103,6 +105,10 @@ class JpaExperiment(private val manager: EntityManager, logger.info { "Starting simulation" } while (trace.jobs.any { !it.finished }) { + // If we have reached a timeout, return + if (simulation.clock.now >= timeout) + return null + // Collect data of simulation cycle manager.transaction { experiment.last = simulation.clock.now @@ -163,8 +169,18 @@ class JpaExperiment(private val manager: EntityManager, logger.info { "Average waiting time: $waiting seconds" } logger.info { "Average execution time: $execution seconds" } logger.info { "Average turnaround time: $turnaround seconds" } + + return Unit } + /** + * Run the experiment on the specified simulation [Kernel]. + * + * @param kernel The simulation kernel to run the experiment. + * @throws IllegalStateException if the simulation is already running or finished. + */ + override fun run(kernel: Kernel) = run(kernel, -1)!! + /** * Closes this resource, relinquishing any underlying resources. * This method is invoked automatically on objects managed by the diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt index 794ca44e..104f1aec 100644 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt +++ b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt @@ -45,6 +45,7 @@ fun main(args: Array) { properties["javax.persistence.jdbc.password"] = env["PERSISTENCE_PASSWORD"] ?: "" val factory = Persistence.createEntityManagerFactory("opendc-simulator", properties) + val timeout = 10000L val threads = 4 val executorService = Executors.newFixedThreadPool(threads) val experiments = JpaExperimentManager(factory) @@ -55,7 +56,7 @@ fun main(args: Array) { experiments.poll()?.let { experiment -> logger.info { "Found experiment. Submitting for simulation now..." } executorService.submit { - experiment.use { it.run(kernel) } + experiment.use { it.run(kernel, timeout) } } } -- cgit v1.2.3