summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2018-02-23 12:17:48 +0100
committerFabian Mastenbroek <mail.fabianm@gmail.com>2018-02-23 12:17:48 +0100
commitf691a72b12a43fa15c1617966450c55206664797 (patch)
treee76afd3b1d5673a29d71eedb9d373396976d84bd
parent8666a78b86a40c1d8dab28dd18e841318c01f97f (diff)
parent86dc826db4cd91b5a6875d9ecdd64c9238d7b95c (diff)
refactor(#18): Redesign core simulation API
This change contains the redesign of the core simulation API and provides a cleaner interface for developing simulation models for the users. Closes #18
-rw-r--r--.editorconfig2
-rw-r--r--opendc-core/build.gradle61
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt64
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt168
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Entity.kt)20
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt27
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Time.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Time.kt)2
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Envelope.kt)31
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Simulation.kt74
-rw-r--r--opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt)36
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Context.kt120
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Interrupt.kt32
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Kernel.kt50
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Process.kt51
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Simulation.kt100
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Readable.kt75
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Receipt.kt53
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Writable.kt54
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/sampler/Sampler.kt40
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Clock.kt79
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/TickClock.kt60
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/AdjacencyList.kt258
-rw-r--r--opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/MutableTopology.kt62
-rw-r--r--opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Task.kt117
-rw-r--r--opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperiment.kt192
-rw-r--r--opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperimentManager.kt93
-rw-r--r--opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/topology/JpaTopologyFactory.kt87
-rw-r--r--opendc-integration-jpa/core/src/main/resources/jpa/schema.xml324
-rw-r--r--opendc-integration-jpa/mysql/build.gradle38
-rw-r--r--opendc-kernel-omega/build.gradle88
-rw-r--r--opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Messages.kt30
-rw-r--r--opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt (renamed from opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaKernel.kt)33
-rw-r--r--opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt402
-rw-r--r--opendc-kernel-omega/src/test/kotlin/com/atlarge/opendc/omega/SmokeTest.kt143
-rw-r--r--opendc-model-odc/core/build.gradle (renamed from opendc-integration-jpa/core/build.gradle)69
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/OdcModel.kt10
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/FifoScheduler.kt118
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/Scheduler.kt)68
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/SrtfScheduler.kt110
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Job.kt)36
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Task.kt92
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/TaskState.kt72
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Trace.kt)10
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/User.kt)18
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Datacenter.kt107
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Rack.kt)7
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Room.kt)7
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Cpu.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Cpu.kt)2
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Gpu.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Gpu.kt)2
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Machine.kt123
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/ProcessingUnit.kt)31
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/network/NetworkUnit.kt)7
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/power/PowerUnit.kt)7
-rw-r--r--opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt (renamed from opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/storage/StorageUnit.kt)7
-rw-r--r--opendc-model-odc/jpa/build.gradle91
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaBootstrap.kt51
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaModel.kt14
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/Jpa.kt)8
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/ParallelizableConverter.kt)52
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/SchedulerConverter.kt)56
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Cpu.kt)28
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Datacenter.kt)52
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Experiment.kt)34
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/ExperimentState.kt)36
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Gpu.kt)28
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Job.kt)33
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Machine.kt)14
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/MachineState.kt)20
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Path.kt)6
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Rack.kt)24
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Room.kt)22
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomObject.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomObject.kt)2
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomType.kt)4
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Section.kt)10
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Task.kt118
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/TaskState.kt)16
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Trace.kt)12
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperiment.kt178
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperimentManager.kt93
-rw-r--r--opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/topology/JpaTopologyFactory.kt91
-rw-r--r--opendc-model-odc/jpa/src/main/resources/jpa/schema.xml326
-rw-r--r--opendc-model-odc/setup/Dockerfile (renamed from opendc-integration-jpa/mysql/Dockerfile)5
-rw-r--r--opendc-model-odc/setup/build.gradle (renamed from opendc-omega/build.gradle)66
-rw-r--r--opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt (renamed from opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt)46
-rw-r--r--opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml (renamed from opendc-integration-jpa/mysql/src/main/resources/META-INF/persistence.xml)30
-rw-r--r--opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/MessageContainer.kt68
-rw-r--r--opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaSimulation.kt398
-rw-r--r--opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Resume.kt38
-rw-r--r--opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Timeout.kt33
-rw-r--r--opendc-omega/src/test/kotlin/nl/atlarge/opendc/SmokeTest.kt115
-rw-r--r--opendc-stdlib/build.gradle64
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/AdjacencyList.kt260
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Bootstrap.kt23
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Component.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Component.kt)2
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Edge.kt)48
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/MutableTopology.kt65
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Topology.kt)26
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyBuilder.kt)16
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyContext.kt)28
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyFactory.kt)14
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyListener.kt)52
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Traversable.kt (renamed from opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Traversable.kt)2
-rw-r--r--opendc-stdlib/src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt44
-rw-r--r--opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/FifoScheduler.kt120
-rw-r--r--opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/SrtfScheduler.kt111
-rw-r--r--opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Task.kt92
-rw-r--r--opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/TaskState.kt72
-rw-r--r--opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Datacenter.kt102
-rw-r--r--opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Machine.kt123
-rw-r--r--settings.gradle7
110 files changed, 3637 insertions, 3821 deletions
diff --git a/.editorconfig b/.editorconfig
index 29e7b14b..4b0abe4d 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,7 +4,7 @@
root = true
[*]
-indent_style = tab
+indent_style = space
indent_size = 4
end_of_line = lf
diff --git a/opendc-core/build.gradle b/opendc-core/build.gradle
index 92cdb2c4..223e73f9 100644
--- a/opendc-core/build.gradle
+++ b/opendc-core/build.gradle
@@ -24,19 +24,19 @@
/* Build configuration */
buildscript {
- ext.kotlin_version = '1.1.4-3'
- ext.dokka_version = '0.9.15'
+ ext.kotlin_version = '1.2.21'
+ ext.dokka_version = '0.9.15'
- repositories {
- mavenCentral()
- jcenter()
- }
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
- classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-RC3'
- }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
+ classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3'
+ }
}
apply plugin: 'java'
@@ -45,43 +45,40 @@ apply plugin: 'org.jetbrains.dokka'
apply plugin: 'org.junit.platform.gradle.plugin'
compileKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
compileTestKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
kotlin {
- experimental {
- coroutines 'enable'
- }
+ experimental {
+ coroutines 'enable'
+ }
}
dokka {
- outputFormat = 'html'
- outputDirectory = "$buildDir/javadoc"
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
}
/* Project configuration */
-group 'nl.atlarge.opendc'
-version '1.0'
+group 'com.atlarge.opendc'
+version '1.1'
repositories {
- jcenter()
+ jcenter()
}
dependencies {
- compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
- compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.18"
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3"
- testRuntime "org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3"
- testCompile "org.junit.platform:junit-platform-launcher:1.0.0-RC3"
- testCompile "org.slf4j:slf4j-simple:1.7.25"
+ testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3"
+ testRuntime "org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3"
+ testCompile "org.junit.platform:junit-platform-launcher:1.0.0-RC3"
}
diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt
new file mode 100644
index 00000000..5f41c727
--- /dev/null
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt
@@ -0,0 +1,64 @@
+package com.atlarge.opendc.simulator
+
+/**
+ * A bootstrapping interface for a conceptual model that is a logical representation of some system of entities,
+ * relationships and processes, as a basis for simulations.
+ *
+ * @param M The shape of the model that is bootstrapped.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface Bootstrap<M> {
+ /**
+ * Apply the apply procedure for model `M` for a simulation in the given context.
+ *
+ * @param context The context to apply to model in.
+ * @return The initialised, resulting model for the simulation.
+ */
+ fun apply(context: Context<M>): M
+
+ /**
+ * A context for the apply of some model type `M` that allows the model to register the entities of the model to
+ * the simulation kernel.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+ interface Context<out M> {
+ /**
+ * Register the given entity to the simulation kernel.
+ *
+ * @param entity The entity to register.
+ * @return `true` if the entity had not yet been registered, `false` otherwise.
+ */
+ fun register(entity: Entity<*, M>): Boolean
+
+ /**
+ * Deregister the given entity from the simulation kernel.
+ *
+ * @param entity The entity to deregister.
+ * @return `true` if the entity had not yet been unregistered, `false` otherwise.
+ */
+ fun deregister(entity: Entity<*, M>): Boolean
+
+ /**
+ * Schedule a message to be received by the given [Entity].
+ *
+ * @param message The message to schedule.
+ * @param destination The destination of the message.
+ * @param sender The sender of the message.
+ * @param delay The amount of time to wait before processing the message.
+ */
+ fun schedule(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, delay: Duration = 0)
+ }
+
+ companion object {
+ /**
+ * Create a [Bootstrap] procedure using the given block to produce a apply for a model of type `M`.
+ *
+ * @param block The block to produce the apply.
+ * @return The apply procedure that has been built.
+ */
+ fun <M> create(block: (Context<M>) -> M): Bootstrap<M> = object : Bootstrap<M> {
+ override fun apply(context: Context<M>) = block(context)
+ }
+ }
+}
diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt
new file mode 100644
index 00000000..23d10e8f
--- /dev/null
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt
@@ -0,0 +1,168 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.simulator
+
+import java.util.*
+import kotlin.coroutines.experimental.CoroutineContext
+
+/**
+ * This interface provides a context for simulation of [Entity] instances, by defining the environment in which the
+ * simulation is run and provides means of communicating with other entities in the environment and control its own
+ * behaviour.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface Context<S, M> : CoroutineContext.Element {
+ /**
+ * The model of simulation in which the entity exists.
+ */
+ val model: M
+
+ /**
+ * The current point in simulation time.
+ */
+ val time: Instant
+
+ /**
+ * The duration between the current point in simulation time and the last point in simulation time where the
+ * [Entity] has done some work. This means the `run()` co-routine has been resumed.
+ */
+ val delta: Duration
+
+ /**
+ * The [Entity] associated with this context.
+ */
+ val self: Entity<S, M>
+
+ /**
+ * The sender of the last received message or `null` in case the process has not received any messages yet.
+ *
+ * Note that this property is only guaranteed to be correct when accessing after a single suspending call. Methods
+ * like `hold()` and `interrupt()` may change the value of this property.
+ */
+ val sender: Entity<*, *>?
+
+ /**
+ * The observable state of the entity bound to this scope.
+ */
+ var state: S
+
+ /**
+ * The observable state of an [Entity] in simulation, which is provided by the simulation context.
+ */
+ val <E : Entity<S, *>, S> E.state: S
+
+ /**
+ * Interrupt an [Entity] process in simulation.
+ *
+ * If an [Entity] process has been suspended, the suspending call will throw an [Interrupt] object as a result of
+ * this call.
+ * Make sure the [Entity] process actually has error handling in place, so it won't take down the whole [Entity]
+ * process as result of the interrupt.
+ *
+ * @param interrupt The interrupt to throw at the entity.
+ */
+ suspend fun Entity<*, *>.interrupt(interrupt: Interrupt)
+
+ /**
+ * Interrupt an [Entity] process in simulation.
+ *
+ * @see [Entity.interrupt(Interrupt)]
+ * @param reason The reason for interrupting the entity.
+ */
+ suspend fun Entity<*, *>.interrupt(reason: String) = interrupt(Interrupt(reason))
+
+ /**
+ * Suspend the [Context] of the [Entity] in simulation for the given duration of simulation time before resuming
+ * execution and drop all messages that are received during this period.
+ *
+ * A call to this method will not make the [Context] sleep for the actual duration of time, but instead suspend
+ * the process until the no more messages at an earlier point in time have to be processed.
+ *
+ * @param duration The duration of simulation time to hold before resuming execution.
+ */
+ suspend fun hold(duration: Duration)
+
+ /**
+ * Suspend the [Context] of the [Entity] in simulation for the given duration of simulation time before resuming
+ * execution and push all messages that are received during this period to the given queue.
+ *
+ * A call to this method will not make the [Context] sleep for the actual duration of time, but instead suspend
+ * the process until the no more messages at an earlier point in time have to be processed.
+ *
+ * @param duration The duration of simulation time to wait before resuming execution.
+ * @param queue The mutable queue to push the messages to.
+ */
+ suspend fun hold(duration: Duration, queue: Queue<Any>)
+
+ /**
+ * Retrieve and remove a single message from the instance's mailbox, suspending the function if the mailbox is
+ * empty. The execution is resumed after the head of the mailbox is removed and returned.
+ *
+ * @return The received message.
+ */
+ suspend fun receive(): Any
+
+ /**
+ * Retrieve and remove a single message from the instance's mailbox, suspending the function if the mailbox is
+ * empty. The execution is either resumed after the head of the mailbox is removed and returned or when the timeout
+ * has been reached.
+ *
+ * @return The received message or `null` if the timeout was reached.
+ */
+ suspend fun receive(timeout: Duration): Any?
+
+ /**
+ * Send the given message to the specified entity, without providing any guarantees about the actual delivery of
+ * the message.
+ *
+ * @param msg The message to send.
+ * @param sender The sender of the message.
+ * @param delay The amount of time to wait before the message should be received by the entity.
+ */
+ suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration = 0)
+
+ /**
+ * Send the given message to the specified entity, without providing any guarantees about the actual delivery of
+ * the message.
+ *
+ * @param msg The message to send.
+ * @param delay The amount of time to wait before the message should be received by the entity.
+ */
+ suspend fun Entity<*, *>.send(msg: Any, delay: Duration = 0) = send(msg, self, delay)
+
+ /**
+ * This key provides users access to an untyped process context in case the coroutine runs inside a simulation.
+ */
+ companion object Key : CoroutineContext.Key<Context<*, *>>
+}
+
+/**
+ * An [Interrupt] message is sent to an [Entity] process in order to interrupt its suspended state.
+ *
+ * @param reason The reason for the interruption of the process.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+open class Interrupt(reason: String) : Throwable(reason)
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Entity.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt
index 66a31d77..56704c5d 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Entity.kt
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt
@@ -22,23 +22,23 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.simulator
/**
- * An entity within a cloud network, represented as a node within a topology.
+ * An entity in some model `M`.
*
- * <p>A [Entity] contains immutable properties given by the topology configuration at the start of a simulation and
- * remain unchanged during simulation.
+ * <p>A [Entity] directly contains its immutable properties that remain unchanged during simulation.
*
- * <p>In addition, other entities in a simulation have direct, immutable access to the observable state of this entity.
+ * <p>In addition, other entities in simulation have direct, immutable access to the observable state of this entity.
*
* @param S The shape of the observable state of this entity, which is directly accessible by other components within
* a simulation.
+ * @param M The shape of the model in which the entity exists.
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface Entity<out S> : Component {
- /**
- * The initial state of the entity.
- */
- val initialState: S
+interface Entity<out S, in M> {
+ /**
+ * The initial state of the entity.
+ */
+ val initialState: S
}
diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt
new file mode 100644
index 00000000..f2b8a52b
--- /dev/null
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt
@@ -0,0 +1,27 @@
+package com.atlarge.opendc.simulator
+
+/**
+ * A process is dynamic entity within a simulation, that interacts with the model environment by the interchange of
+ * messages.
+ *
+ * @param S The shape of the observable state of the process.
+ * @param M The shape of the model in which the process exists.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface Process<S, M> : Entity<S, M> {
+ /**
+ * This method is invoked to start the simulation a process.
+ *
+ * This method is assumed to be running during a simulation, but should hand back control to the simulator at
+ * some point by suspending the process. This allows other processes to do work at the current point in time of the
+ * simulation.
+ * Suspending the process can be achieved by calling suspending method in the context:
+ * - [Context.hold] - Hold for `n` units of time before resuming execution.
+ * - [Context.receive] - Wait for a message to be received in the mailbox of the [Entity] before resuming
+ * execution.
+ *
+ * If this method exits early, before the simulation has finished, the entity is assumed to be shutdown and its
+ * simulation will not run any further.
+ */
+ suspend fun Context<S, M>.run()
+}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Time.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Time.kt
index af9d547b..64e3cb80 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Time.kt
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Time.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.kernel.time
+package com.atlarge.opendc.simulator
/**
* An instantaneous point on the time-line, used to record event time-stamps in a simulation.
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Envelope.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt
index 608d325f..d4995283 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Envelope.kt
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt
@@ -22,29 +22,22 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.kernel.messaging
+package com.atlarge.opendc.simulator.kernel
-import nl.atlarge.opendc.topology.Entity
+import com.atlarge.opendc.simulator.Bootstrap
/**
- * The envelope of a message that is sent to an [Entity], also containing the metadata of the message.
+ * A message-based discrete event simulator (DES). This interface is a factory for creating [Simulation]s using the
+ * provided [Bootstrap] for the model.
*
- * @param T The shape of the message inside the envelope.
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface Envelope<out T: Any> {
- /**
- * The message in this envelope.
- */
- val message: T
-
- /**
- * The sender of the message.
- */
- val sender: Entity<*>?
-
- /**
- * The destination of the message.
- */
- val destination: Entity<*>
+interface Kernel {
+ /**
+ * Create a simulation over the given model facilitated by this simulation kernel.
+ *
+ * @param bootstrap The apply procedure to apply the simulation with.
+ * @return A [Simulation] instance representing the simulation.
+ */
+ fun <M> create(bootstrap: Bootstrap<M>): Simulation<M>
}
diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Simulation.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Simulation.kt
new file mode 100644
index 00000000..bb2ef818
--- /dev/null
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Simulation.kt
@@ -0,0 +1,74 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.simulator.kernel
+
+import com.atlarge.opendc.simulator.Entity
+import com.atlarge.opendc.simulator.Instant
+
+/**
+ * A message based discrete event simulation over some model `M`. This interface provides direct control over the
+ * simulation, allowing the user to step over cycles of the simulation and inspecting the state of the simulation via
+ * [Entity.state].
+ *
+ * @param M The shape of the model over which the simulation runs.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface Simulation<out M> {
+ /**
+ * The model in which the simulation runs.
+ */
+ val model: M
+
+ /**
+ * The simulation time.
+ */
+ var time: Instant
+
+ /**
+ * The observable state of an [Entity] in simulation, which is provided by the simulation context.
+ */
+ val <E : Entity<S, *>, S> E.state: S
+
+ /**
+ * Step through one cycle in the simulation. This method will process all events in a single tick, update the
+ * internal clock and then return the control to the user.
+ */
+ fun step()
+
+ /**
+ * Run a simulation over the specified model.
+ * This method will step through multiple cycles in the simulation until no more message exist in the queue.
+ */
+ fun run()
+
+ /**
+ * Run a simulation over the specified model, stepping through cycles until the specified clock tick has
+ * occurred. The control is then handed back to the user.
+ *
+ * @param until The point in simulation time at which the simulation should be paused and the control is handed
+ * back to the user.
+ */
+ fun run(until: Instant)
+}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt
index 6aed5364..eb959ded 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt
+++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt
@@ -22,10 +22,10 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.platform
+package com.atlarge.opendc.simulator.platform
-import nl.atlarge.opendc.kernel.Kernel
-import nl.atlarge.opendc.kernel.time.Duration
+import com.atlarge.opendc.simulator.Duration
+import com.atlarge.opendc.simulator.kernel.Kernel
/**
* A blueprint for a reproducible simulation in a pre-defined setting.
@@ -33,20 +33,20 @@ import nl.atlarge.opendc.kernel.time.Duration
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface Experiment<out T> {
- /**
- * 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 kernel implementation.
+ *
+ * @param factory The factory to create the simulation kernel with.
+ * @return The result of the experiment.
+ */
+ fun run(factory: 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?
+ /**
+ * Run the experiment on the specified kernel implementation.
+ *
+ * @param factory The factory to create the simulation kernel with.
+ * @param timeout The maximum duration of the experiment before returning to the caller.
+ * @return The result of the experiment or `null`.
+ */
+ fun run(factory: Kernel, timeout: Duration): T?
}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Context.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Context.kt
deleted file mode 100644
index 83a7c4fb..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Context.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel
-
-import nl.atlarge.opendc.kernel.messaging.Readable
-import nl.atlarge.opendc.kernel.messaging.Writable
-import nl.atlarge.opendc.kernel.time.Clock
-import nl.atlarge.opendc.kernel.time.Duration
-import nl.atlarge.opendc.kernel.time.Instant
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.MutableTopology
-import nl.atlarge.opendc.topology.Topology
-import nl.atlarge.opendc.topology.TopologyContext
-import java.lang.Process
-import java.util.*
-
-/**
- * This interface provides a context for simulation [Process]es, which defines the environment in which the simulation
- * is run and provides means of communicating with other entities in the environment and control its own behaviour.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Context<out E : Entity<*>> : Readable, Writable, TopologyContext {
- /**
- * The [Entity] in simulation by the [Process].
- */
- val entity: E
-
- /**
- * The [Topology] over which the simulation is run.
- */
- val topology: MutableTopology
-
- /**
- * The current point in simulation time.
- */
- val time: Instant
-
- /**
- * The duration between the current point in simulation time and the last point in simulation time where the
- * [Process] has executed some work. This means the `run()` co-routine has been resumed.
- */
- val delta: Duration
-
- /**
- * The observable state of an [Entity] in simulation, which is provided by the simulation context.
- */
- val <E : Entity<S>, S> E.state: S
-
- /**
- * Update the observable state of the entity being simulated.
- *
- * Instead of directly mutating the entity, we create a new instance of the entity to prevent other objects
- * referencing the old entity having their data changed.
- *
- * @param next The next state of the entity.
- */
- suspend fun <C : Context<E>, E : Entity<S>, S> C.update(next: S)
-
- /**
- * Interrupt the [Process] of an [Entity] in simulation.
- *
- * If a [Process] has been suspended, the suspending call will throw an [Interrupt] object as a result of this call.
- * Make sure the [Process] actually has error handling in place, so it won't take down the whole [Process].
- */
- suspend fun Entity<*>.interrupt()
-
- /**
- * Suspend the [Process] of the [Entity] in simulation for the given duration of simulation time before resuming
- * execution and drop all messages that are received during this period.
- *
- * A call to this method will not make the [Process] sleep for the actual duration of time, but instead suspend
- * the process until the no more messages at an earlier point in time have to be processed.
- *
- * @param duration The duration of simulation time to wait before resuming execution.
- */
- suspend fun wait(duration: Duration)
-
- /**
- * Suspend the [Process] of the [Entity] in simulation for the given duration of simulation time before resuming
- * execution and push all messages that are received during this period to the given queue.
- *
- * A call to this method will not make the [Process] sleep for the actual duration of time, but instead suspend
- * the process until the no more messages at an earlier point in time have to be processed.
- *
- * @param duration The duration of simulation time to wait before resuming execution.
- * @param queue The mutable queue to push the messages to.
- */
- suspend fun wait(duration: Duration, queue: Queue<Any>)
-
- /**
- * Suspend the [Process] of the [Entity] in simulation for one tick in simulation time which is defined by the
- * [Clock].
- *
- * @return `true` to allow usage in while statements.
- */
- suspend fun tick(): Boolean
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Interrupt.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Interrupt.kt
deleted file mode 100644
index de7c5c6c..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Interrupt.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel
-
-/**
- * An [Interrupt] message is sent to a [Process] in order to interrupt its suspended state.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-object Interrupt: Throwable("The process has been interrupted by another entity")
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Kernel.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Kernel.kt
deleted file mode 100644
index ffb6299c..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Kernel.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel
-
-import nl.atlarge.opendc.topology.MutableTopology
-import nl.atlarge.opendc.topology.Topology
-
-/**
- * A message-based discrete event simulator (DES). This interface allows running simulations over a [Topology].
- * This discrete event simulator works by having entities in a [Topology] interchange messages between each other and
- * updating their observable state accordingly.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Kernel {
- /**
- * The name of the kernel.
- */
- val name: String
-
- /**
- * Create a new [Simulation] of the given [Topology] that is facilitated by this simulation kernel.
- *
- * @param topology The [Topology] to create a [Simulation] of.
- * @return A [Simulation] instance.
- */
- fun create(topology: MutableTopology): Simulation
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Process.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Process.kt
deleted file mode 100644
index 40fbefbf..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Process.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel
-
-import nl.atlarge.opendc.topology.Entity
-
-/**
- * A [Process] defines the behaviour of an [Entity] within simulation.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Process<in E : Entity<*>> {
- /**
- * This method is invoked to start the simulation an [Entity] associated with this [Process].
- *
- * This method is assumed to be running during a simulation, but should hand back control to the simulator at
- * some point by suspending the process. This allows other processes to do work in the current tick of the
- * simulation.
- * Suspending the process can be achieved by calling suspending method in the context:
- * - [Context.tick] - Wait for the next tick to occur
- * - [Context.wait] - Wait for `n` amount of ticks before resuming execution.
- * - [Context.receive] - Wait for a message to be received in the mailbox of the [Entity] before resuming
- * execution.
- *
- * If this method exits early, before the simulation has finished, the entity is assumed to be shutdown and its
- * simulation will not run any further.
- */
- suspend fun Context<E>.run()
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Simulation.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Simulation.kt
deleted file mode 100644
index d07c3ba0..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Simulation.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel
-
-import nl.atlarge.opendc.kernel.messaging.Receipt
-import nl.atlarge.opendc.kernel.time.Clock
-import nl.atlarge.opendc.kernel.time.Duration
-import nl.atlarge.opendc.kernel.time.Instant
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.Topology
-import java.lang.Process
-
-/**
- * A message based discrete event simulation facilitated by a simulation [Kernel].
- *
- * In order for the simulation to run, the simulation kernel needs to bootstrapped by an set of messages to be processed
- * initially by entities in the topology of the simulation. Otherwise, the simulation will immediately exit.
- * Bootstrapping can be achieved by scheduling messages before running the simulation via [Simulation.schedule]:
- *
- * `val simulation = kernel.create(topology).apply {
- * schedule(Boot, entity)
- * }`
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Simulation {
- /**
- * The [Kernel] that facilitates the simulation.
- */
- val kernel: Kernel
-
- /**
- * The [Topology] over which the simulation is run.
- */
- val topology: Topology
-
- /**
- * The [Clock] instance that keeps track of simulation time.
- */
- val clock: Clock
-
- /**
- * The observable state of an [Entity] in simulation, which is provided by the simulation context.
- */
- val <E : Entity<S>, S> E.state: S
-
- /**
- * Step through one cycle in the simulation. This method will process all events in a single tick, update the
- * internal clock and then return the control to the user.
- */
- fun step()
-
- /**
- * Run a simulation over the specified [Topology].
- * This method will step through multiple cycles in the simulation until no more message exist in the queue.
- */
- fun run()
-
- /**
- * Run a simulation over the specified [Topology], stepping through cycles until the specified clock tick has
- * occurred. The control is then handed back to the user.
- *
- * @param until The point in simulation time at which the simulation should be paused and the control is handed
- * back to the user.
- */
- fun run(until: Instant)
-
- /**
- * Schedule a message for processing by a [Process].
- *
- * @param message The message to schedule.
- * @param destination The destination of the message.
- * @param sender The sender of the message.
- * @param delay The amount of time to wait before processing the message.
- * @return A [Receipt] of the message that has been scheduled.
- */
- fun schedule(message: Any, destination: Entity<*>, sender: Entity<*>? = null, delay: Duration = 0): Receipt
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Readable.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Readable.kt
deleted file mode 100644
index 398e9697..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Readable.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.messaging
-
-import nl.atlarge.opendc.kernel.time.Duration
-
-
-/**
- * A [Readable] instance has a mailbox associated with the instance to which objects can send messages, which can be
- * received by the class.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Readable {
- /**
- * Retrieve and removes a single message from the entity's mailbox, suspending the function if the mailbox is empty.
- * The execution is resumed after the message has landed in the entity's mailbox after which the message [Envelope]
- * is mapped through `block` to generate a processed message.
- *
- * @param block The block to process the message with.
- * @return The processed message.
- */
- suspend fun <T> receive(block: suspend Envelope<*>.(Any) -> T): T
-
- /**
- * Retrieve and removes a single message from the entity's mailbox, suspending the function if the mailbox is empty.
- * The execution is resumed after the message has landed in the entity's mailbox or the timeout was reached,
- *
- * If the message has been received, the message [Envelope] is mapped through `block` to generate a processed
- * message. If the timeout was reached, `block` is not called and `null` is returned.
- *
- * @param timeout The duration to wait before resuming execution.
- * @param block The block to process the message with.
- * @return The processed message or `null` if the timeout was reached.
- */
- suspend fun <T> receive(timeout: Duration, block: suspend Envelope<*>.(Any) -> T): T?
-
- /**
- * Retrieve and removes a single message from the entity's mailbox, suspending the function until a message has
- * landed in the entity's mailbox.
- *
- * @return The message that was received from the entity's mailbox.
- */
- suspend fun receive(): Any = receive { it }
-
- /**
- * Retrieve and removes a single message from the entity's mailbox, suspending the function until a message has
- * landed in the entity's mailbox or the timeout has been reached.
- *
- * @return The message that was received from the entity's mailbox or `null` if the timeout was reached.
- */
- suspend fun receive(timeout: Duration): Any? = receive(timeout) { it }
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Receipt.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Receipt.kt
deleted file mode 100644
index 74433f5e..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Receipt.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.messaging
-
-import nl.atlarge.opendc.kernel.Kernel
-import nl.atlarge.opendc.topology.Entity
-
-/**
- * A receipt of a message that has been scheduled by a simulation [Kernel]. This interface allows the cancellation of a
- * message that has been scheduled for delivery and for checking the status of a delivery.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Receipt {
- /**
- * A flag to indicate the message has been canceled.
- */
- val canceled: Boolean
-
- /**
- * A flag to indicate the message has been delivered.
- */
- val delivered: Boolean
-
- /**
- * Cancel the message to prevent it from being received by an [Entity].
- *
- * @throws IllegalStateException if the message has already been delivered.
- */
- fun cancel()
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Writable.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Writable.kt
deleted file mode 100644
index 0d2b2725..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Writable.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.messaging
-
-import nl.atlarge.opendc.kernel.time.Duration
-import nl.atlarge.opendc.topology.Entity
-
-/**
- * A [Writable] instance allows entities to send messages.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Writable {
- /**
- * Send the given message to the specified entity.
- *
- * @param msg The message to send.
- * @param delay The amount of time to wait before the message should be received.
- * @return A [Receipt] of the message that has been sent.
- */
- suspend fun Entity<*>.send(msg: Any, delay: Duration = 0): Receipt
-
- /**
- * Send the given message to the specified entity.
- *
- * @param msg The message to send.
- * @param sender The sender of the message.
- * @param delay The amount of time to wait before the message should be received.
- * @return A [Receipt] of the message that has been sent.
- */
- suspend fun Entity<*>.send(msg: Any, sender: Entity<*>, delay: Duration = 0): Receipt
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/sampler/Sampler.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/sampler/Sampler.kt
deleted file mode 100644
index 66c33341..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/sampler/Sampler.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.sampler
-
-/**
- * A sampler generates data points (samples) of the simulation based on the events that occur to [Entity] instances that
- * are part of the simulation.
- *
- * <p>[Sampler]s work by observing [Entity] instances in the simulation and transforming this stream of events into a
- * stream of data points.
- *
- * <p>An example would be a sampler that tracks [Machine] occupation per time unit, which is achieved by observing the
- * [Entity]'s event stream and filtering for [JobAssignment] events.
- *
- * @param <T> The data type of result generated by this sampler.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Sampler<out T>
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Clock.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Clock.kt
deleted file mode 100644
index f03a98fa..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Clock.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.time
-
-import nl.atlarge.opendc.kernel.Simulation
-
-/**
- * A clock controls and provides access to the simulation time of a [Simulation].
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Clock {
- /**
- * The moment in time the clock is currently at.
- */
- val now: Instant
-
- /**
- * The duration of a tick in this clock. This is an arbitrary duration of time in which entities in simulation
- * perform some defined amount of work.
- */
- val tick: Duration
-
- /**
- * Advance the clock by the given duration.
- *
- * @param duration The duration to advance the clock by.
- */
- fun advance(duration: Duration) {
- require(duration >= 0) { "The duration to advance the clock must not be a negative number" }
- advanceTo(now + duration)
- }
-
- /**
- * Rewind the clock by the given duration.
- *
- * @param duration The duration to rewind the clock by.
- */
- fun rewind(duration: Duration) {
- require(duration >= 0) { "The duration to rewind the clock must not be a negative number" }
- rewindTo(now - duration)
- }
-
- /**
- * Rewind the clock to the given point in time.
- *
- * @param instant The point in time to rewind the clock to.
- */
- fun rewindTo(instant: Instant)
-
- /**
- * Advance the clock to the given point in time.
- *
- * @param instant The point in time to advance the clock to.
- */
- fun advanceTo(instant: Instant)
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/TickClock.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/TickClock.kt
deleted file mode 100644
index d960f454..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/TickClock.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.time
-
-/**
- * A tick based clock which divides time into a discrete interval of points.
- *
- * @param initial The initial point in time of the clock.
- * @param tick The duration of a tick.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-class TickClock(initial: Instant = 0, override val tick: Duration = 1) : Clock {
- /**
- * The moment in time the clock is currently at.
- */
- override var now: Instant = initial
- private set
-
- /**
- * Advance the clock to the given point in time.
- *
- * @param instant The moment in time to advance the clock to.
- */
- override fun advanceTo(instant: Instant) {
- require(instant >= now) { "The point to advance to must be at the same point or further than now" }
- now = instant
- }
-
- /**
- * Rewind the clock to the given point in time.
- *
- * @param instant The point in time to rewind the clock to.
- */
- override fun rewindTo(instant: Instant) {
- require(now >= instant) { "The point to rewind to must be before the current point in time" }
- now = instant
- }
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/AdjacencyList.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/AdjacencyList.kt
deleted file mode 100644
index 74b046de..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/AdjacencyList.kt
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.topology
-
-import nl.atlarge.opendc.topology.Edge as BaseEdge
-import java.util.concurrent.atomic.AtomicInteger
-
-/**
- * This module provides a [Topology] implementation backed internally by an adjacency list.
- *
- * This implementation is best suited for sparse graphs, where an adjacency matrix would take up too much space with
- * empty cells.
- *
- * *Note that this implementation is not synchronized.*
- */
-object AdjacencyList {
- /**
- * Return a [TopologyBuilder] that constructs the topology represents as an adjacency list.
- *
- * @return A [TopologyBuilder] instance.
- */
- fun builder(): TopologyBuilder = AdjacencyListTopologyBuilder()
-}
-
-/**
- * A builder for [Topology] instances, which is backed by an adjacency list.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-internal class AdjacencyListTopologyBuilder : TopologyBuilder {
- /**
- * Build a [Topology] instance from the current state of this builder.
- *
- * @return The graph built from this builder.
- */
- override fun create(): MutableTopology = AdjacencyListTopology()
-}
-
-/**
- * A [Topology] whose graph is represented as adjacency list.
- */
-internal class AdjacencyListTopology : MutableTopology {
- /**
- * The identifier for the next node in the graph.
- */
- private var nextId: AtomicInteger = AtomicInteger(0)
-
- /**
- * A mapping of nodes to their internal representation with the edges of the nodes.
- */
- private var nodes: MutableMap<Entity<*>, Node> = HashMap()
-
- // Topology
-
- /**
- * The listeners of this topology.
- */
- override val listeners: MutableSet<TopologyListener> = HashSet()
-
- /**
- * A unique identifier of this node within the topology.
- */
- override val Entity<*>.id: Int
- get() = nodes[this]!!.id
-
- /**
- * The set of ingoing edges of this node.
- */
- override val Entity<*>.ingoingEdges: MutableSet<BaseEdge<*>>
- get() = nodes[this]!!.ingoingEdges
-
- /**
- * The set of outgoing edges of this node.
- */
- override val Entity<*>.outgoingEdges: MutableSet<BaseEdge<*>>
- get() = nodes[this]!!.outgoingEdges
-
- // MutableTopology
-
- /**
- * Create a directed edge between two [Node]s in the topology.
- *
- * @param from The source of the edge.
- * @param to The destination of the edge.
- * @param label The label of the edge.
- * @param tag The tag of the edge that uniquely identifies the relationship the edge represents.
- * @return The edge that has been created.
- */
- override fun <T> connect(from: Entity<*>, to: Entity<*>, label: T, tag: String?): BaseEdge<T> {
- if (!contains(from) || !contains(to))
- throw IllegalArgumentException("One of the entities is not part of the topology")
- val edge = Edge(label, tag, from, to)
- from.outgoingEdges.add(edge)
- to.ingoingEdges.add(edge)
- listeners.forEach { it.run { this@AdjacencyListTopology.onEdgeAdded(edge) } }
- return edge
- }
-
- // Cloneable
-
- /**
- * Create a copy of the graph.
- *
- * @return A new [Topology] instance with a copy of the graph.
- */
- override public fun clone(): Topology {
- val copy = AdjacencyListTopology()
- copy.nextId = AtomicInteger(nextId.get())
- copy.nodes = HashMap(nodes)
- return copy
- }
-
- // Set
-
- /**
- * Returns the size of the collection.
- */
- override val size: Int = nodes.size
-
- /**
- * Checks if the specified element is contained in this collection.
- */
- override fun contains(element: Entity<*>): Boolean = nodes.contains(element)
-
- /**
- * Checks if all elements in the specified collection are contained in this collection.
- */
- override fun containsAll(elements: Collection<Entity<*>>): Boolean = elements.all { nodes.containsKey(it) }
-
- /**
- * Returns `true` if the collection is empty (contains no elements), `false` otherwise.
- */
- override fun isEmpty(): Boolean = nodes.isEmpty()
-
- // MutableSet
-
- /**
- * Add a node to the graph.
- *
- * @param element The element to add to this graph.
- * @return `true` if the graph has changed, `false` otherwise.
- */
- override fun add(element: Entity<*>): Boolean {
- if (nodes.putIfAbsent(element, Node(nextId.getAndIncrement())) == null) {
- listeners.forEach { it.run { this@AdjacencyListTopology.onNodeAdded(element) } }
- return true
- }
- return false
- }
-
- /**
- * Add all nodes in the specified collection to the graph.
- *
- * @param elements The nodes to add to this graph.
- * @return `true` if the graph has changed, `false` otherwise.
- */
- override fun addAll(elements: Collection<Entity<*>>): Boolean = elements.any { add(it) }
-
- /**
- * Remove all nodes and their respective edges from the graph.
- */
- override fun clear() = nodes.clear()
-
- /**
- * Remove the given node and its edges from the graph.
- *
- * @param element The element to remove from the graph.
- * @return `true` if the graph has changed, `false` otherwise.
- */
- override fun remove(element: Entity<*>): Boolean {
- nodes[element]?.ingoingEdges?.forEach {
- it.from.outgoingEdges.remove(it)
- }
- nodes[element]?.outgoingEdges?.forEach {
- it.to.ingoingEdges.remove(it)
- }
- if (nodes.keys.remove(element)) {
- listeners.forEach { it.run { this@AdjacencyListTopology.onNodeRemoved(element) } }
- return true
- }
- return false
- }
-
-
- /**
- * Remove all nodes in the given collection from the graph.
- *
- * @param elements The elements to remove from the graph.
- * @return `true` if the graph has changed, `false` otherwise.
- */
- override fun removeAll(elements: Collection<Entity<*>>): Boolean = elements.any(this::remove)
-
- /**
- * Remove all nodes in the graph, except those in the specified collection.
- *
- * Take note that this method currently only guarantees a maximum runtime complexity of O(n^2).
- *
- * @param elements The elements to retain in the graph.
- */
- override fun retainAll(elements: Collection<Entity<*>>): Boolean {
- val iterator = nodes.keys.iterator()
- var changed = false
- while (iterator.hasNext()) {
- val entity = iterator.next()
-
- if (entity !in elements) {
- iterator.remove()
- changed = true
- }
- }
- return changed
- }
-
- /**
- * Return a mutable iterator over the nodes of the graph.
- *
- * @return A [MutableIterator] over the nodes of the graph.
- */
- override fun iterator(): MutableIterator<Entity<*>> = nodes.keys.iterator()
-
- /**
- * The internal representation of a node within the graph.
- */
- internal data class Node(val id: Int) {
- val ingoingEdges: MutableSet<BaseEdge<*>> = HashSet()
- val outgoingEdges: MutableSet<BaseEdge<*>> = HashSet()
- }
-
- /**
- * The internal representation of an edge within the graph.
- */
- internal class Edge<out T>(override val label: T,
- override val tag: String?,
- override val from: Entity<*>,
- override val to: Entity<*>) : BaseEdge<T>
-}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/MutableTopology.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/MutableTopology.kt
deleted file mode 100644
index 10a55e5b..00000000
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/MutableTopology.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.topology
-
-/**
- * A subinterface of [Topology] which adds mutation methods. When mutation is not required, users
- * should prefer the [Topology] interface.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface MutableTopology : Topology, MutableSet<Entity<*>> {
- /**
- * Create a directed, labeled edge between two nodes in the topology.
- *
- * @param from The source of the edge.
- * @param to The destination of the edge.
- * @param label The label of the edge.
- * @param tag The tag of the edge that uniquely identifies the relationship the edge represents.
- * @return The edge that has been created.
- */
- fun <T> connect(from: Entity<*>, to: Entity<*>, label: T, tag: String? = null): Edge<T>
-
- /**
- * Create a directed, unlabeled edge between two nodes in the topology.
- *
- * @param from The source of the edge.
- * @param to The destination of the edge.
- * @param tag The tag of the edge that uniquely identifies the relationship the edge represents.
- * @return The edge that has been created.
- */
- fun connect(from: Entity<*>, to: Entity<*>, tag: String? = null): Edge<Unit> = connect(from, to, Unit, tag)
-
- /**
- * Create a directed, unlabeled edge between two nodes in the topology.
- *
- * @param dest The destination of the edge.
- * @return The edge that has been created.
- */
- infix fun Entity<*>.to(dest: Entity<*>): Edge<Unit> = connect(this, dest)
-}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Task.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Task.kt
deleted file mode 100644
index 83a98cfb..00000000
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Task.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.integration.jpa.schema
-
-import nl.atlarge.opendc.kernel.time.Instant
-import nl.atlarge.opendc.platform.workload.Task
-import nl.atlarge.opendc.platform.workload.TaskState
-import javax.persistence.*
-
-/**
- * A [Task] backed by the JPA API and an underlying database connection.
- *
- * @property id The unique identifier of the job.
- * @property flops The total amount of flops for the task.
- * @property dependency A dependency on another task.
- * @property parallelizable A flag to indicate the task is parallelizable.
- * @property startTime The start time in the simulation.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-@Entity
-data class Task(
- override val id: Int,
- override val flops: Long,
- private val dependency: Task?,
- override val parallelizable: Boolean,
- val startTime: Instant
-) : Task {
- /**
- * The dependencies of the task.
- */
- override lateinit var dependencies: Set<Task>
- private set
-
- /**
- * The remaining flops for this task.
- */
- override var remaining: Long = 0
- private set
-
- /**
- * A flag to indicate whether the task has finished.
- */
- override var finished: Boolean = false
- private set
-
- /**
- * The state of the task.
- */
- override lateinit var state: TaskState
- private set
-
- /**
- * This method initialises the task object after it has been created by the JPA implementation. We use this
- * initialisation method because JPA implementations only call the default constructor
- */
- @PostLoad
- internal fun init() {
- remaining = flops
- dependencies = dependency?.let(::setOf) ?: emptySet()
- state = TaskState.Underway
- }
-
- /**
- * This method is invoked when a task has arrived at a datacenter.
- *
- * @param time The moment in time the task has arrived at the datacenter.
- */
- override fun arrive(time: Instant) {
- if (state !is TaskState.Underway) {
- throw IllegalStateException("The task has already been submitted to a datacenter")
- }
- remaining = flops
- state = TaskState.Queued(time)
- }
-
- /**
- * Consume the given amount of flops of this task.
- *
- * @param time The current moment in time of the consumption.
- * @param flops The total amount of flops to consume.
- */
- override fun consume(time: Instant, flops: Long) {
- if (state is TaskState.Queued) {
- state = TaskState.Running(state as TaskState.Queued, time)
- } else if (finished) {
- return
- }
- remaining -= flops
- if (remaining <= 0) {
- remaining = 0
- finished = true
- state = TaskState.Finished(state as TaskState.Running, time)
- }
- }
-}
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
deleted file mode 100644
index 9e0e0565..00000000
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperiment.kt
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.platform
-
-import mu.KotlinLogging
-import nl.atlarge.opendc.integration.jpa.schema.ExperimentState
-import nl.atlarge.opendc.integration.jpa.schema.MachineState
-import nl.atlarge.opendc.integration.jpa.transaction
-import nl.atlarge.opendc.integration.jpa.schema.Trace as InternalTrace
-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
-import nl.atlarge.opendc.topology.container.Room
-import nl.atlarge.opendc.topology.destinations
-import nl.atlarge.opendc.topology.machine.Machine
-import java.util.*
-import javax.persistence.EntityManager
-
-/**
- * An [Experiment] backed by the JPA API and an underlying database connection.
- *
- * @property manager The entity manager for the database connection.
- * @property experiment The internal experiment definition to use.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-class JpaExperiment(private val manager: EntityManager,
- private val experiment: InternalExperiment): Experiment<Unit>, AutoCloseable {
- /**
- * The logging instance.
- */
- private val logger = KotlinLogging.logger {}
-
- /**
- * 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`.
- */
- override fun run(kernel: Kernel, timeout: Duration): Unit? {
- if (experiment.state != ExperimentState.CLAIMED) {
- throw IllegalStateException("The experiment is in illegal state ${experiment.state}")
- }
-
- // Set the simulation state
- manager.transaction {
- experiment.state = ExperimentState.SIMULATING
- }
-
- val section = experiment.path.sections.first()
-
- // Important: initialise the scheduler of the datacenter
- section.datacenter.scheduler = experiment.scheduler
-
- val topology = JpaTopologyFactory(section).create()
- val simulation = kernel.create(topology)
- val trace = experiment.trace
- val tasks = trace.jobs.flatMap { it.tasks }
-
- logger.info { "Sending trace to kernel ${Objects.hashCode(trace)} ${(trace as InternalTrace).id}" }
-
- // Schedule all messages in the trace
- tasks.forEach { task ->
- if (task is InternalTask) {
- simulation.schedule(task, section.datacenter, delay = task.startTime)
- } else {
- logger.warn { "Dropped invalid task $task" }
- }
- }
-
- // Find all machines in the datacenter
- val machines = topology.run {
- section.datacenter.outgoingEdges.destinations<Room>("room").asSequence()
- .flatMap { it.outgoingEdges.destinations<Rack>("rack").asSequence() }
- .flatMap { it.outgoingEdges.destinations<Machine>("machine").asSequence() }.toList()
- }
-
- 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
-
- machines.forEach { machine ->
- val state = simulation.run { machine.state }
- val wrapped = MachineState(0,
- machine as nl.atlarge.opendc.integration.jpa.schema.Machine,
- state.task as nl.atlarge.opendc.integration.jpa.schema.Task?,
- experiment,
- simulation.clock.now,
- state.temperature,
- state.memory,
- state.load
- )
- manager.persist(wrapped)
- }
-
- trace.jobs.asSequence()
- .flatMap { it.tasks.asSequence() }
- .forEach { task ->
- val state = InternalTaskState(0,
- task as nl.atlarge.opendc.integration.jpa.schema.Task,
- experiment,
- simulation.clock.now,
- task.remaining.toInt(),
- 1
- )
- manager.persist(state)
- }
- }
-
- // Run next simulation cycle
- simulation.run(simulation.clock.now + 1)
- }
-
- // Set the experiment state
- manager.transaction {
- experiment.state = ExperimentState.FINISHED
- }
-
- logger.info { "Simulation done" }
- val waiting: Long = tasks.fold(0.toLong()) { acc, task ->
- val finished = task.state as TaskState.Finished
- acc + (finished.previous.at - finished.previous.previous.at)
- } / tasks.size
-
- val execution: Long = tasks.fold(0.toLong()) { acc, task ->
- val finished = task.state as TaskState.Finished
- acc + (finished.at - finished.previous.at)
- } / tasks.size
-
- val turnaround: Long = tasks.fold(0.toLong()) { acc, task ->
- val finished = task.state as TaskState.Finished
- acc + (finished.at - finished.previous.previous.at)
- } / tasks.size
-
- 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
- * `try`-with-resources statement.
- *
- * @throws Exception if this resource cannot be closed
- */
- override fun close() = manager.close()
-}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperimentManager.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperimentManager.kt
deleted file mode 100644
index 1d1e118d..00000000
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperimentManager.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.platform
-
-import nl.atlarge.opendc.integration.jpa.transaction
-import nl.atlarge.opendc.integration.jpa.schema.Experiment as InternalExperiment
-import nl.atlarge.opendc.integration.jpa.schema.ExperimentState
-import javax.persistence.EntityManager
-import javax.persistence.EntityManagerFactory
-
-/**
- * A manager for [Experiment]s received from a JPA database.
- *
- * @property factory The JPA entity manager factory to create [EntityManager]s to retrieve entities from the database
- * from.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-class JpaExperimentManager(private val factory: EntityManagerFactory): AutoCloseable {
- /**
- * The entity manager for this experiment.
- */
- private var manager: EntityManager = factory.createEntityManager()
-
- /**
- * The amount of experiments in the queue. This property makes a call to the database and does therefore not
- * run in O(1) time.
- */
- val size: Int
- get() {
- return manager.createQuery("SELECT COUNT(e.id) FROM experiments e WHERE e.state = :s",
- java.lang.Long::class.java)
- .setParameter("s", ExperimentState.QUEUED)
- .singleResult.toInt()
- }
-
- /**
- * Poll an [Experiment] from the database and claim it.
- *
- * @return The experiment that has been polled from the database or `null` if there are no experiments in the
- * queue.
- */
- fun poll(): JpaExperiment? {
- var result: JpaExperiment? = null
- manager.transaction {
- var experiment: InternalExperiment? = null
- val results = manager.createQuery("SELECT e FROM experiments e WHERE e.state = :s",
- InternalExperiment::class.java)
- .setParameter("s", ExperimentState.QUEUED)
- .setMaxResults(1)
- .resultList
-
-
- if (!results.isEmpty()) {
- experiment = results.first()
- experiment!!.state = ExperimentState.CLAIMED
- }
- result = experiment?.let { JpaExperiment(manager, it) }
- }
- manager = factory.createEntityManager()
- return result
- }
-
- /**
- * Close this resource, relinquishing any underlying resources.
- * This method is invoked automatically on objects managed by the
- * `try`-with-resources statement.*
- *
- * @throws Exception if this resource cannot be closed
- */
- override fun close() = manager.close()
-}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/topology/JpaTopologyFactory.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/topology/JpaTopologyFactory.kt
deleted file mode 100644
index 8def721e..00000000
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/topology/JpaTopologyFactory.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.topology
-
-import nl.atlarge.opendc.integration.jpa.schema.*
-
-/**
- * A [TopologyFactory] that converts a [Section] of an experiment as defined by the API, into a proper [Topology].
- *
- * @property section The section to convert into a topology.
- * @property builder A builder for a topology to use.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-class JpaTopologyFactory(val section: Section, val builder: TopologyBuilder = AdjacencyList.builder()) : TopologyFactory {
- /**
- * Create a [MutableTopology] instance.
- *
- * @return A mutable topology.
- */
- override fun create(): MutableTopology = builder.construct {
- val datacenter = section.datacenter
- add(datacenter)
- datacenter.rooms.forEach { room ->
- add(room)
- connect(datacenter, room, tag = "room")
-
- room.objects.forEach { roomObject(room, it) }
- }
- }
-
- /**
- * Handle the objects in a room.
- *
- * @param obj The obj to handle.
- */
- private fun MutableTopology.roomObject(parent: Room, obj: RoomObject) = when(obj) {
- is Rack -> rack(parent, obj)
- else -> Unit
- }
-
- /**
- * Handle a rack in a room.
- *
- * @param parent The parent of the rack.
- * @param rack The rack to handle.
- */
- private fun MutableTopology.rack(parent: Room, rack: Rack) {
- add(rack)
- connect(parent, rack, tag = "rack")
- rack.machines.forEach { machine ->
- add(machine)
- connect(rack, machine, tag = "machine")
-
- machine.cpus.forEach { cpu ->
- add(cpu)
- connect(machine, cpu, tag = "cpu")
- }
-
- machine.gpus.forEach { gpu ->
- add(gpu)
- connect(machine, gpu, tag = "gpu")
- }
- }
- }
-}
diff --git a/opendc-integration-jpa/core/src/main/resources/jpa/schema.xml b/opendc-integration-jpa/core/src/main/resources/jpa/schema.xml
deleted file mode 100644
index bd6ea7a1..00000000
--- a/opendc-integration-jpa/core/src/main/resources/jpa/schema.xml
+++ /dev/null
@@ -1,324 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ MIT License
- ~
- ~ Copyright (c) 2017 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.
- -->
-<entity-mappings version="2.1"
- xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
-
- <package>nl.atlarge.opendc.integration.jpa.schema</package>
-
- <entity class="Experiment" access="FIELD" name="experiments">
- <convert converter="nl.atlarge.opendc.integration.jpa.converter.SchedulerConverter" attribute-name="scheduler" />
- <attributes>
- <id name="id" />
-
- <basic name="name">
- <column column-definition="text" />
- </basic>
-
- <basic name="state">
- <column column-definition="text" />
- <enumerated>STRING</enumerated>
- </basic>
-
- <basic name="last">
- <column name="last_simulated_tick" column-definition="int(11)" />
- </basic>
-
- <basic name="scheduler">
- <column name="scheduler_name" />
- </basic>
-
- <many-to-one name="trace" target-entity="nl.atlarge.opendc.integration.jpa.schema.Trace">
- <join-column name="trace_id" />
- </many-to-one>
-
- <one-to-one name="path" target-entity="nl.atlarge.opendc.integration.jpa.schema.Path">
- <join-column name="path_id" />
- </one-to-one>
- </attributes>
- </entity>
-
- <entity class="Path" access="FIELD" name="paths">
- <attributes>
- <id name="id" />
-
- <one-to-many name="sections" target-entity="nl.atlarge.opendc.integration.jpa.schema.Section">
- <join-column name="path_id" />
- </one-to-many>
- </attributes>
- </entity>
-
- <entity class="Section" access="FIELD" name="sections">
- <attributes>
- <id name="id" />
-
- <basic name="startTime">
- <column name="start_tick" column-definition="int(11)" />
- </basic>
-
- <many-to-one name="datacenter">
- <join-column name="datacenter_id" />
- </many-to-one>
- </attributes>
- </entity>
-
- <entity class="Trace" access="FIELD" name="traces" cacheable="false">
- <attributes>
- <id name="id" />
- <basic name="name">
- <column column-definition="text" />
- </basic>
- <one-to-many name="jobs" target-entity="nl.atlarge.opendc.integration.jpa.schema.Job">
- <join-column name="trace_id" />
- </one-to-many>
- </attributes>
- </entity>
-
- <entity class="Job" access="FIELD" name="jobs" cacheable="false">
- <attributes>
- <id name="id" />
- <one-to-many name="tasks" target-entity="Task">
- <join-column name="job_id" />
- </one-to-many>
- <transient name="owner" />
- </attributes>
- </entity>
-
- <entity class="Task" access="FIELD" name="tasks" cacheable="false">
- <convert converter="nl.atlarge.opendc.integration.jpa.converter.ParallelizableConverter" attribute-name="parallelizable" />
- <attributes>
- <id name="id" />
- <basic name="flops">
- <column name="total_flop_count" column-definition="int(11)" />
- </basic>
- <basic name="startTime">
- <column name="start_tick" column-definition="int(11)" />
- </basic>
- <basic name="parallelizable">
- <column name="parallelizability" column-definition="text" />
- </basic>
-
- <one-to-one name="dependency" target-entity="Task">
- <join-column name="task_dependency_id" />
- </one-to-one>
- <transient name="dependencies" />
- <transient name="state" />
- <transient name="remaining" />
- <transient name="finished" />
- </attributes>
- </entity>
-
- <entity class="Datacenter" access="FIELD" name="datacenters">
- <attributes>
- <id name="id" />
-
- <one-to-many name="rooms" target-entity="Room">
- <join-column name="datacenter_id" />
- </one-to-many>
- <transient name="scheduler" />
- <transient name="interval" />
- <transient name="initialState" />
- </attributes>
- </entity>
-
- <entity class="Room" access="FIELD" name="rooms">
- <attributes>
- <id name="id" />
- <basic name="name">
- <column column-definition="text" />
- </basic>
- <basic name="type">
- <enumerated>STRING</enumerated>
- </basic>
- <one-to-many name="objects">
- <join-table name="tiles">
- <join-column name="room_id" />
- <inverse-join-column name="object_id" />
- </join-table>
- </one-to-many>
- <transient name="initialState" />
- </attributes>
- </entity>
-
- <entity class="RoomObject" access="FIELD" name="objects">
- <inheritance strategy="JOINED" />
- <discriminator-column name="type" />
- <attributes>
- <id name="id"/>
- </attributes>
- </entity>
-
- <entity class="Rack" access="FIELD" name="racks">
- <discriminator-value>RACK</discriminator-value>
- <attributes>
- <id name="id" />
- <basic name="name">
- <column column-definition="text" />
- </basic>
- <basic name="capacity" />
- <basic name="powerCapacity">
- <column name="power_capacity_w" />
- </basic>
-
- <one-to-many name="machines">
- <join-column name="rack_id" />
- </one-to-many>
- <transient name="initialState" />
- </attributes>
- </entity>
-
- <entity class="Machine" access="FIELD" name="machines">
- <attributes>
- <id name="id" />
- <basic name="position" />
-
- <many-to-many name="cpus">
- <join-table name="machine_cpus">
- <join-column name="machine_id" />
- <inverse-join-column name="cpu_id" />
- </join-table>
- </many-to-many>
-
- <many-to-many name="gpus">
- <join-table name="machine_gpus">
- <join-column name="machine_id" />
- <inverse-join-column name="gpu_id" />
- </join-table>
- </many-to-many>
- <transient name="initialState" />
- </attributes>
- </entity>
-
- <entity class="Cpu" access="FIELD" name="cpus">
- <attributes>
- <id name="id" />
- <basic name="manufacturer">
- <column column-definition="text" />
- </basic>
- <basic name="family">
- <column column-definition="text" />
- </basic>
- <basic name="generation">
- <column column-definition="text" />
- </basic>
- <basic name="model">
- <column column-definition="text" />
- </basic>
- <basic name="clockRate">
- <column name="clock_rate_mhz" />
- </basic>
- <basic name="cores">
- <column name="number_of_cores" />
- </basic>
- <basic name="energyConsumption">
- <column name="energy_consumption_w" />
- </basic>
- <transient name="initialState" />
- </attributes>
- </entity>
-
- <entity class="Gpu" access="FIELD" name="gpus">
- <attributes>
- <id name="id" />
- <basic name="manufacturer">
- <column column-definition="text" />
- </basic>
- <basic name="family">
- <column column-definition="text" />
- </basic>
- <basic name="generation">
- <column column-definition="text" />
- </basic>
- <basic name="model">
- <column column-definition="text" />
- </basic>
- <basic name="clockRate">
- <column name="clock_rate_mhz" />
- </basic>
- <basic name="cores">
- <column name="number_of_cores" />
- </basic>
- <basic name="energyConsumption">
- <column name="energy_consumption_w" />
- </basic>
- <transient name="initialState" />
- </attributes>
- </entity>
-
- <entity class="MachineState" access="FIELD" name="machine_states">
- <attributes>
- <id name="id">
- <generated-value strategy="IDENTITY" />
- </id>
- <basic name="time">
- <column name="tick" column-definition="int(11)" />
- </basic>
- <basic name="temperature">
- <column name="temperature_c" />
- </basic>
- <basic name="memoryUsage">
- <column name="in_use_memory_mb" />
- </basic>
- <basic name="load">
- <column name="load_fraction" />
- </basic>
-
- <many-to-one name="task">
- <join-column name="task_id" />
- </many-to-one>
- <many-to-one name="machine">
- <join-column name="machine_id" />
- </many-to-one>
- <many-to-one name="experiment">
- <join-column name="experiment_id" />
- </many-to-one>
- </attributes>
- </entity>
-
- <entity class="TaskState" access="FIELD" name="task_states">
- <attributes>
- <id name="id">
- <generated-value strategy="IDENTITY" />
- </id>
- <basic name="time">
- <column name="tick" column-definition="int(11)" />
- </basic>
- <basic name="remaining">
- <column name="flops_left" />
- </basic>
- <basic name="cores">
- <column name="cores_used" />
- </basic>
-
- <many-to-one name="task">
- <join-column name="task_id" />
- </many-to-one>
- <many-to-one name="experiment">
- <join-column name="experiment_id" />
- </many-to-one>
- </attributes>
- </entity>
-</entity-mappings>
diff --git a/opendc-integration-jpa/mysql/build.gradle b/opendc-integration-jpa/mysql/build.gradle
deleted file mode 100644
index c1cc6f58..00000000
--- a/opendc-integration-jpa/mysql/build.gradle
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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.
- */
-
-apply plugin: 'java'
-apply plugin: 'application'
-mainClassName = "nl.atlarge.opendc.platform.JpaPlatformRunnerKt"
-
-repositories {
- jcenter()
-}
-
-dependencies {
- compile project(':opendc-integration-jpa:core')
- runtime 'org.slf4j:slf4j-simple:1.7.25'
- runtime 'org.hibernate:hibernate-core:5.2.5.Final'
- runtime 'mysql:mysql-connector-java:5.1.13'
-}
diff --git a/opendc-kernel-omega/build.gradle b/opendc-kernel-omega/build.gradle
new file mode 100644
index 00000000..e02da931
--- /dev/null
+++ b/opendc-kernel-omega/build.gradle
@@ -0,0 +1,88 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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.
+ */
+
+/* Build configuration */
+buildscript {
+ ext.kotlin_version = '1.2.21'
+ ext.dokka_version = '0.9.15'
+
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
+ classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3'
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'kotlin'
+apply plugin: 'org.jetbrains.dokka'
+apply plugin: 'org.junit.platform.gradle.plugin'
+
+compileKotlin {
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+}
+
+compileTestKotlin {
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+}
+
+kotlin {
+ experimental {
+ coroutines 'enable'
+ }
+}
+
+dokka {
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
+}
+
+/* Project configuration */
+group 'com.atlarge.opendc'
+version '1.1'
+
+repositories {
+ jcenter()
+}
+
+dependencies {
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.2"
+ compile project(':opendc-core')
+ compile "io.github.microutils:kotlin-logging:1.4.6"
+
+ testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3"
+ testRuntime "org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3"
+ testCompile "org.junit.platform:junit-platform-launcher:1.0.0-RC3"
+ testCompile "org.slf4j:slf4j-simple:1.7.25"
+}
diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Messages.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Messages.kt
new file mode 100644
index 00000000..d63a53c8
--- /dev/null
+++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Messages.kt
@@ -0,0 +1,30 @@
+package com.atlarge.opendc.omega
+
+import com.atlarge.opendc.simulator.Context
+import com.atlarge.opendc.simulator.Process
+
+/**
+ * An internal message used by the Omega simulation kernel to indicate to a suspended [Process], that it should wake up
+ * and resume execution.
+ *
+ * This message is not guaranteed to work on other simulation kernels and [Context.interrupt] should be preferred to
+ * wake up a process from another entity.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+object Resume
+
+/**
+ * An internal message used by the Omega simulation kernel to indicate to a suspended [Process], that a timeout has been
+ * reached and that it should wake up and resume execution.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+object Timeout
+
+/**
+ * An internal message used by the Omega simulation kernel to launch a process.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+data class Launch<M>(val process: Process<*, M>)
diff --git a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaKernel.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt
index cbc25b63..c0ab9fb4 100644
--- a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaKernel.kt
+++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt
@@ -22,14 +22,11 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.kernel.omega
+package com.atlarge.opendc.omega
-import nl.atlarge.opendc.kernel.Kernel
-import nl.atlarge.opendc.kernel.Process
-import nl.atlarge.opendc.kernel.Simulation
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.MutableTopology
-import nl.atlarge.opendc.topology.Topology
+import com.atlarge.opendc.simulator.Bootstrap
+import com.atlarge.opendc.simulator.kernel.Kernel
+import com.atlarge.opendc.simulator.kernel.Simulation
/**
* The Omega simulation kernel is the reference simulation kernel implementation for the OpenDC Simulator core.
@@ -37,22 +34,14 @@ import nl.atlarge.opendc.topology.Topology
* This simulator implementation is a single-threaded implementation, running simulation kernels synchronously and
* provides a single priority queue for all events (messages, ticks, etc) that occur in the entities.
*
- * By default, [Process]s are resolved as part of the [Topology], meaning each [Entity] in the topology should also
- * implement its simulation behaviour by deriving from the [Process] interface.
- *
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
object OmegaKernel : Kernel {
- /**
- * The name of the kernel.
- */
- override val name: String = "opendc-omega"
-
- /**
- * Create a new [Simulation] of the given [Topology] that is facilitated by this simulation kernel.
- *
- * @param topology The [Topology] to create a [Simulation] of.
- * @return A [Simulation] instance.
- */
- override fun create(topology: MutableTopology): Simulation = OmegaSimulation(this, topology)
+ /**
+ * Create a simulation over the given model facilitated by this simulation kernel.
+ *
+ * @param bootstrap The apply procedure to apply the simulation with.
+ * @return A [Simulation] instance to control the simulation.
+ */
+ override fun <M> create(bootstrap: Bootstrap<M>): Simulation<M> = OmegaSimulation(bootstrap)
}
diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt
new file mode 100644
index 00000000..532a033a
--- /dev/null
+++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt
@@ -0,0 +1,402 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.omega
+
+import com.atlarge.opendc.simulator.*
+import com.atlarge.opendc.simulator.kernel.Simulation
+import mu.KotlinLogging
+import java.util.*
+import kotlin.coroutines.experimental.*
+
+/**
+ * The Omega simulation kernel is the reference simulation kernel implementation for the OpenDC Simulator core.
+ *
+ * This simulator implementation is a single-threaded implementation, running simulation kernels synchronously and
+ * provides a single priority queue for all events (messages, ticks, etc) that occur in the entities.
+ *
+ * @property model The model that is simulated.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+internal class OmegaSimulation<M>(bootstrap: Bootstrap<M>) : Simulation<M>, Bootstrap.Context<M> {
+ /**
+ * The logger instance to use for the simulator.
+ */
+ private val logger = KotlinLogging.logger {}
+
+ /**
+ * The registry of the processes used in the simulation.
+ */
+ private val registry: MutableMap<Entity<*, *>, OmegaContext<*>> = HashMap()
+
+ /**
+ * The message queue.
+ */
+ private val queue: Queue<Envelope> = PriorityQueue(Comparator
+ .comparingLong(Envelope::time)
+ .thenComparingLong(Envelope::id))
+
+ /**
+ * The kernel process instance that handles internal operations during the simulation.
+ */
+ private val process = object : Process<Unit, M> {
+ override val initialState = Unit
+
+ override suspend fun Context<Unit, M>.run() {
+ while(true) {
+ val msg = receive()
+ when (msg) {
+ is Launch<*> ->
+ @Suppress("UNCHECKED_CAST")
+ launch((msg as Launch<M>).process)
+ }
+ }
+ }
+ }
+
+ /**
+ * The context associated with an [Entity].
+ */
+ @Suppress("UNCHECKED_CAST")
+ private val <E : Entity<S, M>, S, M> E.context: OmegaContext<S>?
+ get() = registry[this] as? OmegaContext<S>
+
+ /**
+ * The simulation time.
+ */
+ override var time: Instant = 0
+
+ /**
+ * The model of simulation.
+ */
+ // XXX: the bootstrap requires the properties of this class to be initialised, so changing the order may cause NPEs
+ override var model: M = bootstrap.apply(this)
+
+ /**
+ * The observable state of an [Entity] in simulation, which is provided by the simulation context.
+ */
+ override val <E : Entity<S, *>, S> E.state: S
+ get() = context?.state ?: initialState
+
+ /**
+ * Initialise the simulation instance.
+ */
+ init {
+ // Launch the Omega kernel process
+ launch(process)
+ }
+
+ // Bootstrap Context implementation
+ override fun register(entity: Entity<*, M>): Boolean {
+ if (!registry.containsKey(entity) && entity !is Process) {
+ return false
+ }
+
+ schedule(Launch(entity as Process<*, M>), process)
+ return true
+ }
+
+ override fun deregister(entity: Entity<*, M>): Boolean {
+ val context = entity.context ?: return false
+ context.resume(Unit)
+ return true
+ }
+
+ override fun schedule(message: Any, destination: Entity<*, *>, sender: Entity<*, *>?, delay: Duration) =
+ schedule(prepare(message, destination, sender, delay))
+
+ // Simulation implementation
+ override fun step() {
+ while (true) {
+ val envelope = queue.peek() ?: return
+ val delivery = envelope.time
+
+ if (delivery > time) {
+ // Tick has yet to occur
+ // Jump in time to next event
+ time = delivery
+ break
+ } else if (delivery < time) {
+ // Tick has already occurred
+ logger.warn { "Message processed out of order" }
+ }
+
+ queue.poll()
+
+ // If the sender has canceled the message, we move on to the next message
+ if (envelope.canceled) {
+ continue
+ }
+
+ val context = envelope.destination.context ?: continue
+
+ if (envelope.message !is Interrupt) {
+ context.continuation.resume(envelope)
+ } else {
+ context.continuation.resumeWithException(envelope.message)
+ }
+
+ context.last = time
+ }
+ }
+
+ override fun run() {
+ while (queue.isNotEmpty()) {
+ step()
+ }
+ }
+
+ override fun run(until: Instant) {
+ require(until > 0) { "The given instant must be a non-zero positive number" }
+
+ if (time >= until) {
+ return
+ }
+
+ while (time < until && queue.isNotEmpty()) {
+ step()
+ }
+
+ // Fix clock if step() jumped too far in time to give the impression to the user that simulation stopped at
+ // exactly the tick it gave. This has not effect on the actual simulation results as the next call to run() will
+ // just jump forward again.
+ if (time > until) {
+ time = until
+ }
+ }
+
+ /**
+ * The identifier for the next message to be scheduled.
+ */
+ private var nextId: Long = 0
+
+ /**
+ * A wrapper around a message that has been scheduled for processing.
+ *
+ * @property id The identifier of the message to keep the priority queue stable
+ * @property message The message to wrap.
+ * @property time The point in time to deliver the message.
+ * @property sender The sender of the message.
+ * @property destination The destination of the message.
+ */
+ private data class Envelope(val id: Long,
+ val message: Any,
+ val time: Instant,
+ val sender: Entity<*, *>?,
+ val destination: Entity<*, *>) {
+ /**
+ * A flag to indicate the message has been canceled.
+ */
+ internal var canceled: Boolean = false
+ }
+
+ /**
+ * Schedule the given envelope to be processed by the kernel.
+ *
+ * @param envelope The envelope containing the message to schedule.
+ */
+ private fun schedule(envelope: Envelope) {
+ queue.add(envelope)
+ }
+
+ /**
+ * Prepare a message for scheduling by wrapping it into an envelope.
+ *
+ * @param message The message to send.
+ * @param destination The destination entity that should receive the message.
+ * @param sender The optional sender of the message.
+ * @param delay The time to delay the message.
+ */
+ private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null,
+ delay: Duration): Envelope {
+ require(delay >= 0) { "The amount of time to delay the message must be a positive number" }
+ return Envelope(nextId++, message, time + delay, sender, destination)
+ }
+
+ /**
+ * Launch the given [Process].
+ *
+ * @param process The process to launch.
+ */
+ private fun launch(process: Process<*, M>) {
+ val context = OmegaContext(process).also { registry[process] = it }
+
+ // Bootstrap the process coroutine
+ val block: suspend () -> Unit = { context.start() }
+ block.startCoroutine(context)
+ }
+
+ /**
+ * This internal class provides the default implementation for the [Context] interface for this simulator.
+ */
+ private inner class OmegaContext<S>(val process: Process<S, M>) : Context<S, M>, Continuation<Unit>,
+ AbstractCoroutineContextElement(Context) {
+ /**
+ * The model in which the process exists.
+ */
+ override val model: M
+ get() = this@OmegaSimulation.model
+
+ /**
+ * The current point in simulation time.
+ */
+ override val time: Instant
+ get() = this@OmegaSimulation.time
+
+ /**
+ * The [Entity] associated with this context.
+ */
+ override val self: Entity<S, M>
+ get() = process
+
+ /**
+ * The duration between the current point in simulation time and the last point in simulation time where the
+ * [Context] has executed some work.
+ */
+ override val delta: Duration
+ get() = maxOf(time - last, 0)
+
+ /**
+ * The state of the entity.
+ */
+ override var state: S = process.initialState
+
+ /**
+ * The observable state of an [Entity] within the simulation is provided by the context of the simulation.
+ */
+ override val <T : Entity<S, *>, S> T.state: S
+ get() = context?.state ?: initialState
+
+ /**
+ * The sender of the last received message or `null` in case the process has not received any messages yet.
+ */
+ override var sender: Entity<*, *>? = null
+
+ /**
+ * The [CoroutineContext] for a [Context].
+ */
+ override val context: CoroutineContext = this
+
+ /**
+ * The continuation to resume the execution of the process.
+ */
+ lateinit var continuation: Continuation<Envelope>
+
+ /**
+ * The last point in time the process has done some work.
+ */
+ var last: Instant = -1
+
+ override suspend fun receive(): Any = receiveEnvelope().message
+
+ override suspend fun receive(timeout: Duration): Any? {
+ val send = prepare(Timeout, process, process, timeout).also { schedule(it) }
+
+ try {
+ val received = receiveEnvelope()
+
+ if (received.message != Timeout) {
+ send.canceled = true
+ return received.message
+ }
+
+ return null
+ } finally {
+ send.canceled = true
+ }
+ }
+
+ override suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) =
+ schedule(prepare(msg, this, sender, delay))
+
+ override suspend fun Entity<*, *>.interrupt(interrupt: Interrupt) = send(interrupt)
+
+ override suspend fun hold(duration: Duration) {
+ require(duration >= 0) { "The amount of time to hold must be a positive number" }
+ val envelope = prepare(Resume, process, process, duration).also { schedule(it) }
+
+ try {
+ while (true) {
+ if (receive() == Resume)
+ return
+ }
+ } finally {
+ envelope.canceled = true
+ }
+ }
+
+ override suspend fun hold(duration: Duration, queue: Queue<Any>) {
+ require(duration >= 0) { "The amount of time to hold must be a positive number" }
+ val envelope = prepare(Resume, process, process, duration).also { schedule(it) }
+
+ try {
+ while (true) {
+ val msg = receive()
+ if (msg == Resume)
+ return
+ queue.add(msg)
+ }
+ } finally {
+ envelope.canceled = true
+ }
+ }
+
+ /**
+ * Start the process associated with this context.
+ */
+ internal suspend fun start() = process.run { run() }
+
+ /**
+ * Retrieve and remove and single message from the mailbox of the [Entity] and suspend the [Context] until the
+ * message has been received.
+ *
+ * @return The envelope containing the message.
+ */
+ suspend fun receiveEnvelope() = suspendCoroutine<Envelope> { continuation = it }
+ .also { sender = it.sender }
+
+ // Completion continuation implementation
+ /**
+ * Resume the execution of this continuation with the given value.
+ *
+ * @param value The value to resume with.
+ */
+ override fun resume(value: Unit) {
+ // Deregister process from registry in order to have the GC collect this context
+ registry.remove(process)
+ }
+
+ /**
+ * Resume the execution of this continuation with an exception.
+ *
+ * @param exception The exception to resume with.
+ */
+ override fun resumeWithException(exception: Throwable) {
+ // Deregister process from registry in order to have the GC collect this context:w
+ registry.remove(process)
+
+ logger.error(exception) { "An exception occurred during the execution of a process" }
+ }
+ }
+}
diff --git a/opendc-kernel-omega/src/test/kotlin/com/atlarge/opendc/omega/SmokeTest.kt b/opendc-kernel-omega/src/test/kotlin/com/atlarge/opendc/omega/SmokeTest.kt
new file mode 100644
index 00000000..c47f9a26
--- /dev/null
+++ b/opendc-kernel-omega/src/test/kotlin/com/atlarge/opendc/omega/SmokeTest.kt
@@ -0,0 +1,143 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.omega
+
+import com.atlarge.opendc.simulator.Bootstrap
+import com.atlarge.opendc.simulator.Context
+import com.atlarge.opendc.simulator.Process
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
+
+/**
+ * This test suite checks for smoke when running a large amount of simulations.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+internal class SmokeTest {
+ class EchoProcess : Process<Unit, Unit> {
+ override val initialState = Unit
+ override suspend fun Context<Unit, Unit>.run() {
+ while (true) {
+ val msg = receive()
+ sender?.send(msg)
+ }
+ }
+ }
+
+ /**
+ * Run a large amount of simulations and test if any exceptions occur.
+ */
+ @Test
+ fun smoke() {
+ val n = 1000
+ val messages = 100
+ val bootstrap: Bootstrap<Unit> = Bootstrap.create { ctx ->
+ repeat(n) {
+ EchoProcess().also {
+ ctx.register(it)
+
+ for (i in 1 until messages) {
+ ctx.schedule(i, it, delay = i.toLong())
+ }
+ }
+ }
+ }
+ val simulation = OmegaKernel.create(bootstrap)
+ simulation.run()
+ }
+
+ object NullProcess : Process<Unit, Unit> {
+ override val initialState = Unit
+ override suspend fun Context<Unit, Unit>.run() {}
+ }
+
+ /**
+ * Test if the kernel allows sending messages to [Context] instances that have already stopped.
+ */
+ @Test
+ fun `sending message to process that has gracefully stopped`() {
+ val process = NullProcess
+ val bootstrap: Bootstrap<Unit> = Bootstrap.create { ctx ->
+ process.also {
+ ctx.register(it)
+ ctx.schedule(0, it)
+ }
+ }
+
+ val simulation = OmegaKernel.create(bootstrap)
+ simulation.run()
+ }
+
+ object CrashProcess : Process<Unit, Unit> {
+ override val initialState = Unit
+ override suspend fun Context<Unit, Unit>.run() {
+ TODO("This process should crash")
+ }
+ }
+
+ /**
+ * Test if the kernel allows sending messages to [Context] instances that have crashed.
+ */
+ @Test
+ fun `sending message to process that has crashed`() {
+ val process = CrashProcess
+ val bootstrap: Bootstrap<Unit> = Bootstrap.create { ctx ->
+ process.also {
+ ctx.register(it)
+ ctx.schedule(0, it)
+ }
+ }
+
+ val simulation = OmegaKernel.create(bootstrap)
+ simulation.run()
+ }
+
+ class ModelProcess(private val value: Int) : Process<Boolean, Int> {
+ override val initialState = false
+ override suspend fun Context<Boolean, Int>.run() {
+ assertEquals(value, model)
+ state = true
+ hold(10)
+ }
+ }
+ /**
+ * Test if the kernel allows access to the simulation model object.
+ */
+ @Test
+ fun `access simulation model`() {
+ val value = 1
+ val process = ModelProcess(value)
+ val bootstrap: Bootstrap<Int> = Bootstrap.create { ctx ->
+ ctx.register(process)
+ value
+ }
+
+ val simulation = OmegaKernel.create(bootstrap)
+ simulation.run(5)
+
+ assertTrue(simulation.run { process.state })
+ }
+}
diff --git a/opendc-integration-jpa/core/build.gradle b/opendc-model-odc/core/build.gradle
index ed510560..e423da50 100644
--- a/opendc-integration-jpa/core/build.gradle
+++ b/opendc-model-odc/core/build.gradle
@@ -24,67 +24,66 @@
/* Build configuration */
buildscript {
- ext.kotlin_version = '1.1.4-3'
- ext.dokka_version = '0.9.15'
+ ext.kotlin_version = '1.2.21'
+ ext.dokka_version = '0.9.15'
- repositories {
- mavenCentral()
- jcenter()
- }
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
- classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
- classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-RC3'
- }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
+ classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3'
+ }
}
apply plugin: 'java'
apply plugin: 'kotlin'
-apply plugin: 'kotlin-jpa'
apply plugin: 'org.jetbrains.dokka'
apply plugin: 'org.junit.platform.gradle.plugin'
-
compileKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
compileTestKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
kotlin {
- experimental {
- coroutines 'enable'
- }
+ experimental {
+ coroutines 'enable'
+ }
}
dokka {
- outputFormat = 'html'
- outputDirectory = "$buildDir/javadoc"
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
}
/* Project configuration */
-group 'nl.atlarge.opendc'
-version '1.0'
+group 'com.atlarge.opendc'
+version '1.1'
repositories {
- jcenter()
+ jcenter()
}
dependencies {
- compile project(':opendc-core')
- compile project(':opendc-stdlib')
- compile project(':opendc-omega')
- compile 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final'
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+
+ compile project(':opendc-core')
+ compile project(':opendc-stdlib')
+ compile "io.github.microutils:kotlin-logging:1.4.6"
- testCompile 'org.junit.jupiter:junit-jupiter-api:5.0.0-RC3'
- testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3'
- testCompile 'org.junit.platform:junit-platform-launcher:1.0.0-RC3'
+ testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3"
+ testRuntime "org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3"
+ testCompile "org.junit.platform:junit-platform-launcher:1.0.0-RC3"
+ testCompile "org.slf4j:slf4j-simple:1.7.25"
}
diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/OdcModel.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/OdcModel.kt
new file mode 100644
index 00000000..298a14cf
--- /dev/null
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/OdcModel.kt
@@ -0,0 +1,10 @@
+package com.atlarge.opendc.model.odc
+
+import com.atlarge.opendc.model.topology.MutableTopology
+
+/**
+ * The OpenDC standard simulation model used for datacenter simulations.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface OdcModel : MutableTopology
diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/FifoScheduler.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/FifoScheduler.kt
new file mode 100644
index 00000000..e743586c
--- /dev/null
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/FifoScheduler.kt
@@ -0,0 +1,118 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.platform.scheduler
+
+import com.atlarge.opendc.model.odc.platform.workload.Task
+import com.atlarge.opendc.model.odc.topology.machine.Machine
+import com.atlarge.opendc.simulator.Context
+import java.util.*
+
+/**
+ * A [Scheduler] that distributes work according to the first-in-first-out principle.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+class FifoScheduler : Scheduler {
+ /**
+ * The name of this scheduler.
+ */
+ override val name: String = "FIFO"
+
+ /**
+ * The set of machines the scheduler knows of.
+ */
+ private val machines: MutableSet<Machine> = HashSet()
+
+ /**
+ * The queue of [Task]s that need to be scheduled.
+ */
+ private val queue: Queue<Task> = ArrayDeque()
+
+ /**
+ * (Re)schedule the tasks submitted to the scheduler over the specified set of machines.
+ */
+ override suspend fun <S, M> Context<S, M>.schedule() {
+ if (queue.isEmpty()) {
+ return
+ }
+
+ // The tasks that need to be rescheduled
+ val rescheduled = ArrayDeque<Task>()
+ val iterator = queue.iterator()
+
+ machines
+ .filter { it.state.status != Machine.Status.HALT }
+ .forEach { machine ->
+ while (iterator.hasNext()) {
+ val task = iterator.next()
+
+ // TODO What to do with tasks that are not ready yet to be processed
+ if (!task.ready) {
+ iterator.remove()
+ rescheduled.add(task)
+ continue
+ } else if (task.finished) {
+ iterator.remove()
+ continue
+ }
+
+ machine.send(task)
+ break
+ }
+ }
+
+ // Reschedule all tasks that are not ready yet
+ while (!rescheduled.isEmpty()) {
+ queue.add(rescheduled.poll())
+ }
+ }
+
+ /**
+ * Submit a [Task] to this scheduler.
+ *
+ * @param task The task to submit to the scheduler.
+ */
+ override fun submit(task: Task) {
+ queue.add(task)
+ }
+
+ /**
+ * Register a [Machine] to this scheduler.
+ *
+ * @param machine The machine to register.
+ */
+ override fun register(machine: Machine) {
+ machines.add(machine)
+ }
+
+ /**
+ * Deregister a [Machine] from this scheduler.
+ *
+ * @param machine The machine to deregister.
+ */
+ override fun deregister(machine: Machine) {
+ machines.remove(machine)
+ }
+}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/Scheduler.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt
index 578bef9c..79486ee6 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/Scheduler.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt
@@ -22,12 +22,12 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.platform.scheduler
+package com.atlarge.opendc.model.odc.platform.scheduler
-import nl.atlarge.opendc.kernel.Context
-import nl.atlarge.opendc.platform.workload.Task
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.machine.Machine
+import com.atlarge.opendc.model.odc.platform.workload.Task
+import com.atlarge.opendc.model.odc.topology.machine.Machine
+import com.atlarge.opendc.simulator.Context
+import com.atlarge.opendc.simulator.Entity
/**
* A task scheduler that is coupled to an [Entity] in the topology of the cloud network.
@@ -35,37 +35,37 @@ import nl.atlarge.opendc.topology.machine.Machine
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface Scheduler {
- /**
- * The name of this scheduler.
- */
- val name: String
+ /**
+ * The name of this scheduler.
+ */
+ val name: String
- /**
- * (Re)schedule the tasks submitted to the scheduler over the specified set of machines.
- *
- * This method should be invoked at some interval to allow the scheduler to reschedule existing tasks and schedule
- * new tasks.
- */
- suspend fun <E: Entity<*>> Context<E>.schedule()
+ /**
+ * (Re)schedule the tasks submitted to the scheduler over the specified set of machines.
+ *
+ * This method should be invoked at some interval to allow the scheduler to reschedule existing tasks and schedule
+ * new tasks.
+ */
+ suspend fun <S, M> Context<S, M>.schedule()
- /**
- * Submit a [Task] to this scheduler.
- *
- * @param task The task to submit to the scheduler.
- */
- fun submit(task: Task)
+ /**
+ * Submit a [Task] to this scheduler.
+ *
+ * @param task The task to submit to the scheduler.
+ */
+ fun submit(task: Task)
- /**
- * Register a [Machine] to this scheduler.
- *
- * @param machine The machine to register.
- */
- fun register(machine: Machine)
+ /**
+ * Register a [Machine] to this scheduler.
+ *
+ * @param machine The machine to register.
+ */
+ fun register(machine: Machine)
- /**
- * Deregister a [Machine] from this scheduler.
- *
- * @param machine The machine to deregister.
- */
- fun deregister(machine: Machine)
+ /**
+ * Deregister a [Machine] from this scheduler.
+ *
+ * @param machine The machine to deregister.
+ */
+ fun deregister(machine: Machine)
}
diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/SrtfScheduler.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/SrtfScheduler.kt
new file mode 100644
index 00000000..d3f067df
--- /dev/null
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/SrtfScheduler.kt
@@ -0,0 +1,110 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.platform.scheduler
+
+import com.atlarge.opendc.model.odc.platform.workload.Task
+import com.atlarge.opendc.model.odc.topology.machine.Machine
+import com.atlarge.opendc.simulator.Context
+import java.util.*
+
+/**
+ * A [Scheduler] that distributes work according to the shortest job first policy.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+class SrtfScheduler : Scheduler {
+ /**
+ * The name of this scheduler.
+ */
+ override val name: String = "SRTF"
+
+ /**
+ * The set of machines the scheduler knows of.
+ */
+ private val machines: MutableSet<Machine> = HashSet()
+
+ /**
+ * The set of [Task]s that need to be scheduled.
+ */
+ private val tasks: MutableSet<Task> = HashSet()
+
+ /**
+ * (Re)schedule the tasks submitted to the scheduler over the specified set of machines.
+ */
+ override suspend fun <S, M> Context<S, M>.schedule() {
+ if (tasks.isEmpty()) {
+ return
+ }
+
+ val iterator = tasks.sortedBy { it.remaining }.iterator()
+
+ machines
+ .filter { it.state.status != Machine.Status.HALT }
+ .forEach { machine ->
+ while (iterator.hasNext()) {
+ val task = iterator.next()
+
+ // TODO What to do with tasks that are not ready yet to be processed
+ if (!task.ready) {
+ tasks.add(task)
+ continue
+ } else if (task.finished) {
+ tasks.remove(task)
+ continue
+ }
+
+ machine.send(task)
+ break
+ }
+ }
+ }
+
+ /**
+ * Submit a [Task] to this scheduler.
+ *
+ * @param task The task to submit to the scheduler.
+ */
+ override fun submit(task: Task) {
+ tasks.add(task)
+ }
+
+ /**
+ * Register a [Machine] to this scheduler.
+ *
+ * @param machine The machine to register.
+ */
+ override fun register(machine: Machine) {
+ machines.add(machine)
+ }
+
+ /**
+ * Deregister a [Machine] from this scheduler.
+ *
+ * @param machine The machine to deregister.
+ */
+ override fun deregister(machine: Machine) {
+ machines.remove(machine)
+ }
+}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Job.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt
index df2f2b6a..3e6c6821 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Job.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.platform.workload
+package com.atlarge.opendc.model.odc.platform.workload
/**
* A bag of tasks which are submitted by a [User] to the cloud network.
@@ -30,24 +30,24 @@ package nl.atlarge.opendc.platform.workload
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface Job {
- /**
- * A unique identifier of the job.
- */
- val id: Int
+ /**
+ * A unique identifier of the job.
+ */
+ val id: Int
- /**
- * The owner of this job.
- */
- val owner: User
+ /**
+ * The owner of this job.
+ */
+ val owner: User
- /**
- * The tasks this job consists of.
- */
- val tasks: Set<Task>
+ /**
+ * The tasks this job consists of.
+ */
+ val tasks: Set<Task>
- /**
- * A flag to indicate the job has finished.
- */
- val finished: Boolean
- get() = !tasks.any { !it.finished }
+ /**
+ * A flag to indicate the job has finished.
+ */
+ val finished: Boolean
+ get() = !tasks.any { !it.finished }
}
diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Task.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Task.kt
new file mode 100644
index 00000000..d68cceba
--- /dev/null
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Task.kt
@@ -0,0 +1,92 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.platform.workload
+
+import com.atlarge.opendc.model.odc.topology.machine.Machine
+import com.atlarge.opendc.simulator.Instant
+
+/**
+ * A task that runs as part of a [Job] on a [Machine].
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface Task {
+ /**
+ * The unique identifier of the task.
+ */
+ val id: Int
+
+ /**
+ * The amount of flops for this task.
+ */
+ val flops: Long
+
+ /**
+ * The dependencies of the task.
+ */
+ val dependencies: Set<Task>
+
+ /**
+ * A flag to indicate the task is parallelizable.
+ */
+ val parallelizable: Boolean
+
+ /**
+ * The remaining flops for this task.
+ */
+ val remaining: Long
+
+ /**
+ * The state of the task.
+ */
+ val state: TaskState
+
+ /**
+ * A flag to indicate whether the task is ready to be started.
+ */
+ val ready: Boolean
+ get() = !dependencies.any { !it.finished }
+
+ /**
+ * A flag to indicate whether the task has finished.
+ */
+ val finished: Boolean
+ get() = state is TaskState.Finished
+
+ /**
+ * This method is invoked when a task has arrived at a datacenter.
+ *
+ * @param time The moment in time the task has arrived at the datacenter.
+ */
+ fun arrive(time: Instant)
+
+ /**
+ * Consume the given amount of flops of this task.
+ *
+ * @param time The current moment in time of the consumption.
+ * @param flops The total amount of flops to consume.
+ */
+ fun consume(time: Instant, flops: Long)
+}
diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/TaskState.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/TaskState.kt
new file mode 100644
index 00000000..78963ca3
--- /dev/null
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/TaskState.kt
@@ -0,0 +1,72 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.platform.workload
+
+import com.atlarge.opendc.simulator.Instant
+
+
+/**
+ * This class hierarchy describes the states of a [Task].
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+sealed class TaskState {
+ /**
+ * A state to indicate the task has not yet arrived at the [Datacenter].
+ */
+ object Underway : TaskState()
+
+ /**
+ * A state to indicate the task has arrived at the [Datacenter].
+ *
+ * @property at The moment in time the task has arrived.
+ */
+ data class Queued(val at: Instant) : TaskState()
+
+ /**
+ * A state to indicate the task has started running on a machine.
+ *
+ * @property previous The previous state of the task.
+ * @property at The moment in time the task started.
+ */
+ data class Running(val previous: Queued, val at: Instant) : TaskState()
+
+ /**
+ * A state to indicate the task has finished.
+ *
+ * @property previous The previous state of the task.
+ * @property at The moment in time the task finished.
+ */
+ data class Finished(val previous: Running, val at: Instant) : TaskState()
+
+ /**
+ * A state to indicate the task has failed.
+ *
+ * @property previous The previous state of the task.
+ * @property at The moment in time the task failed.
+ * @property reason The reason of the failure.
+ */
+ data class Failed(val previous: Running, val at: Instant, val reason: String) : TaskState()
+}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Trace.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt
index 6dd2efb8..25bcad83 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Trace.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.platform.workload
+package com.atlarge.opendc.model.odc.platform.workload
/**
* A timestamped sequence of jobs received in a cloud network.
@@ -30,8 +30,8 @@ package nl.atlarge.opendc.platform.workload
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface Trace {
- /**
- * The [Job]s in the trace.
- */
- val jobs: Set<Job>
+ /**
+ * The [Job]s in the trace.
+ */
+ val jobs: Set<Job>
}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/User.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt
index d827fee5..da696d88 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/User.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.platform.workload
+package com.atlarge.opendc.model.odc.platform.workload
/**
* A user of a cloud network that provides [Job]s for the simulation.
@@ -33,13 +33,13 @@ package nl.atlarge.opendc.platform.workload
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface User {
- /**
- * The unique identifier of the user.
- */
- val id: Int
+ /**
+ * The unique identifier of the user.
+ */
+ val id: Int
- /**
- * The name of this user.
- */
- val name: String
+ /**
+ * The name of this user.
+ */
+ val name: String
}
diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Datacenter.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Datacenter.kt
new file mode 100644
index 00000000..7293d9f7
--- /dev/null
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Datacenter.kt
@@ -0,0 +1,107 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.topology.container
+
+import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler
+import com.atlarge.opendc.model.odc.platform.workload.Task
+import com.atlarge.opendc.model.odc.platform.workload.TaskState
+import com.atlarge.opendc.model.odc.topology.machine.Machine
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.model.topology.destinations
+import com.atlarge.opendc.simulator.Context
+import com.atlarge.opendc.simulator.Duration
+import com.atlarge.opendc.simulator.Entity
+import com.atlarge.opendc.simulator.Process
+import mu.KotlinLogging
+import java.util.*
+
+/**
+ * A representation of a facility used to house computer systems and associated components.
+ *
+ * @property scheduler The tasks scheduler the datacenter uses.
+ * @property interval The interval at which task will be (re)scheduled.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface Datacenter : Process<Unit, Topology> {
+ /**
+ * The task scheduler the datacenter uses.
+ */
+ val scheduler: Scheduler
+
+ /**
+ * The interval at which task will be (re)scheduled.
+ */
+ val interval: Duration
+
+ /**
+ * This method is invoked to start the simulation an [Entity] associated with this [Context].
+ *
+ * This method is assumed to be running during a simulation, but should hand back control to the simulator at
+ * some point by suspending the process. This allows other processes to do work in the current tick of the
+ * simulation.
+ * Suspending the process can be achieved by calling suspending method in the context:
+ * - [Context.hold] - Wait for `n` amount of ticks before resuming execution.
+ * - [Context.receive] - Wait for a message to be received in the mailbox of the [Entity] before resuming
+ * execution.
+ *
+ * If this method exits early, before the simulation has finished, the entity is assumed to be shutdown and its
+ * simulation will not run any further.
+ */
+ override suspend fun Context<Unit, Topology>.run() = model.run {
+ val logger = KotlinLogging.logger {}
+
+ // The queue of messages to be processed after a cycle
+ val queue: Queue<Any> = ArrayDeque()
+ // Find all machines in the datacenter
+ val machines = outgoingEdges.destinations<Room>("room").asSequence()
+ .flatMap { it.outgoingEdges.destinations<Rack>("rack").asSequence() }
+ .flatMap { it.outgoingEdges.destinations<Machine>("machine").asSequence() }.toList()
+
+ logger.info { "Initialising datacenter with ${machines.size} machines" }
+
+ // Register all machines to the scheduler
+ machines.forEach(scheduler::register)
+
+ while (true) {
+ // Context all messages in the queue
+ while (queue.isNotEmpty()) {
+ val msg = queue.poll()
+ if (msg is Task) {
+ if (msg.state != TaskState.Underway) {
+ logger.warn { "Received invalid task $msg"}
+ continue
+ }
+ msg.arrive(time)
+ scheduler.submit(msg)
+ }
+ }
+ // (Re)schedule the tasks
+ scheduler.run { schedule() }
+
+ // Sleep a time quantum
+ hold(interval, queue)
+ }
+ }
+}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Rack.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt
index 25429f71..42fdc9cf 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Rack.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt
@@ -22,9 +22,10 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.container
+package com.atlarge.opendc.model.odc.topology.container
-import nl.atlarge.opendc.topology.Entity
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.simulator.Entity
/**
* A type of physical steel and electronic framework that is designed to house servers, networking devices, cables and
@@ -32,4 +33,4 @@ import nl.atlarge.opendc.topology.Entity
*
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface Rack : Entity<Unit>
+interface Rack : Entity<Unit, Topology>
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Room.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt
index 3b338899..5e07b0ce 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Room.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt
@@ -22,13 +22,14 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.container
+package com.atlarge.opendc.model.odc.topology.container
-import nl.atlarge.opendc.topology.Entity
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.simulator.Entity
/**
* A physical room in a datacenter with relationships to the entities within the room.
*
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface Room : Entity<Unit>
+interface Room : Entity<Unit, Topology>
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Cpu.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Cpu.kt
index f97e73e9..58eacdc1 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Cpu.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Cpu.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.machine
+package com.atlarge.opendc.model.odc.topology.machine
/**
* A central processing unit.
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Gpu.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Gpu.kt
index 15c5263f..84afc711 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Gpu.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Gpu.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.machine
+package com.atlarge.opendc.model.odc.topology.machine
/**
* A graphics processing unit.
diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Machine.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Machine.kt
new file mode 100644
index 00000000..642723f5
--- /dev/null
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Machine.kt
@@ -0,0 +1,123 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.topology.machine
+
+import com.atlarge.opendc.model.odc.platform.workload.Task
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.model.topology.destinations
+import com.atlarge.opendc.simulator.Context
+import com.atlarge.opendc.simulator.Duration
+import com.atlarge.opendc.simulator.Process
+import mu.KotlinLogging
+
+/**
+ * A Physical Machine (PM) inside a rack of a datacenter. It has a speed, and can be given a workload on which it will
+ * work until finished or interrupted.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+open class Machine : Process<Machine.State, Topology> {
+ /**
+ * The logger instance to use for the simulator.
+ */
+ private val logger = KotlinLogging.logger {}
+
+ /**
+ * The status of a machine.
+ */
+ enum class Status {
+ HALT, IDLE, RUNNING
+ }
+
+ /**
+ * The shape of the state of a [Machine] entity.
+ *
+ * @property status The status of the machine.
+ * @property task The task assign to the machine.
+ * @property memory The memory usage of the machine (defaults to 50mb for the kernel)
+ * @property load The load on the machine (defaults to 0.0)
+ * @property temperature The temperature of the machine (defaults to 23 degrees Celcius)
+ */
+ data class State(val status: Status,
+ val task: Task? = null,
+ val memory: Int = 50,
+ val load: Double = 0.0,
+ val temperature: Double = 23.0)
+
+ /**
+ * The initial state of a [Machine] entity.
+ */
+ override val initialState = State(Status.HALT)
+
+ /**
+ * Run the simulation kernel for this entity.
+ */
+ override suspend fun Context<State, Topology>.run() = model.run {
+ state = State(Status.IDLE)
+
+ val interval: Duration = 10
+ val cpus = outgoingEdges.destinations<Cpu>("cpu")
+ val speed = cpus.fold(0, { acc, cpu -> acc + cpu.clockRate * cpu.cores })
+
+ // Halt the machine if it has not processing units (see bug #4)
+ if (cpus.isEmpty()) {
+ state = State(Status.HALT)
+ return
+ }
+
+ var task: Task = receiveTask()
+ state = State(Status.RUNNING, task, load = 1.0, memory = state.memory + 50, temperature = 30.0)
+
+ while (true) {
+ if (task.finished) {
+ logger.info { "$id: Task ${task.id} finished. Machine idle at $time" }
+ state = State(Status.IDLE)
+ task = receiveTask()
+ } else {
+ task.consume(time, speed * delta)
+ }
+
+ // Check if we have received a new order in the meantime.
+ val msg = receive(interval)
+ if (msg is Task) {
+ task = msg
+ state = State(Status.RUNNING, task, load = 1.0, memory = state.memory + 50, temperature = 30.0)
+ }
+ }
+ }
+
+ /**
+ * Wait for a [Task] to be received by the [Context] and discard all other messages received in the meantime.
+ *
+ * @return The task that has been received.
+ */
+ private suspend fun Context<State, Topology>.receiveTask(): Task {
+ while (true) {
+ val msg = receive()
+ if (msg is Task)
+ return msg
+ }
+ }
+}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/ProcessingUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt
index abc8608b..e5d30173 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/ProcessingUnit.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt
@@ -22,28 +22,29 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.machine
+package com.atlarge.opendc.model.odc.topology.machine
-import nl.atlarge.opendc.topology.Entity
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.simulator.Entity
/**
* An interface representing a generic processing unit which is placed into a [Machine].
*
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface ProcessingUnit : Entity<Unit> {
- /**
- * The speed of this [ProcessingUnit] per core in MHz.
- */
- val clockRate: Int
+interface ProcessingUnit : Entity<Unit, Topology> {
+ /**
+ * The speed of this [ProcessingUnit] per core in MHz.
+ */
+ val clockRate: Int
- /**
- * The amount of cores within this [ProcessingUnit].
- */
- val cores: Int
+ /**
+ * The amount of cores within this [ProcessingUnit].
+ */
+ val cores: Int
- /**
- * The energy consumption of this [ProcessingUnit] in Watt.
- */
- val energyConsumption: Double
+ /**
+ * The energy consumption of this [ProcessingUnit] in Watt.
+ */
+ val energyConsumption: Double
}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/network/NetworkUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt
index d3a9eefe..5ffc19bf 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/network/NetworkUnit.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt
@@ -22,13 +22,14 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.network
+package com.atlarge.opendc.model.odc.topology.network
-import nl.atlarge.opendc.topology.Entity
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.simulator.Entity
/**
* A generic interface for a network unit in a cloud network.
*
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface NetworkUnit : Entity<Unit>
+interface NetworkUnit : Entity<Unit, Topology>
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/power/PowerUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt
index b9602e55..3e9248c4 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/power/PowerUnit.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt
@@ -22,13 +22,14 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.power
+package com.atlarge.opendc.model.odc.topology.power
-import nl.atlarge.opendc.topology.Entity
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.simulator.Entity
/**
* An [Entity] which provides power for other entities a cloud network to run.
*
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface PowerUnit : Entity<Unit>
+interface PowerUnit : Entity<Unit, Topology>
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/storage/StorageUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt
index f719f152..eb622f2c 100644
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/storage/StorageUnit.kt
+++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt
@@ -22,13 +22,14 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology.storage
+package com.atlarge.opendc.model.odc.topology.storage
-import nl.atlarge.opendc.topology.Entity
+import com.atlarge.opendc.model.topology.Topology
+import com.atlarge.opendc.simulator.Entity
/**
* A generic interface for a storage unit in a cloud network.
*
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface StorageUnit : Entity<Unit>
+interface StorageUnit : Entity<Unit, Topology>
diff --git a/opendc-model-odc/jpa/build.gradle b/opendc-model-odc/jpa/build.gradle
new file mode 100644
index 00000000..191ca787
--- /dev/null
+++ b/opendc-model-odc/jpa/build.gradle
@@ -0,0 +1,91 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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.
+ */
+
+/* Build configuration */
+buildscript {
+ ext.kotlin_version = '1.2.21'
+ ext.dokka_version = '0.9.15'
+
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
+ classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-RC3'
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'kotlin'
+apply plugin: 'kotlin-jpa'
+apply plugin: 'org.jetbrains.dokka'
+apply plugin: 'org.junit.platform.gradle.plugin'
+
+compileKotlin {
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+}
+
+compileTestKotlin {
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+}
+
+kotlin {
+ experimental {
+ coroutines 'enable'
+ }
+}
+
+dokka {
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
+}
+
+/* Project configuration */
+group 'com.atlarge.opendc'
+version '1.1'
+
+repositories {
+ jcenter()
+}
+
+dependencies {
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+
+ compile project(':opendc-core')
+ compile project(':opendc-stdlib')
+ compile project(':opendc-model-odc:core')
+ compile 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final'
+
+ testCompile 'org.junit.jupiter:junit-jupiter-api:5.0.0-RC3'
+ testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3'
+ testCompile 'org.junit.platform:junit-platform-launcher:1.0.0-RC3'
+}
diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaBootstrap.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaBootstrap.kt
new file mode 100644
index 00000000..0a0c792c
--- /dev/null
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaBootstrap.kt
@@ -0,0 +1,51 @@
+package com.atlarge.opendc.model.odc
+
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Experiment
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Task
+import com.atlarge.opendc.model.odc.topology.JpaTopologyFactory
+import com.atlarge.opendc.model.topology.bootstrap
+import com.atlarge.opendc.simulator.Bootstrap
+import mu.KotlinLogging
+
+/**
+ * A [Bootstrap] procedure for experiments retrieved from a JPA data store.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+class JpaBootstrap(val experiment: Experiment) : Bootstrap<JpaModel> {
+ /**
+ * The logging instance.
+ */
+ private val logger = KotlinLogging.logger {}
+
+ /**
+ * Bootstrap a model `M` for a kernel in the given context.
+ *
+ * @param context The context to apply to model in.
+ * @return The initialised model for the simulation.
+ */
+ override fun apply(context: Bootstrap.Context<JpaModel>): JpaModel {
+ val section = experiment.path.sections.first()
+
+ // TODO We should not modify parts of the experiment in a apply as the apply should be reproducible.
+ // Important: initialise the scheduler of the datacenter
+ section.datacenter.scheduler = experiment.scheduler
+
+ val topology = JpaTopologyFactory(section)
+ .create()
+ .bootstrap()
+ .apply(context)
+ val trace = experiment.trace
+ val tasks = trace.jobs.flatMap { it.tasks }
+
+ // Schedule all messages in the trace
+ tasks.forEach { task ->
+ if (task is Task) {
+ logger.info { "Scheduling $task" }
+ context.schedule(task, section.datacenter, delay = task.startTime)
+ }
+ }
+
+ return JpaModel(experiment, topology)
+ }
+}
diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaModel.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaModel.kt
new file mode 100644
index 00000000..44c1fb69
--- /dev/null
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaModel.kt
@@ -0,0 +1,14 @@
+package com.atlarge.opendc.model.odc
+
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Experiment
+import com.atlarge.opendc.model.topology.MutableTopology
+
+/**
+ * Implementation of the [OdcModel] using a JPA backend.
+ *
+ * @property experiment The experiment that is simulated.
+ * @property topology The topology the simulation runs on.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+data class JpaModel(val experiment: Experiment, val topology: MutableTopology) : OdcModel, MutableTopology by topology
+
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/Jpa.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt
index cbbe280a..cb3181f8 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/Jpa.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa
+package com.atlarge.opendc.model.odc.integration.jpa
import javax.persistence.EntityManager
@@ -32,7 +32,7 @@ import javax.persistence.EntityManager
* @param block The block to execute in the transaction.
*/
inline fun EntityManager.transaction(block: () -> Unit) {
- transaction.begin()
- block()
- transaction.commit()
+ transaction.begin()
+ block()
+ transaction.commit()
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/ParallelizableConverter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt
index 11d5836e..e9635b2e 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/ParallelizableConverter.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.converter
+package com.atlarge.opendc.model.odc.integration.jpa.converter
import javax.persistence.AttributeConverter
@@ -33,30 +33,30 @@ import javax.persistence.AttributeConverter
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
class ParallelizableConverter : AttributeConverter<Boolean, String> {
- /**
- * Converts the data stored in the database column into the
- * value to be stored in the entity attribute.
- * Note that it is the responsibility of the converter writer to
- * specify the correct dbData type for the corresponding column
- * for use by the JDBC driver: i.e., persistence providers are
- * not expected to do such type conversion.
- *
- * @param dbData the data from the database column to be converted
- * @return the converted value to be stored in the entity attribute
- */
- override fun convertToEntityAttribute(dbData: String?): Boolean = when(dbData?.toUpperCase()) {
- "SEQUENTIAL" -> false
- "PARALLEL" -> true
- else -> false
- }
+ /**
+ * Converts the data stored in the database column into the
+ * value to be stored in the entity attribute.
+ * Note that it is the responsibility of the converter writer to
+ * specify the correct dbData type for the corresponding column
+ * for use by the JDBC driver: i.e., persistence providers are
+ * not expected to do such type conversion.
+ *
+ * @param dbData the data from the database column to be converted
+ * @return the converted value to be stored in the entity attribute
+ */
+ override fun convertToEntityAttribute(dbData: String?): Boolean = when (dbData?.toUpperCase()) {
+ "SEQUENTIAL" -> false
+ "PARALLEL" -> true
+ else -> false
+ }
- /**
- * Converts the value stored in the entity attribute into the
- * data representation to be stored in the database.
- *
- * @param attribute the entity attribute value to be converted
- * @return the converted data to be stored in the database column
- */
- override fun convertToDatabaseColumn(attribute: Boolean?): String =
- if (attribute == true) "PARALLEL" else "SEQUENTIAL"
+ /**
+ * Converts the value stored in the entity attribute into the
+ * data representation to be stored in the database.
+ *
+ * @param attribute the entity attribute value to be converted
+ * @return the converted data to be stored in the database column
+ */
+ override fun convertToDatabaseColumn(attribute: Boolean?): String =
+ if (attribute == true) "PARALLEL" else "SEQUENTIAL"
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/SchedulerConverter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt
index 95027440..15f6a905 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/SchedulerConverter.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt
@@ -22,11 +22,11 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.converter
+package com.atlarge.opendc.model.odc.integration.jpa.converter
-import nl.atlarge.opendc.platform.scheduler.FifoScheduler
-import nl.atlarge.opendc.platform.scheduler.Scheduler
-import nl.atlarge.opendc.platform.scheduler.SrtfScheduler
+import com.atlarge.opendc.model.odc.platform.scheduler.FifoScheduler
+import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler
+import com.atlarge.opendc.model.odc.platform.scheduler.SrtfScheduler
import javax.persistence.AttributeConverter
/**
@@ -38,29 +38,29 @@ import javax.persistence.AttributeConverter
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
class SchedulerConverter : AttributeConverter<Scheduler, String> {
- /**
- * Converts the data stored in the database column into the
- * value to be stored in the entity attribute.
- * Note that it is the responsibility of the converter writer to
- * specify the correct dbData type for the corresponding column
- * for use by the JDBC driver: i.e., persistence providers are
- * not expected to do such type conversion.
- *
- * @param dbData the data from the database column to be converted
- * @return the converted value to be stored in the entity attribute
- */
- override fun convertToEntityAttribute(dbData: String?): Scheduler = when(dbData?.toUpperCase()) {
- "SRTF" -> SrtfScheduler()
- else -> FifoScheduler()
- }
+ /**
+ * Converts the data stored in the database column into the
+ * value to be stored in the entity attribute.
+ * Note that it is the responsibility of the converter writer to
+ * specify the correct dbData type for the corresponding column
+ * for use by the JDBC driver: i.e., persistence providers are
+ * not expected to do such type conversion.
+ *
+ * @param dbData the data from the database column to be converted
+ * @return the converted value to be stored in the entity attribute
+ */
+ override fun convertToEntityAttribute(dbData: String?): Scheduler = when (dbData?.toUpperCase()) {
+ "SRTF" -> SrtfScheduler()
+ else -> FifoScheduler()
+ }
- /**
- * Converts the value stored in the entity attribute into the
- * data representation to be stored in the database.
- *
- * @param attribute the entity attribute value to be converted
- * @return the converted data to be stored in the database column
- */
- override fun convertToDatabaseColumn(attribute: Scheduler?): String =
- attribute?.name?.toUpperCase() ?: "FIFO"
+ /**
+ * Converts the value stored in the entity attribute into the
+ * data representation to be stored in the database.
+ *
+ * @param attribute the entity attribute value to be converted
+ * @return the converted data to be stored in the database column
+ */
+ override fun convertToDatabaseColumn(attribute: Scheduler?): String =
+ attribute?.name?.toUpperCase() ?: "FIFO"
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Cpu.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt
index b775eb6e..11553477 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Cpu.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.topology.machine.Cpu
+import com.atlarge.opendc.model.odc.topology.machine.Cpu
import javax.persistence.Entity
/**
@@ -42,17 +42,17 @@ import javax.persistence.Entity
*/
@Entity
data class Cpu(
- val id: Int,
- val manufacturer: String,
- val family: String,
- val generation: String,
- val model: String,
- override val clockRate: Int,
- override val cores: Int,
- override val energyConsumption: Double
+ val id: Int,
+ val manufacturer: String,
+ val family: String,
+ val generation: String,
+ val model: String,
+ override val clockRate: Int,
+ override val cores: Int,
+ override val energyConsumption: Double
) : Cpu {
- /**
- * The initial state of the entity.
- */
- override val initialState = Unit
+ /**
+ * The initial state of the entity.
+ */
+ override val initialState = Unit
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Datacenter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt
index 1e6eaa2b..e65eef8b 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Datacenter.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt
@@ -22,11 +22,11 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.kernel.time.Duration
-import nl.atlarge.opendc.platform.scheduler.Scheduler
-import nl.atlarge.opendc.topology.container.Datacenter
+import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler
+import com.atlarge.opendc.model.odc.topology.container.Datacenter
+import com.atlarge.opendc.simulator.Duration
import javax.persistence.Entity
/**
@@ -38,29 +38,29 @@ import javax.persistence.Entity
*/
@Entity
data class Datacenter(
- val id: Int,
- val rooms: Set<Room>
-): Datacenter {
- /**
- * Construct a datacenter. We need this useless constructor in order for Kotlin correctly initialise the
- * constant fields of the class.
- */
- private constructor() : this(-1, emptySet())
+ val id: Int,
+ val rooms: Set<Room>
+) : Datacenter {
+ /**
+ * Construct a datacenter. We need this useless constructor in order for Kotlin correctly initialise the
+ * constant fields of the class.
+ */
+ private constructor() : this(-1, emptySet())
- /**
- * The task scheduler the datacenter uses.
- */
- override lateinit var scheduler: Scheduler
- internal set
+ /**
+ * The task scheduler the datacenter uses.
+ */
+ override lateinit var scheduler: Scheduler
+ internal set
- /**
- * The interval at which task will be (re)scheduled.
- * We set this to a fixed constant since the database provides no way of configuring this.
- */
- override val interval: Duration = 10
+ /**
+ * The interval at which task will be (re)scheduled.
+ * We set this to a fixed constant since the database provides no way of configuring this.
+ */
+ override val interval: Duration = 10
- /**
- * The initial state of the datacenter.
- */
- override val initialState = Unit
+ /**
+ * The initial state of the datacenter.
+ */
+ override val initialState = Unit
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Experiment.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt
index 0b352cb4..ce489b1f 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Experiment.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt
@@ -22,12 +22,10 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.kernel.time.Instant
-import nl.atlarge.opendc.platform.Experiment
-import nl.atlarge.opendc.platform.scheduler.Scheduler
-import nl.atlarge.opendc.platform.workload.Trace
+import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler
+import com.atlarge.opendc.simulator.Instant
import javax.persistence.Entity
/**
@@ -42,19 +40,19 @@ import javax.persistence.Entity
*/
@Entity
data class Experiment(
- val id: Int,
- val name: String,
- val scheduler: Scheduler,
- val trace: Trace,
- val path: Path
+ val id: Int,
+ val name: String,
+ val scheduler: Scheduler,
+ val trace: Trace,
+ val path: Path
) {
- /**
- * The state of the experiment.
- */
- var state: ExperimentState = ExperimentState.QUEUED
+ /**
+ * The state of the experiment.
+ */
+ var state: ExperimentState = ExperimentState.QUEUED
- /**
- * The last tick that has been simulated.
- */
- var last: Instant = 0
+ /**
+ * The last tick that has been simulated.
+ */
+ var last: Instant = 0
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/ExperimentState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt
index 96fc112c..fecfe060 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/ExperimentState.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
/**
* Enumerations of the states an [Experiment] can assume.
@@ -30,24 +30,24 @@ package nl.atlarge.opendc.integration.jpa.schema
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
enum class ExperimentState {
- /**
- * This state indicates the experiment has been queued for simulation, but has not yet started.
- */
- QUEUED,
+ /**
+ * This state indicates the experiment has been queued for simulation, but has not yet started.
+ */
+ QUEUED,
- /**
- * This state indicates the experiment has been claimed by a simulator for simulation, but
- * not yet started.
- */
- CLAIMED,
+ /**
+ * This state indicates the experiment has been claimed by a simulator for simulation, but
+ * not yet started.
+ */
+ CLAIMED,
- /**
- * This state indicates the experiment is currently in simulation.
- */
- SIMULATING,
+ /**
+ * This state indicates the experiment is currently in simulation.
+ */
+ SIMULATING,
- /**
- * This state indicates the experiment has finished simulating.
- */
- FINISHED,
+ /**
+ * This state indicates the experiment has finished simulating.
+ */
+ FINISHED,
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Gpu.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt
index 94625242..c04262cc 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Gpu.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.topology.machine.Gpu
+import com.atlarge.opendc.model.odc.topology.machine.Gpu
import javax.persistence.Entity
/**
@@ -42,17 +42,17 @@ import javax.persistence.Entity
*/
@Entity
data class Gpu(
- val id: Int,
- val manufacturer: String,
- val family: String,
- val generation: String,
- val model: String,
- override val clockRate: Int,
- override val cores: Int,
- override val energyConsumption: Double
+ val id: Int,
+ val manufacturer: String,
+ val family: String,
+ val generation: String,
+ val model: String,
+ override val clockRate: Int,
+ override val cores: Int,
+ override val energyConsumption: Double
) : Gpu {
- /**
- * The initial state of the entity.
- */
- override val initialState = Unit
+ /**
+ * The initial state of the entity.
+ */
+ override val initialState = Unit
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Job.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt
index 394cf478..67ffba32 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Job.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt
@@ -22,12 +22,11 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.platform.workload.Job
-import nl.atlarge.opendc.platform.workload.Task
-import nl.atlarge.opendc.platform.workload.User
-import javax.persistence.*
+import com.atlarge.opendc.model.odc.platform.workload.Job
+import com.atlarge.opendc.model.odc.platform.workload.User
+import javax.persistence.Entity
/**
* A [Job] backed by the JPA API and an underlying database connection.
@@ -38,22 +37,22 @@ import javax.persistence.*
*/
@Entity
data class Job(
- override val id: Int,
- override val tasks: Set<Task>
+ override val id: Int,
+ override val tasks: Set<Task>
) : Job {
- /**
- * The owner of the job, which is a singleton, since the database has no
- * concept of ownership yet.
- */
- override val owner: User = object : User {
- /**
+ /**
+ * The owner of the job, which is a singleton, since the database has no
+ * concept of ownership yet.
+ */
+ override val owner: User = object : User {
+ /**
* The unique identifier of the user.
*/
- override val id: Int = 0
+ override val id: Int = 0
- /**
+ /**
* The name of this user.
*/
- override val name: String = "admin"
- }
+ override val name: String = "admin"
+ }
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Machine.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt
index 4071b342..925ab1d2 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Machine.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.topology.machine.Machine
+import com.atlarge.opendc.model.odc.topology.machine.Machine
import javax.persistence.Entity
/**
@@ -38,8 +38,8 @@ import javax.persistence.Entity
*/
@Entity
data class Machine(
- val id: Int,
- val position: Int,
- val cpus: Set<Cpu>,
- val gpus: Set<Gpu>
-): Machine()
+ val id: Int,
+ val position: Int,
+ val cpus: Set<Cpu>,
+ val gpus: Set<Gpu>
+) : Machine()
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/MachineState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt
index 23efe888..f3149adb 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/MachineState.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.kernel.time.Instant
+import com.atlarge.opendc.simulator.Instant
import javax.persistence.Entity
/**
@@ -42,12 +42,12 @@ import javax.persistence.Entity
*/
@Entity
data class MachineState(
- val id: Int,
- val machine: Machine,
- val task: Task?,
- val experiment: Experiment,
- val time: Instant,
- val temperature: Double,
- val memoryUsage: Int,
- val load: Double
+ val id: Int,
+ val machine: Machine,
+ val task: Task?,
+ val experiment: Experiment,
+ val time: Instant,
+ val temperature: Double,
+ val memoryUsage: Int,
+ val load: Double
)
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Path.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt
index ccf3b6e8..a6e915f3 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Path.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
import javax.persistence.Entity
@@ -35,6 +35,6 @@ import javax.persistence.Entity
*/
@Entity
open class Path(
- val id: Int,
- val sections: List<Section>
+ val id: Int,
+ val sections: List<Section>
)
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Rack.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt
index 2d2099a2..dd48480d 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Rack.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.topology.container.Rack
+import com.atlarge.opendc.model.odc.topology.container.Rack
import javax.persistence.Entity
/**
@@ -39,14 +39,14 @@ import javax.persistence.Entity
*/
@Entity
class Rack(
- id: Int,
- val name: String,
- val capacity: Int,
- val powerCapacity: Int,
- val machines: List<Machine>
-): RoomObject(id), Rack {
- /**
- * The initial state of the entity.
- */
- override val initialState = Unit
+ id: Int,
+ val name: String,
+ val capacity: Int,
+ val powerCapacity: Int,
+ val machines: List<Machine>
+) : RoomObject(id), Rack {
+ /**
+ * The initial state of the entity.
+ */
+ override val initialState = Unit
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Room.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt
index f3b7ae06..1a1c721f 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Room.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.topology.container.Room
+import com.atlarge.opendc.model.odc.topology.container.Room
import javax.persistence.Entity
/**
@@ -38,13 +38,13 @@ import javax.persistence.Entity
*/
@Entity
data class Room(
- val id: Int,
- val name: String,
- val type: RoomType,
- val objects: Set<RoomObject>
-): Room {
- /**
- * The initial state of the entity.
- */
- override val initialState = Unit
+ val id: Int,
+ val name: String,
+ val type: RoomType,
+ val objects: Set<RoomObject>
+) : Room {
+ /**
+ * The initial state of the entity.
+ */
+ override val initialState = Unit
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomObject.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomObject.kt
index 0e9fb84f..49db076c 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomObject.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomObject.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
import javax.persistence.Entity
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomType.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt
index 5e138947..ed0f89d3 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomType.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
/**
* This enumeration defines the room types available in the OpenDC frontend.
@@ -30,5 +30,5 @@ package nl.atlarge.opendc.integration.jpa.schema
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
enum class RoomType {
- COOLING, HALLWAY, OFFICE, POWER, SERVER
+ COOLING, HALLWAY, OFFICE, POWER, SERVER
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Section.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt
index e3b8c350..c6de2e50 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Section.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.kernel.time.Instant
+import com.atlarge.opendc.simulator.Instant
import javax.persistence.Entity
/**
@@ -39,7 +39,7 @@ import javax.persistence.Entity
*/
@Entity
data class Section(
- val id: Int,
- val datacenter: Datacenter,
- val startTime: Instant
+ val id: Int,
+ val datacenter: Datacenter,
+ val startTime: Instant
)
diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Task.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Task.kt
new file mode 100644
index 00000000..4a296255
--- /dev/null
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Task.kt
@@ -0,0 +1,118 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.integration.jpa.schema
+
+import com.atlarge.opendc.model.odc.platform.workload.Task
+import com.atlarge.opendc.model.odc.platform.workload.TaskState
+import com.atlarge.opendc.simulator.Instant
+import javax.persistence.Entity
+import javax.persistence.PostLoad
+
+/**
+ * A [Task] backed by the JPA API and an underlying database connection.
+ *
+ * @property id The unique identifier of the job.
+ * @property flops The total amount of flops for the task.
+ * @property dependency A dependency on another task.
+ * @property parallelizable A flag to indicate the task is parallelizable.
+ * @property startTime The start time in the simulation.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+@Entity
+data class Task(
+ override val id: Int,
+ override val flops: Long,
+ private val dependency: Task?,
+ override val parallelizable: Boolean,
+ val startTime: Instant
+) : Task {
+ /**
+ * The dependencies of the task.
+ */
+ override lateinit var dependencies: Set<Task>
+ private set
+
+ /**
+ * The remaining flops for this task.
+ */
+ override var remaining: Long = 0
+ private set
+
+ /**
+ * A flag to indicate whether the task has finished.
+ */
+ override var finished: Boolean = false
+ private set
+
+ /**
+ * The state of the task.
+ */
+ override lateinit var state: TaskState
+ private set
+
+ /**
+ * This method initialises the task object after it has been created by the JPA implementation. We use this
+ * initialisation method because JPA implementations only call the default constructor
+ */
+ @PostLoad
+ internal fun init() {
+ remaining = flops
+ dependencies = dependency?.let(::setOf) ?: emptySet()
+ state = TaskState.Underway
+ }
+
+ /**
+ * This method is invoked when a task has arrived at a datacenter.
+ *
+ * @param time The moment in time the task has arrived at the datacenter.
+ */
+ override fun arrive(time: Instant) {
+ if (state !is TaskState.Underway) {
+ throw IllegalStateException("The task has already been submitted to a datacenter")
+ }
+ remaining = flops
+ state = TaskState.Queued(time)
+ }
+
+ /**
+ * Consume the given amount of flops of this task.
+ *
+ * @param time The current moment in time of the consumption.
+ * @param flops The total amount of flops to consume.
+ */
+ override fun consume(time: Instant, flops: Long) {
+ if (state is TaskState.Queued) {
+ state = TaskState.Running(state as TaskState.Queued, time)
+ } else if (finished) {
+ return
+ }
+ remaining -= flops
+ if (remaining <= 0) {
+ remaining = 0
+ finished = true
+ state = TaskState.Finished(state as TaskState.Running, time)
+ }
+ }
+}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/TaskState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt
index 14441752..6ab43b93 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/TaskState.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt
@@ -22,9 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.kernel.time.Instant
+import com.atlarge.opendc.simulator.Instant
import javax.persistence.Entity
/**
@@ -40,10 +40,10 @@ import javax.persistence.Entity
*/
@Entity
data class TaskState(
- val id: Int,
- val task: Task,
- val experiment: Experiment,
- val time: Instant,
- val remaining: Int,
- val cores: Int
+ val id: Int,
+ val task: Task,
+ val experiment: Experiment,
+ val time: Instant,
+ val remaining: Int,
+ val cores: Int
)
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Trace.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt
index cd3d9348..e2ed78a2 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Trace.kt
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt
@@ -22,10 +22,10 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.integration.jpa.schema
+package com.atlarge.opendc.model.odc.integration.jpa.schema
-import nl.atlarge.opendc.platform.workload.Job
-import nl.atlarge.opendc.platform.workload.Trace
+import com.atlarge.opendc.model.odc.platform.workload.Job
+import com.atlarge.opendc.model.odc.platform.workload.Trace
import javax.persistence.Entity
/**
@@ -38,7 +38,7 @@ import javax.persistence.Entity
*/
@Entity
data class Trace(
- val id: Int,
- val name: String,
- override val jobs: Set<Job>
+ val id: Int,
+ val name: String,
+ override val jobs: Set<Job>
) : Trace
diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperiment.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperiment.kt
new file mode 100644
index 00000000..4e88b3d4
--- /dev/null
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperiment.kt
@@ -0,0 +1,178 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.platform
+
+import com.atlarge.opendc.model.odc.JpaBootstrap
+import com.atlarge.opendc.model.odc.integration.jpa.schema.ExperimentState
+import com.atlarge.opendc.model.odc.integration.jpa.schema.MachineState
+import com.atlarge.opendc.model.odc.integration.jpa.transaction
+import com.atlarge.opendc.model.odc.platform.workload.TaskState
+import com.atlarge.opendc.model.odc.topology.container.Rack
+import com.atlarge.opendc.model.odc.topology.container.Room
+import com.atlarge.opendc.model.odc.topology.machine.Machine
+import com.atlarge.opendc.model.topology.destinations
+import com.atlarge.opendc.simulator.Duration
+import com.atlarge.opendc.simulator.kernel.Kernel
+import com.atlarge.opendc.simulator.platform.Experiment
+import mu.KotlinLogging
+import java.io.Closeable
+import javax.persistence.EntityManager
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Experiment as InternalExperiment
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Task as InternalTask
+import com.atlarge.opendc.model.odc.integration.jpa.schema.TaskState as InternalTaskState
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Trace as InternalTrace
+
+/**
+ * An [Experiment] backed by the JPA API and an underlying database connection.
+ *
+ * @property manager The entity manager for the database connection.
+ * @property experiment The internal experiment definition to use.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+class JpaExperiment(private val manager: EntityManager,
+ private val experiment: InternalExperiment) : Experiment<Unit>, Closeable {
+ /**
+ * The logging instance.
+ */
+ private val logger = KotlinLogging.logger {}
+
+ /**
+ * Run the experiment using the specified simulation kernel implementation.
+ *
+ * @param factory The simulation kernel implementation to use.
+ * @param timeout The maximum duration of the experiment before returning to the caller.
+ * @return The result of the experiment or `null`.
+ */
+ override fun run(factory: Kernel, timeout: Duration): Unit? {
+ if (experiment.state != ExperimentState.CLAIMED) {
+ throw IllegalStateException("The experiment is in illegal state ${experiment.state}")
+ }
+
+ // Set the simulation state
+ manager.transaction {
+ experiment.state = ExperimentState.SIMULATING
+ }
+
+ val bootstrap = JpaBootstrap(experiment)
+ val simulation = factory.create(bootstrap)
+ val topology = simulation.model
+
+ val section = experiment.path.sections.first()
+ val trace = experiment.trace
+ val tasks = trace.jobs.flatMap { it.tasks }
+
+ // Find all machines in the datacenter
+ val machines = topology.run {
+ section.datacenter.outgoingEdges.destinations<Room>("room").asSequence()
+ .flatMap { it.outgoingEdges.destinations<Rack>("rack").asSequence() }
+ .flatMap { it.outgoingEdges.destinations<Machine>("machine").asSequence() }.toList()
+ }
+
+ logger.info { "Starting simulation" }
+
+ while (trace.jobs.any { !it.finished }) {
+ // If we have reached a timeout, return
+ if (simulation.time >= timeout)
+ return null
+
+ // Collect data of simulation cycle
+ manager.transaction {
+ experiment.last = simulation.time
+
+ machines.forEach { machine ->
+ val state = simulation.run { machine.state }
+ val wrapped = MachineState(0,
+ machine as com.atlarge.opendc.model.odc.integration.jpa.schema.Machine,
+ state.task as com.atlarge.opendc.model.odc.integration.jpa.schema.Task?,
+ experiment,
+ simulation.time,
+ state.temperature,
+ state.memory,
+ state.load
+ )
+ manager.persist(wrapped)
+ }
+
+ tasks.forEach { task ->
+ val state = InternalTaskState(0,
+ task as com.atlarge.opendc.model.odc.integration.jpa.schema.Task,
+ experiment,
+ simulation.time,
+ task.remaining.toInt(),
+ 1
+ )
+ manager.persist(state)
+ }
+ }
+
+ // Run next simulation cycle
+ simulation.step()
+ }
+
+ // Set the experiment state
+ manager.transaction {
+ experiment.state = ExperimentState.FINISHED
+ }
+
+ logger.info { "Simulation done" }
+ val waiting: Long = tasks.fold(0.toLong()) { acc, task ->
+ val finished = task.state as TaskState.Finished
+ acc + (finished.previous.at - finished.previous.previous.at)
+ } / tasks.size
+
+ val execution: Long = tasks.fold(0.toLong()) { acc, task ->
+ val finished = task.state as TaskState.Finished
+ acc + (finished.at - finished.previous.at)
+ } / tasks.size
+
+ val turnaround: Long = tasks.fold(0.toLong()) { acc, task ->
+ val finished = task.state as TaskState.Finished
+ acc + (finished.at - finished.previous.previous.at)
+ } / tasks.size
+
+ 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 implementation.
+ *
+ * @param factory The factory to create the simulation kernel with.
+ * @throws IllegalStateException if the simulation is already running or finished.
+ */
+ override fun run(factory: Kernel) = run(factory, -1)!!
+
+ /**
+ * Closes this resource, relinquishing any underlying resources.
+ * This method is invoked automatically on objects managed by the
+ * `try`-with-resources statement.
+ *
+ * @throws Exception if this resource cannot be closed
+ */
+ override fun close() = manager.close()
+}
diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperimentManager.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperimentManager.kt
new file mode 100644
index 00000000..5dbb9a8b
--- /dev/null
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperimentManager.kt
@@ -0,0 +1,93 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.platform
+
+import com.atlarge.opendc.model.odc.integration.jpa.schema.ExperimentState
+import com.atlarge.opendc.model.odc.integration.jpa.transaction
+import com.atlarge.opendc.simulator.platform.Experiment
+import javax.persistence.EntityManager
+import javax.persistence.EntityManagerFactory
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Experiment as InternalExperiment
+
+/**
+ * A manager for [Experiment]s received from a JPA database.
+ *
+ * @property factory The JPA entity manager factory to create [EntityManager]s to retrieve entities from the database
+ * from.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+class JpaExperimentManager(private val factory: EntityManagerFactory) : AutoCloseable {
+ /**
+ * The entity manager for this experiment.
+ */
+ private var manager: EntityManager = factory.createEntityManager()
+
+ /**
+ * The amount of experiments in the queue. This property is not guaranteed to run in constant time.
+ */
+ val size: Int
+ get() {
+ return manager.createQuery("SELECT COUNT(e.id) FROM experiments e WHERE e.state = :s",
+ java.lang.Long::class.java)
+ .setParameter("s", ExperimentState.QUEUED)
+ .singleResult.toInt()
+ }
+
+ /**
+ * Poll an [Experiment] from the database and claim it.
+ *
+ * @return The experiment that has been polled from the database or `null` if there are no experiments in the
+ * queue.
+ */
+ fun poll(): JpaExperiment? {
+ var result: JpaExperiment? = null
+ manager.transaction {
+ var experiment: InternalExperiment? = null
+ val results = manager.createQuery("SELECT e FROM experiments e WHERE e.state = :s",
+ InternalExperiment::class.java)
+ .setParameter("s", ExperimentState.QUEUED)
+ .setMaxResults(1)
+ .resultList
+
+
+ if (!results.isEmpty()) {
+ experiment = results.first()
+ experiment!!.state = ExperimentState.CLAIMED
+ }
+ result = experiment?.let { JpaExperiment(manager, it) }
+ }
+ manager = factory.createEntityManager()
+ return result
+ }
+
+ /**
+ * Close this resource, relinquishing any underlying resources.
+ * This method is invoked automatically on objects managed by the
+ * `try`-with-resources statement.*
+ *
+ * @throws Exception if this resource cannot be closed
+ */
+ override fun close() = manager.close()
+}
diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/topology/JpaTopologyFactory.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/topology/JpaTopologyFactory.kt
new file mode 100644
index 00000000..65961413
--- /dev/null
+++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/topology/JpaTopologyFactory.kt
@@ -0,0 +1,91 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.odc.topology
+
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Rack
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Room
+import com.atlarge.opendc.model.odc.integration.jpa.schema.RoomObject
+import com.atlarge.opendc.model.odc.integration.jpa.schema.Section
+import com.atlarge.opendc.model.topology.*
+
+/**
+ * A [TopologyFactory] that converts a [Section] of an experiment as defined by the API, into a proper [Topology].
+ *
+ * @property section The section to convert into a topology.
+ * @property builder A builder for a topology to use.
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+class JpaTopologyFactory(val section: Section, val builder: TopologyBuilder = AdjacencyList.builder()) : TopologyFactory {
+ /**
+ * Create a [MutableTopology] instance.
+ *
+ * @return A mutable topology.
+ */
+ override fun create(): MutableTopology = builder.construct {
+ val datacenter = section.datacenter
+ add(datacenter)
+ datacenter.rooms.forEach { room ->
+ add(room)
+ connect(datacenter, room, tag = "room")
+
+ room.objects.forEach { roomObject(room, it) }
+ }
+ }
+
+ /**
+ * Handle the objects in a room.
+ *
+ * @param obj The obj to handle.
+ */
+ private fun MutableTopology.roomObject(parent: Room, obj: RoomObject) = when (obj) {
+ is Rack -> rack(parent, obj)
+ else -> Unit
+ }
+
+ /**
+ * Handle a rack in a room.
+ *
+ * @param parent The parent of the rack.
+ * @param rack The rack to handle.
+ */
+ private fun MutableTopology.rack(parent: Room, rack: Rack) {
+ add(rack)
+ connect(parent, rack, tag = "rack")
+ rack.machines.forEach { machine ->
+ add(machine)
+ connect(rack, machine, tag = "machine")
+
+ machine.cpus.forEach { cpu ->
+ add(cpu)
+ connect(machine, cpu, tag = "cpu")
+ }
+
+ machine.gpus.forEach { gpu ->
+ add(gpu)
+ connect(machine, gpu, tag = "gpu")
+ }
+ }
+ }
+}
diff --git a/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml b/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml
new file mode 100644
index 00000000..887cc8ab
--- /dev/null
+++ b/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml
@@ -0,0 +1,326 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ MIT License
+ ~
+ ~ Copyright (c) 2017 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.
+ -->
+<entity-mappings
+ version="2.1"
+ xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
+>
+
+ <package>com.atlarge.opendc.model.odc.integration.jpa.schema</package>
+
+ <entity class="Experiment" access="FIELD" name="experiments">
+ <convert converter="com.atlarge.opendc.model.odc.integration.jpa.converter.SchedulerConverter"
+ attribute-name="scheduler"/>
+ <attributes>
+ <id name="id"/>
+
+ <basic name="name">
+ <column column-definition="text"/>
+ </basic>
+
+ <basic name="state">
+ <column column-definition="text"/>
+ <enumerated>STRING</enumerated>
+ </basic>
+
+ <basic name="last">
+ <column name="last_simulated_tick" column-definition="int(11)"/>
+ </basic>
+
+ <basic name="scheduler">
+ <column name="scheduler_name"/>
+ </basic>
+
+ <many-to-one name="trace" target-entity="com.atlarge.opendc.model.odc.integration.jpa.schema.Trace">
+ <join-column name="trace_id"/>
+ </many-to-one>
+
+ <one-to-one name="path" target-entity="com.atlarge.opendc.model.odc.integration.jpa.schema.Path">
+ <join-column name="path_id"/>
+ </one-to-one>
+ </attributes>
+ </entity>
+
+ <entity class="Path" access="FIELD" name="paths">
+ <attributes>
+ <id name="id"/>
+
+ <one-to-many name="sections" target-entity="com.atlarge.opendc.model.odc.integration.jpa.schema.Section">
+ <join-column name="path_id"/>
+ </one-to-many>
+ </attributes>
+ </entity>
+
+ <entity class="Section" access="FIELD" name="sections">
+ <attributes>
+ <id name="id"/>
+
+ <basic name="startTime">
+ <column name="start_tick" column-definition="int(11)"/>
+ </basic>
+
+ <many-to-one name="datacenter">
+ <join-column name="datacenter_id"/>
+ </many-to-one>
+ </attributes>
+ </entity>
+
+ <entity class="Trace" access="FIELD" name="traces" cacheable="false">
+ <attributes>
+ <id name="id"/>
+ <basic name="name">
+ <column column-definition="text"/>
+ </basic>
+ <one-to-many name="jobs" target-entity="com.atlarge.opendc.model.odc.integration.jpa.schema.Job">
+ <join-column name="trace_id"/>
+ </one-to-many>
+ </attributes>
+ </entity>
+
+ <entity class="Job" access="FIELD" name="jobs" cacheable="false">
+ <attributes>
+ <id name="id"/>
+ <one-to-many name="tasks" target-entity="Task">
+ <join-column name="job_id"/>
+ </one-to-many>
+ <transient name="owner"/>
+ </attributes>
+ </entity>
+
+ <entity class="Task" access="FIELD" name="tasks" cacheable="false">
+ <convert converter="com.atlarge.opendc.model.odc.integration.jpa.converter.ParallelizableConverter"
+ attribute-name="parallelizable"/>
+ <attributes>
+ <id name="id"/>
+ <basic name="flops">
+ <column name="total_flop_count" column-definition="int(11)"/>
+ </basic>
+ <basic name="startTime">
+ <column name="start_tick" column-definition="int(11)"/>
+ </basic>
+ <basic name="parallelizable">
+ <column name="parallelizability" column-definition="text"/>
+ </basic>
+
+ <one-to-one name="dependency" target-entity="Task">
+ <join-column name="task_dependency_id"/>
+ </one-to-one>
+ <transient name="dependencies"/>
+ <transient name="state"/>
+ <transient name="remaining"/>
+ <transient name="finished"/>
+ </attributes>
+ </entity>
+
+ <entity class="Datacenter" access="FIELD" name="datacenters">
+ <attributes>
+ <id name="id"/>
+
+ <one-to-many name="rooms" target-entity="Room">
+ <join-column name="datacenter_id"/>
+ </one-to-many>
+ <transient name="scheduler"/>
+ <transient name="interval"/>
+ <transient name="initialState"/>
+ </attributes>
+ </entity>
+
+ <entity class="Room" access="FIELD" name="rooms">
+ <attributes>
+ <id name="id"/>
+ <basic name="name">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="type">
+ <enumerated>STRING</enumerated>
+ </basic>
+ <one-to-many name="objects">
+ <join-table name="tiles">
+ <join-column name="room_id"/>
+ <inverse-join-column name="object_id"/>
+ </join-table>
+ </one-to-many>
+ <transient name="initialState"/>
+ </attributes>
+ </entity>
+
+ <entity class="RoomObject" access="FIELD" name="objects">
+ <inheritance strategy="JOINED"/>
+ <discriminator-column name="type"/>
+ <attributes>
+ <id name="id"/>
+ </attributes>
+ </entity>
+
+ <entity class="Rack" access="FIELD" name="racks">
+ <discriminator-value>RACK</discriminator-value>
+ <attributes>
+ <id name="id"/>
+ <basic name="name">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="capacity"/>
+ <basic name="powerCapacity">
+ <column name="power_capacity_w"/>
+ </basic>
+
+ <one-to-many name="machines">
+ <join-column name="rack_id"/>
+ </one-to-many>
+ <transient name="initialState"/>
+ </attributes>
+ </entity>
+
+ <entity class="Machine" access="FIELD" name="machines">
+ <attributes>
+ <id name="id"/>
+ <basic name="position"/>
+
+ <many-to-many name="cpus">
+ <join-table name="machine_cpus">
+ <join-column name="machine_id"/>
+ <inverse-join-column name="cpu_id"/>
+ </join-table>
+ </many-to-many>
+
+ <many-to-many name="gpus">
+ <join-table name="machine_gpus">
+ <join-column name="machine_id"/>
+ <inverse-join-column name="gpu_id"/>
+ </join-table>
+ </many-to-many>
+ <transient name="initialState"/>
+ </attributes>
+ </entity>
+
+ <entity class="Cpu" access="FIELD" name="cpus">
+ <attributes>
+ <id name="id"/>
+ <basic name="manufacturer">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="family">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="generation">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="model">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="clockRate">
+ <column name="clock_rate_mhz"/>
+ </basic>
+ <basic name="cores">
+ <column name="number_of_cores"/>
+ </basic>
+ <basic name="energyConsumption">
+ <column name="energy_consumption_w"/>
+ </basic>
+ <transient name="initialState"/>
+ </attributes>
+ </entity>
+
+ <entity class="Gpu" access="FIELD" name="gpus">
+ <attributes>
+ <id name="id"/>
+ <basic name="manufacturer">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="family">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="generation">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="model">
+ <column column-definition="text"/>
+ </basic>
+ <basic name="clockRate">
+ <column name="clock_rate_mhz"/>
+ </basic>
+ <basic name="cores">
+ <column name="number_of_cores"/>
+ </basic>
+ <basic name="energyConsumption">
+ <column name="energy_consumption_w"/>
+ </basic>
+ <transient name="initialState"/>
+ </attributes>
+ </entity>
+
+ <entity class="MachineState" access="FIELD" name="machine_states">
+ <attributes>
+ <id name="id">
+ <generated-value strategy="IDENTITY"/>
+ </id>
+ <basic name="time">
+ <column name="tick" column-definition="int(11)"/>
+ </basic>
+ <basic name="temperature">
+ <column name="temperature_c"/>
+ </basic>
+ <basic name="memoryUsage">
+ <column name="in_use_memory_mb"/>
+ </basic>
+ <basic name="load">
+ <column name="load_fraction"/>
+ </basic>
+
+ <many-to-one name="task">
+ <join-column name="task_id"/>
+ </many-to-one>
+ <many-to-one name="machine">
+ <join-column name="machine_id"/>
+ </many-to-one>
+ <many-to-one name="experiment">
+ <join-column name="experiment_id"/>
+ </many-to-one>
+ </attributes>
+ </entity>
+
+ <entity class="TaskState" access="FIELD" name="task_states">
+ <attributes>
+ <id name="id">
+ <generated-value strategy="IDENTITY"/>
+ </id>
+ <basic name="time">
+ <column name="tick" column-definition="int(11)"/>
+ </basic>
+ <basic name="remaining">
+ <column name="flops_left"/>
+ </basic>
+ <basic name="cores">
+ <column name="cores_used"/>
+ </basic>
+
+ <many-to-one name="task">
+ <join-column name="task_id"/>
+ </many-to-one>
+ <many-to-one name="experiment">
+ <join-column name="experiment_id"/>
+ </many-to-one>
+ </attributes>
+ </entity>
+</entity-mappings>
diff --git a/opendc-integration-jpa/mysql/Dockerfile b/opendc-model-odc/setup/Dockerfile
index 75e419b4..bfebc044 100644
--- a/opendc-integration-jpa/mysql/Dockerfile
+++ b/opendc-model-odc/setup/Dockerfile
@@ -17,7 +17,7 @@ USER root
WORKDIR $APP_HOME
# Build the application
-RUN gradle --no-daemon :opendc-integration-jpa:mysql:installDist
+RUN gradle --no-daemon assemble installDist
# Fix permissions
RUN chown -R gradle:gradle $APP_HOME
@@ -26,5 +26,4 @@ RUN chown -R gradle:gradle $APP_HOME
USER gradle
# Start the Gradle application on run
-CMD opendc-integration-jpa/mysql/build/install/mysql/bin/mysql
-
+CMD opendc-model-odc/setup/build/install/setup/bin/setup
diff --git a/opendc-omega/build.gradle b/opendc-model-odc/setup/build.gradle
index 89b5740d..1cca2a6e 100644
--- a/opendc-omega/build.gradle
+++ b/opendc-model-odc/setup/build.gradle
@@ -24,64 +24,64 @@
/* Build configuration */
buildscript {
- ext.kotlin_version = '1.1.4-3'
- ext.dokka_version = '0.9.15'
+ ext.kotlin_version = '1.2.21'
+ ext.dokka_version = '0.9.15'
- repositories {
- mavenCentral()
- jcenter()
- }
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
- classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-RC3'
- }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
+ }
}
apply plugin: 'java'
+apply plugin: 'application'
apply plugin: 'kotlin'
apply plugin: 'org.jetbrains.dokka'
-apply plugin: 'org.junit.platform.gradle.plugin'
+
+mainClassName = "com.atlarge.opendc.model.odc.platform.JpaPlatformRunnerKt"
compileKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
compileTestKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
kotlin {
- experimental {
- coroutines 'enable'
- }
+ experimental {
+ coroutines 'enable'
+ }
}
dokka {
- outputFormat = 'html'
- outputDirectory = "$buildDir/javadoc"
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
}
/* Project configuration */
-group 'nl.atlarge.opendc'
-version '1.0'
+group 'com.atlarge.opendc'
+version '1.1'
repositories {
- jcenter()
+ jcenter()
}
dependencies {
- compile project(':opendc-core')
- compile "io.github.microutils:kotlin-logging:1.4.6"
+ compile project(':opendc-model-odc:jpa')
+ compile project(':opendc-kernel-omega')
- testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3"
- testRuntime "org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3"
- testCompile "org.junit.platform:junit-platform-launcher:1.0.0-RC3"
- testCompile "org.slf4j:slf4j-simple:1.7.25"
- testCompile project(':opendc-stdlib')
+ runtime 'org.slf4j:slf4j-simple:1.7.25'
+ runtime 'org.hibernate:hibernate-core:5.2.5.Final'
+ runtime 'mysql:mysql-connector-java:5.1.13'
}
diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt b/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt
index 104f1aec..13f322bc 100644
--- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt
+++ b/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt
@@ -22,10 +22,10 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.platform
+package com.atlarge.opendc.model.odc.platform
+import com.atlarge.opendc.omega.OmegaKernel
import mu.KotlinLogging
-import nl.atlarge.opendc.kernel.omega.OmegaKernel
import java.util.concurrent.Executors
import javax.persistence.Persistence
@@ -38,28 +38,28 @@ val logger = KotlinLogging.logger {}
* @param args The command line arguments of the program.
*/
fun main(args: Array<String>) {
- val properties = HashMap<Any, Any>()
- val env = System.getenv()
- properties["javax.persistence.jdbc.url"] = env["PERSISTENCE_URL"] ?: ""
- properties["javax.persistence.jdbc.user"] = env["PERSISTENCE_USER"] ?: ""
- properties["javax.persistence.jdbc.password"] = env["PERSISTENCE_PASSWORD"] ?: ""
- val factory = Persistence.createEntityManagerFactory("opendc-simulator", properties)
+ val properties = HashMap<Any, Any>()
+ val env = System.getenv()
+ properties["javax.persistence.jdbc.url"] = env["PERSISTENCE_URL"] ?: ""
+ properties["javax.persistence.jdbc.user"] = env["PERSISTENCE_USER"] ?: ""
+ 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)
- val kernel = OmegaKernel
+ val timeout = 10000L
+ val threads = 4
+ val executorService = Executors.newFixedThreadPool(threads)
+ val experiments = JpaExperimentManager(factory)
+ val kernel = OmegaKernel
- logger.info { "Waiting for enqueued experiments..." }
- while (true) {
- experiments.poll()?.let { experiment ->
- logger.info { "Found experiment. Submitting for simulation now..." }
- executorService.submit {
- experiment.use { it.run(kernel, timeout) }
- }
- }
+ logger.info { "Waiting for enqueued experiments..." }
+ while (true) {
+ experiments.poll()?.let { experiment ->
+ logger.info { "Found experiment. Submitting for simulation now..." }
+ executorService.submit {
+ experiment.use { it.run(kernel, timeout) }
+ }
+ }
- Thread.sleep(500)
- }
+ Thread.sleep(500)
+ }
}
diff --git a/opendc-integration-jpa/mysql/src/main/resources/META-INF/persistence.xml b/opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml
index 0e40dc6e..4c4e6ac7 100644
--- a/opendc-integration-jpa/mysql/src/main/resources/META-INF/persistence.xml
+++ b/opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml
@@ -23,19 +23,19 @@
~ SOFTWARE.
-->
-<persistence xmlns="http://java.sun.com/xml/ns/persistence"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
- version="2.0">
- <persistence-unit name="opendc-simulator">
- <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
- <mapping-file>jpa/schema.xml</mapping-file>
- <properties>
- <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
- <property name="hibernate.show_sql" value="false" />
- <property name="hibernate.hbm2ddl.auto" value="validate" />
- <property name="hibernate.jdbc.batch_size" value="50" />
- </properties>
- </persistence-unit>
+<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://java.sun.com/xml/ns/persistence"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+ version="2.0">
+ <persistence-unit name="opendc-simulator">
+ <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
+ <mapping-file>jpa/schema.xml</mapping-file>
+ <properties>
+ <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
+ <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+ <property name="hibernate.show_sql" value="false"/>
+ <property name="hibernate.hbm2ddl.auto" value="validate"/>
+ <property name="hibernate.jdbc.batch_size" value="50"/>
+ </properties>
+ </persistence-unit>
</persistence>
diff --git a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/MessageContainer.kt b/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/MessageContainer.kt
deleted file mode 100644
index 1554a9e6..00000000
--- a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/MessageContainer.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.omega
-
-import nl.atlarge.opendc.kernel.messaging.Envelope
-import nl.atlarge.opendc.kernel.messaging.Receipt
-import nl.atlarge.opendc.kernel.time.Instant
-import nl.atlarge.opendc.topology.Entity
-
-/**
- * A wrapper around a message that has been scheduled for processing.
- *
- * @property message The message to wrap.
- * @property time The point in time to deliver the message.
- * @property sender The sender of the message.
- * @property destination The destination of the message.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-internal data class MessageContainer(override val message: Any,
- val time: Instant,
- override val sender: Entity<*>?,
- override val destination: Entity<*>) : Envelope<Any>, Receipt {
- /**
- * A flag to indicate the message has been canceled.
- */
- override var canceled: Boolean = false
-
- /**
- * A flag to indicate the message has been delivered.
- */
- override var delivered: Boolean = false
-
- /**
- * Cancel the message to prevent it from being received by an [Entity].
- *
- * @throws IllegalStateException if the message has already been delivered.
- */
- override fun cancel() {
- if (delivered) {
- throw IllegalStateException("The message has already been delivered")
- }
-
- canceled = true
- }
-
-}
diff --git a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaSimulation.kt b/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaSimulation.kt
deleted file mode 100644
index 48b9d556..00000000
--- a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaSimulation.kt
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.omega
-
-import mu.KotlinLogging
-import nl.atlarge.opendc.kernel.*
-import nl.atlarge.opendc.kernel.messaging.Envelope
-import nl.atlarge.opendc.kernel.messaging.Receipt
-import nl.atlarge.opendc.kernel.time.Clock
-import nl.atlarge.opendc.kernel.time.Duration
-import nl.atlarge.opendc.kernel.time.Instant
-import nl.atlarge.opendc.kernel.time.TickClock
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.MutableTopology
-import nl.atlarge.opendc.topology.Topology
-import nl.atlarge.opendc.topology.TopologyContext
-import java.util.*
-import kotlin.coroutines.experimental.*
-
-/**
- * The Omega simulation kernel is the reference simulation kernel implementation for the OpenDC Simulator core.
- *
- * This simulator implementation is a single-threaded implementation, running simulation kernels synchronously and
- * provides a single priority queue for all events (messages, ticks, etc) that occur in the entities.
- *
- * By default, [Process]s are resolved as part of the [Topology], meaning each [Entity] in the topology should also
- * implement its simulation behaviour by deriving from the [Process] interface.
- *
- * @property kernel The kernel that facilitates the simulation.
- * @property topology The topology to run the simulation over.
- * @property clock The clock to use for simulation time.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-internal class OmegaSimulation(override val kernel: OmegaKernel, override val topology: MutableTopology,
- override val clock: Clock = TickClock()) : Simulation {
- /**
- * The logger instance to use for the simulator.
- */
- private val logger = KotlinLogging.logger {}
-
- /**
- * The registry of the simulation kernels used in the experiment.
- */
- private val registry: MutableMap<Entity<*>, OmegaContext<*, *>> = HashMap()
-
- /**
- * The message queue.
- */
- private val queue: Queue<MessageContainer> = PriorityQueue(Comparator.comparingLong(MessageContainer::time))
-
- /**
- * The context associated with an [Entity].
- */
- @Suppress("UNCHECKED_CAST")
- private val <E : Entity<S>, S> E.context: OmegaContext<E, S>?
- get() = registry[this] as? OmegaContext<E, S>
-
- /**
- * The observable state of an [Entity] in simulation, which is provided by the simulation context.
- */
- override val <E : Entity<S>, S> E.state: S
- get() = context?.state ?: initialState
-
- /**
- * Initialise the simulator.
- */
- init {
- topology.forEach { entity ->
- if (entity is Process<*>) {
- @Suppress("UNCHECKED_CAST")
- val context = registry.computeIfAbsent(entity, { OmegaContext(entity) }) as OmegaContext<Nothing, *>
- val process = entity as Process<*>
-
- // Start all process co-routines
- val block: suspend () -> Unit = { process.run { context.run() } }
- block.startCoroutine(context)
- }
- }
- }
-
- /**
- * Step through one event in the simulation.
- */
- override fun step() {
- while (true) {
- val envelope = queue.peek() ?: return
- val delivery = envelope.time
-
- if (delivery > clock.now) {
- // Tick has yet to occur
- // Jump in time to next event
- clock.advanceTo(delivery)
- break
- } else if (delivery < clock.now) {
- // Tick has already occurred
- logger.warn { "message processed out of order" }
- }
- // Remove the message from the queue
- queue.poll()
-
- // If the sender has canceled the message, we move on to the next message
- if (envelope.canceled) {
- continue
- }
-
- val context = envelope.destination.context ?: continue
-
- if (envelope.message !is Interrupt) {
- context.continuation.resume(envelope)
- } else {
- context.continuation.resumeWithException(envelope.message)
- }
-
- context.last = clock.now
- }
- }
-
- /**
- * Run a simulation over the specified [Topology].
- * This method will step through multiple cycles in the simulation until no more message exist in the queue.
- */
- override fun run() {
- while (queue.isNotEmpty()) {
- step()
- }
- }
-
- /**
- * Run a simulation over the specified [Topology], stepping through cycles until (exclusive) the specified clock
- * tick has occurred. The control is then handed back to the user.
- *
- * @param until The point in simulation time at which the simulation should be paused and the control is handed
- * back to the user.
- */
- override fun run(until: Instant) {
- require(until > 0) { "The given instant must be a non-zero positive number" }
-
- if (clock.now >= until) {
- return
- }
-
- while (clock.now < until && queue.isNotEmpty()) {
- step()
- }
-
- // Fix clock if step() jumped too far in time to give the impression to the user that simulation stopped at
- // exactly the tick it gave. This has not effect on the actual simulation results as the next call to run() will
- // just jump forward again.
- if (clock.now > until) {
- clock.rewindTo(until)
- }
- }
-
- /**
- * Schedule a message for processing by a [Process].
- *
- * @param message The message to schedule.
- * @param destination The destination of the message.
- * @param sender The sender of the message.
- * @param delay The amount of time to wait before processing the message.
- */
- override fun schedule(message: Any, destination: Entity<*>, sender: Entity<*>?, delay: Duration): Receipt {
- require(delay >= 0) { "The amount of time to delay the message must be a positive number" }
- val wrapped = MessageContainer(message, clock.now + delay, sender, destination)
- queue.add(wrapped)
- return wrapped
- }
-
- /**
- * This internal class provides the default implementation for the [Context] interface for this simulator.
- */
- private inner class OmegaContext<out E : Entity<S>, S>(override val entity: E) : Context<E>,
- Continuation<Unit>, TopologyContext by topology {
- /**
- * The continuation to resume the execution of the process.
- */
- lateinit var continuation: Continuation<Envelope<*>>
-
- /**
- * The last point in time the process has done some work.
- */
- var last: Instant = -1
-
- /**
- * The state of the entity.
- */
- var state: S = entity.initialState
-
- /**
- * The [Topology] over which the simulation is run.
- */
- override val topology = this@OmegaSimulation.topology
-
- /**
- * The current point in simulation time.
- */
- override val time: Instant
- get() = clock.now
-
- /**
- * The duration between the current point in simulation time and the last point in simulation time where the
- * [Process] has executed some work.
- */
- override val delta: Duration
- get() = clock.now - last
-
- /**
- * The [CoroutineContext] for a [Process].
- */
- override val context: CoroutineContext = EmptyCoroutineContext
-
- /**
- * The observable state of an [Entity] within the simulation is provided by the context of the simulation.
- */
- override val <T : Entity<S>, S> T.state: S
- get() = context?.state ?: initialState
-
- /**
- * Retrieve and remove and single message from the mailbox of the [Entity] and suspend the [Process] until the
- * message has been received.
- *
- * @return The envelope containing the message.
- */
- suspend fun receiveEnvelope(): Envelope<*> {
- return suspendCoroutine { continuation = it }
- }
-
- /**
- * Retrieve and removes a single message from the entity's mailbox, suspending the function if the mailbox is empty.
- * The execution is resumed after the message has landed in the entity's mailbox after which the message [Envelope]
- * is mapped through `block` to generate a processed message.
- *
- * @param block The block to process the message with.
- * @return The processed message.
- */
- suspend override fun <T> receive(block: suspend Envelope<*>.(Any) -> T): T {
- val envelope = receiveEnvelope()
- return block(envelope, envelope.message)
- }
-
- /**
- * Retrieve and removes a single message from the entity's mailbox, suspending the function if the mailbox is empty.
- * The execution is resumed after the message has landed in the entity's mailbox or the timeout was reached,
- *
- * If the message has been received, the message [Envelope] is mapped through `block` to generate a processed
- * message. If the timeout was reached, `block` is not called and `null` is returned.
- *
- * @param timeout The duration to wait before resuming execution.
- * @param block The block to process the message with.
- * @return The processed message or `null` if the timeout was reached.
- */
- suspend override fun <T> receive(timeout: Duration, block: suspend Envelope<*>.(Any) -> T): T? {
- val receipt = schedule(Timeout, entity, entity, timeout)
- val envelope = receiveEnvelope()
-
- if (envelope.message !is Timeout) {
- receipt.cancel()
- return block(envelope, envelope.message)
- }
-
- return null
- }
-
- /**
- * Send the given message to the specified entity.
- *
- * @param msg The message to send.
- * @param delay The amount of time to wait before the message should be received.
- */
- suspend override fun Entity<*>.send(msg: Any, delay: Duration) = send(msg, entity, delay)
-
- /**
- * Send the given message to the specified entity.
- *
- * @param msg The message to send.
- * @param sender The sender of the message.
- * @param delay The amount of time to wait before the message should be received.
- */
- suspend override fun Entity<*>.send(msg: Any, sender: Entity<*>, delay: Duration): Receipt {
- return schedule(msg, this, sender, delay)
- }
-
- /**
- * Send an interruption message to the given [Entity].
- */
- suspend override fun Entity<*>.interrupt() {
- send(Interrupt)
- }
-
- /**
- * Suspend the [Process] of the [Entity] in simulation for one tick in simulation time which is defined by the
- * [Clock].
- *
- * @return `true` to allow usage in while statements.
- */
- suspend override fun tick(): Boolean {
- wait(clock.tick)
- return true
- }
-
- /**
- * Suspend the [Process] of the [Entity] in simulation for the given duration of simulation time before resuming
- * execution.
- *
- * A call to this method will not make the [Process] sleep for the actual duration of time, but instead suspend
- * the process until the no more messages at an earlier point in time have to be processed.
- *
- * @param duration The duration of simulation time to wait before resuming execution.
- */
- suspend override fun wait(duration: Duration) {
- require(duration >= 0) { "The amount of time to suspend must be a positive number" }
- schedule(Resume, entity, entity, duration)
- while (true) {
- if (receive() is Resume)
- return
- }
- }
-
- /**
- * Suspend the [Process] of the [Entity] in simulation for the given duration of simulation time before resuming
- * execution and push all messages that are received during this period to the given queue.
- *
- * A call to this method will not make the [Process] sleep for the actual duration of time, but instead suspend
- * the process until the no more messages at an earlier point in time have to be processed.
- *
- * @param duration The duration of simulation time to wait before resuming execution.
- * @param queue The mutable queue to push the messages to.
- */
- suspend override fun wait(duration: Duration, queue: Queue<Any>) {
- require(duration >= 0) { "The amount of time to suspend must be a positive number" }
- schedule(Resume, entity, entity, duration)
- while (true) {
- val msg = receive()
- if (msg is Resume)
- return
- queue.add(msg)
- }
- }
-
- /**
- * Update the state of the entity being simulated.
- *
- * <p>Instead of directly mutating the entity, we create a new instance of the entity to prevent other objects
- * referencing the old entity having their data changed.
- *
- * @param next The next state of the entity.
- */
- suspend override fun <C : Context<E>, E : Entity<S>, S> C.update(next: S) {
- @Suppress("UNCHECKED_CAST")
- (this as OmegaContext<E, S>).state = next
- }
-
- // Completion continuation implementation
- /**
- * Resume the execution of this continuation with the given value.
- *
- * @param value The value to resume with.
- */
- override fun resume(value: Unit) {
- // Deregister process from registry
- registry.remove(entity)
- }
-
- /**
- * Resume the execution of this continuation with an exception.
- *
- * @param exception The exception to resume with.
- */
- override fun resumeWithException(exception: Throwable) {
- // Deregister process from registry
- registry.remove(entity)
-
- logger.error(exception) { "An exception occurred during the execution of a process" }
- }
- }
-}
diff --git a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Resume.kt b/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Resume.kt
deleted file mode 100644
index d20115d0..00000000
--- a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Resume.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.omega
-
-import nl.atlarge.opendc.kernel.Context
-
-/**
- * An internal message used by the Omega simulation kernel to indicate to a suspended [Process], that it should wake up
- * and resume execution.
- *
- * This message is not guaranteed to work on other simulation kernels and [Context.interrupt] should be preferred to
- * wake up a process from another entity.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-object Resume
diff --git a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Timeout.kt b/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Timeout.kt
deleted file mode 100644
index 41dcce71..00000000
--- a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Timeout.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.kernel.omega
-
-/**
- * An internal message used by the Omega simulation kernel to indicate to a suspended [Process], that a timeout has been
- * reached and that it should wake up and resume execution.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-object Timeout
diff --git a/opendc-omega/src/test/kotlin/nl/atlarge/opendc/SmokeTest.kt b/opendc-omega/src/test/kotlin/nl/atlarge/opendc/SmokeTest.kt
deleted file mode 100644
index cb2ce643..00000000
--- a/opendc-omega/src/test/kotlin/nl/atlarge/opendc/SmokeTest.kt
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc
-
-import nl.atlarge.opendc.kernel.Context
-import nl.atlarge.opendc.kernel.Process
-import nl.atlarge.opendc.kernel.omega.OmegaKernel
-import nl.atlarge.opendc.topology.AdjacencyList
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.machine.Machine
-import org.junit.jupiter.api.Test
-
-/**
- * This test suite checks for smoke when running a large amount of simulations.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-internal class SmokeTest {
- /**
- * Run a large amount of simulations and test if any exceptions occur.
- */
- @Test
- fun smoke() {
- val n = 1000
- val builder = AdjacencyList.builder()
- repeat(n) {
- val root = Machine()
- val topology = builder.construct {
- add(root)
-
- val other = Machine()
- add(other)
-
- connect(root, other, tag = "neighbour")
- connect(other, root, tag = "neighbour")
- }
-
- val simulation = OmegaKernel.create(topology)
-
- for (i in 1..1000) {
- simulation.schedule(i, root, delay = i.toLong())
- }
-
- simulation.run()
- }
- }
-
- class NullProcess : Entity<Unit>, Process<NullProcess> {
- override val initialState = Unit
- suspend override fun Context<NullProcess>.run() {}
- }
-
- /**
- * Test if the kernel allows sending messages to [Process] instances that have already stopped.
- */
- @Test
- fun `sending message to process that has gracefully stopped`() {
-
- val builder = AdjacencyList.builder()
- val process = NullProcess()
- val topology = builder.construct {
- add(process)
- }
-
- val simulation = OmegaKernel.create(topology)
- simulation.schedule(0, process)
- simulation.run()
- }
-
- class CrashProcess : Entity<Unit>, Process<NullProcess> {
- override val initialState = Unit
- suspend override fun Context<NullProcess>.run() {
- TODO()
- }
- }
-
- /**
- * Test if the kernel allows sending messages to [Process] instances that have crashed.
- */
- @Test
- fun `sending message to process that has crashed`() {
-
- val builder = AdjacencyList.builder()
- val process = CrashProcess()
- val topology = builder.construct {
- add(process)
- }
-
- val simulation = OmegaKernel.create(topology)
- simulation.schedule(0, process)
- simulation.run()
- }
-}
diff --git a/opendc-stdlib/build.gradle b/opendc-stdlib/build.gradle
index a0c92459..e02da931 100644
--- a/opendc-stdlib/build.gradle
+++ b/opendc-stdlib/build.gradle
@@ -24,19 +24,19 @@
/* Build configuration */
buildscript {
- ext.kotlin_version = '1.1.4-3'
- ext.dokka_version = '0.9.15'
+ ext.kotlin_version = '1.2.21'
+ ext.dokka_version = '0.9.15'
- repositories {
- mavenCentral()
- jcenter()
- }
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
- classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-RC3'
- }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
+ classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3'
+ }
}
apply plugin: 'java'
@@ -45,42 +45,44 @@ apply plugin: 'org.jetbrains.dokka'
apply plugin: 'org.junit.platform.gradle.plugin'
compileKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
compileTestKotlin {
- kotlinOptions {
- jvmTarget = "1.8"
- }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
}
kotlin {
- experimental {
- coroutines 'enable'
- }
+ experimental {
+ coroutines 'enable'
+ }
}
dokka {
- outputFormat = 'html'
- outputDirectory = "$buildDir/javadoc"
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/javadoc"
}
/* Project configuration */
-group 'nl.atlarge.opendc'
-version '1.0'
+group 'com.atlarge.opendc'
+version '1.1'
repositories {
- jcenter()
+ jcenter()
}
dependencies {
- compile project(':opendc-core')
- compile "io.github.microutils:kotlin-logging:1.4.6"
+ compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.2"
+ compile project(':opendc-core')
+ compile "io.github.microutils:kotlin-logging:1.4.6"
- testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3"
- testRuntime "org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3"
- testCompile "org.junit.platform:junit-platform-launcher:1.0.0-RC3"
- testCompile "org.slf4j:slf4j-simple:1.7.25"
+ testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3"
+ testRuntime "org.junit.jupiter:junit-jupiter-engine:5.0.0-RC3"
+ testCompile "org.junit.platform:junit-platform-launcher:1.0.0-RC3"
+ testCompile "org.slf4j:slf4j-simple:1.7.25"
}
diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/AdjacencyList.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/AdjacencyList.kt
new file mode 100644
index 00000000..db117917
--- /dev/null
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/AdjacencyList.kt
@@ -0,0 +1,260 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.topology
+
+import com.atlarge.opendc.simulator.Entity
+import java.util.concurrent.atomic.AtomicInteger
+import com.atlarge.opendc.model.topology.Edge as BaseEdge
+
+/**
+ * This module provides a [Topology] implementation backed internally by an adjacency list.
+ *
+ * This implementation is best suited for sparse graphs, where an adjacency matrix would take up too much space with
+ * empty cells.
+ *
+ * *Note that this implementation is not synchronized.*
+ */
+object AdjacencyList {
+ /**
+ * Return a [TopologyBuilder] that constructs the topology represents as an adjacency list.
+ *
+ * @return A [TopologyBuilder] instance.
+ */
+ fun builder(): TopologyBuilder = AdjacencyListTopologyBuilder()
+}
+
+/**
+ * A builder for [Topology] instances, which is backed by an adjacency list.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+internal class AdjacencyListTopologyBuilder : TopologyBuilder {
+ /**
+ * Build a [Topology] instance from the current state of this builder.
+ *
+ * @return The graph built from this builder.
+ */
+ override fun create(): MutableTopology = AdjacencyListTopology()
+}
+
+/**
+ * A [Topology] whose graph is represented as adjacency list.
+ */
+internal class AdjacencyListTopology : MutableTopology {
+ /**
+ * The identifier for the next node in the graph.
+ */
+ private var nextId: AtomicInteger = AtomicInteger(0)
+
+ /**
+ * A mapping of nodes to their internal representation with the edges of the nodes.
+ */
+ private var nodes: MutableMap<Entity<*, Topology>, Node> = HashMap()
+
+ // Topology
+
+ /**
+ * The listeners of this topology.
+ */
+ override val listeners: MutableSet<TopologyListener> = HashSet()
+
+ /**
+ * A unique identifier of this node within the topology.
+ */
+ override val Entity<*, Topology>.id: Int
+ get() = nodes[this]!!.id
+
+ /**
+ * The set of ingoing edges of this node.
+ */
+ override val Entity<*, Topology>.ingoingEdges: MutableSet<BaseEdge<*>>
+ get() = nodes[this]!!.ingoingEdges
+
+ /**
+ * The set of outgoing edges of this node.
+ */
+ override val Entity<*, Topology>.outgoingEdges: MutableSet<BaseEdge<*>>
+ get() = nodes[this]!!.outgoingEdges
+
+ // MutableTopology
+
+ /**
+ * Create a directed edge between two [Node]s in the topology.
+ *
+ * @param from The source of the edge.
+ * @param to The destination of the edge.
+ * @param label The label of the edge.
+ * @param tag The tag of the edge that uniquely identifies the relationship the edge represents.
+ * @return The edge that has been created.
+ */
+ override fun <T> connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String?): BaseEdge<T> {
+ if (!contains(from) || !contains(to))
+ throw IllegalArgumentException("One of the entities is not part of the topology")
+ val edge = Edge(label, tag, from, to)
+ from.outgoingEdges.add(edge)
+ to.ingoingEdges.add(edge)
+ listeners.forEach { it.run { this@AdjacencyListTopology.onEdgeAdded(edge) } }
+ return edge
+ }
+
+ // Cloneable
+
+ /**
+ * Create a copy of the graph.
+ *
+ * @return A new [Topology] instance with a copy of the graph.
+ */
+ override fun clone(): Topology {
+ val copy = AdjacencyListTopology()
+ copy.nextId = AtomicInteger(nextId.get())
+ copy.nodes = HashMap(nodes)
+ return copy
+ }
+
+ // Set
+
+ /**
+ * Returns the size of the collection.
+ */
+ override val size: Int = nodes.size
+
+ /**
+ * Checks if the specified element is contained in this collection.
+ */
+ override fun contains(element: Entity<*, Topology>): Boolean = nodes.contains(element)
+
+ /**
+ * Checks if all elements in the specified collection are contained in this collection.
+ */
+ override fun containsAll(elements: Collection<Entity<*, Topology>>): Boolean =
+ elements.all { nodes.containsKey(it) }
+
+ /**
+ * Returns `true` if the collection is empty (contains no elements), `false` otherwise.
+ */
+ override fun isEmpty(): Boolean = nodes.isEmpty()
+
+ // MutableSet
+
+ /**
+ * Add a node to the graph.
+ *
+ * @param element The element to add to this graph.
+ * @return `true` if the graph has changed, `false` otherwise.
+ */
+ override fun add(element: Entity<*, Topology>): Boolean {
+ if (nodes.putIfAbsent(element, Node(nextId.getAndIncrement())) == null) {
+ listeners.forEach { it.run { this@AdjacencyListTopology.onNodeAdded(element) } }
+ return true
+ }
+ return false
+ }
+
+ /**
+ * Add all nodes in the specified collection to the graph.
+ *
+ * @param elements The nodes to add to this graph.
+ * @return `true` if the graph has changed, `false` otherwise.
+ */
+ override fun addAll(elements: Collection<Entity<*, Topology>>): Boolean = elements.any { add(it) }
+
+ /**
+ * Remove all nodes and their respective edges from the graph.
+ */
+ override fun clear() = nodes.clear()
+
+ /**
+ * Remove the given node and its edges from the graph.
+ *
+ * @param element The element to remove from the graph.
+ * @return `true` if the graph has changed, `false` otherwise.
+ */
+ override fun remove(element: Entity<*, Topology>): Boolean {
+ nodes[element]?.ingoingEdges?.forEach {
+ it.from.outgoingEdges.remove(it)
+ }
+ nodes[element]?.outgoingEdges?.forEach {
+ it.to.ingoingEdges.remove(it)
+ }
+ if (nodes.keys.remove(element)) {
+ listeners.forEach { it.run { this@AdjacencyListTopology.onNodeRemoved(element) } }
+ return true
+ }
+ return false
+ }
+
+
+ /**
+ * Remove all nodes in the given collection from the graph.
+ *
+ * @param elements The elements to remove from the graph.
+ * @return `true` if the graph has changed, `false` otherwise.
+ */
+ override fun removeAll(elements: Collection<Entity<*, Topology>>): Boolean = elements.any(this::remove)
+
+ /**
+ * Remove all nodes in the graph, except those in the specified collection.
+ *
+ * Take note that this method currently only guarantees a maximum runtime complexity of O(n^2).
+ *
+ * @param elements The elements to retain in the graph.
+ */
+ override fun retainAll(elements: Collection<Entity<*, Topology>>): Boolean {
+ val iterator = nodes.keys.iterator()
+ var changed = false
+ while (iterator.hasNext()) {
+ val entity = iterator.next()
+
+ if (entity !in elements) {
+ iterator.remove()
+ changed = true
+ }
+ }
+ return changed
+ }
+
+ /**
+ * Return a mutable iterator over the nodes of the graph.
+ *
+ * @return A [MutableIterator] over the nodes of the graph.
+ */
+ override fun iterator(): MutableIterator<Entity<*, Topology>> = nodes.keys.iterator()
+
+ /**
+ * The internal representation of a node within the graph.
+ */
+ internal data class Node(val id: Int) {
+ val ingoingEdges: MutableSet<BaseEdge<*>> = HashSet()
+ val outgoingEdges: MutableSet<BaseEdge<*>> = HashSet()
+ }
+
+ /**
+ * The internal representation of an edge within the graph.
+ */
+ internal class Edge<out T>(override val label: T,
+ override val tag: String?,
+ override val from: Entity<*, Topology>,
+ override val to: Entity<*, Topology>) : BaseEdge<T>
+}
diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Bootstrap.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Bootstrap.kt
new file mode 100644
index 00000000..e0b54a28
--- /dev/null
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Bootstrap.kt
@@ -0,0 +1,23 @@
+package com.atlarge.opendc.model.topology
+
+import com.atlarge.opendc.simulator.Bootstrap
+import com.atlarge.opendc.simulator.Entity
+
+/**
+ * Create a [Bootstrap] procedure for the given [Topology].
+ *
+ * @return A apply procedure for the topology.
+ */
+fun <T : Topology> T.bootstrap(): Bootstrap<T> = Bootstrap.create { ctx ->
+ forEach { ctx.register(it) }
+ listeners += object : TopologyListener {
+ override fun Topology.onNodeAdded(node: Entity<*, Topology>) {
+ ctx.register(node)
+ }
+
+ override fun Topology.onNodeRemoved(node: Entity<*, Topology>) {
+ ctx.deregister(node)
+ }
+ }
+ this
+}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Component.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Component.kt
index 3c383892..5e8611a0 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Component.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Component.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.model.topology
/**
* A component within a [Topology], which is either a node or an [Edge] representing the relationship between
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Edge.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt
index 3be14dec..1963a056 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Edge.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt
@@ -22,7 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.model.topology
+
+import com.atlarge.opendc.simulator.Entity
/**
* An edge that represents a directed relationship between exactly two nodes in a logical topology of a cloud network.
@@ -31,29 +33,29 @@ package nl.atlarge.opendc.topology
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface Edge<out T> : Component {
- /**
- * The label of this edge.
- */
- val label: T
+ /**
+ * The label of this edge.
+ */
+ val label: T
- /**
- * A tag to uniquely identify the relationship this edge represents.
- */
- val tag: String?
+ /**
+ * A tag to uniquely identify the relationship this edge represents.
+ */
+ val tag: String?
- /**
- * The source of the edge.
- *
- * This property is not guaranteed to have a runtime complexity of <code>O(1)</code>, but must be at least
- * <code>O(n)</code>, with respect to the size of the topology.
- */
- val from: Entity<*>
+ /**
+ * The source of the edge.
+ *
+ * This property is not guaranteed to have a runtime complexity of <code>O(1)</code>, but must be at least
+ * <code>O(n)</code>, with respect to the size of the topology.
+ */
+ val from: Entity<*, Topology>
- /**
- * The destination of the edge.
- *
- * This property is not guaranteed to have a runtime complexity of <code>O(1)</code>, but must be at least
- * <code>O(n)</code>, with respect to the size of the topology.
- */
- val to: Entity<*>
+ /**
+ * The destination of the edge.
+ *
+ * This property is not guaranteed to have a runtime complexity of <code>O(1)</code>, but must be at least
+ * <code>O(n)</code>, with respect to the size of the topology.
+ */
+ val to: Entity<*, Topology>
}
diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/MutableTopology.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/MutableTopology.kt
new file mode 100644
index 00000000..7cf80702
--- /dev/null
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/MutableTopology.kt
@@ -0,0 +1,65 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2017 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 com.atlarge.opendc.model.topology
+
+import com.atlarge.opendc.simulator.Entity
+
+/**
+ * A subinterface of [Topology] which adds mutation methods. When mutation is not required, users
+ * should prefer the [Topology] interface.
+ *
+ * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
+ */
+interface MutableTopology : Topology, MutableSet<Entity<*, Topology>> {
+ /**
+ * Create a directed, labeled edge between two nodes in the topology.
+ *
+ * @param from The source of the edge.
+ * @param to The destination of the edge.
+ * @param label The label of the edge.
+ * @param tag The tag of the edge that uniquely identifies the relationship the edge represents.
+ * @return The edge that has been created.
+ */
+ fun <T> connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String? = null): Edge<T>
+
+ /**
+ * Create a directed, unlabeled edge between two nodes in the topology.
+ *
+ * @param from The source of the edge.
+ * @param to The destination of the edge.
+ * @param tag The tag of the edge that uniquely identifies the relationship the edge represents.
+ * @return The edge that has been created.
+ */
+ fun connect(from: Entity<*, Topology>, to: Entity<*, Topology>, tag: String? = null): Edge<Unit> =
+ connect(from, to, Unit, tag)
+
+ /**
+ * Create a directed, unlabeled edge between two nodes in the topology.
+ *
+ * @param dest The destination of the edge.
+ * @return The edge that has been created.
+ */
+ infix fun Entity<*, Topology>.to(dest: Entity<*, Topology>): Edge<Unit> = connect(this, dest)
+}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Topology.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt
index 27c1c889..e277bc9f 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Topology.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt
@@ -22,7 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.model.topology
+
+import com.atlarge.opendc.simulator.Entity
/**
* A graph data structure which represents the logical topology of a cloud network consisting of one or more
@@ -32,17 +34,17 @@ package nl.atlarge.opendc.topology
*
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
-interface Topology : TopologyContext, Cloneable, Set<Entity<*>> {
- /**
- * The listeners of this topology.
- */
- val listeners: MutableSet<TopologyListener>
+interface Topology : TopologyContext, Cloneable, Set<Entity<*, Topology>> {
+ /**
+ * The listeners of this topology.
+ */
+ val listeners: MutableSet<TopologyListener>
- /**
- * Create a copy of the topology.
- *
- * @return A new [Topology] with a copy of the graph.
- */
- public override fun clone(): Topology
+ /**
+ * Create a copy of the topology.
+ *
+ * @return A new [Topology] with a copy of the graph.
+ */
+ public override fun clone(): Topology
}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyBuilder.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt
index bb9c7e8e..8bdc37c0 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyBuilder.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.model.topology
/**
* A builder for [Topology] instances.
@@ -30,11 +30,11 @@ package nl.atlarge.opendc.topology
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface TopologyBuilder : TopologyFactory {
- /**
- * Construct a [Topology] from the given block and return it.
- *
- * @param block The block to construct the topology.
- * @return The topology that has been built.
- */
- fun construct(block: MutableTopology.() -> Unit): MutableTopology = create().apply(block)
+ /**
+ * Construct a [Topology] from the given block and return it.
+ *
+ * @param block The block to construct the topology.
+ * @return The topology that has been built.
+ */
+ fun construct(block: MutableTopology.() -> Unit): MutableTopology = create().apply(block)
}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyContext.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt
index 22e7dd94..9d78b5eb 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyContext.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt
@@ -22,7 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.model.topology
+
+import com.atlarge.opendc.simulator.Entity
/**
* A [TopologyContext] represents the context for entities in a specific topology, providing access to the identifier
@@ -31,18 +33,18 @@ package nl.atlarge.opendc.topology
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface TopologyContext {
- /**
- * A unique identifier of an [Entity] within the topology.
- */
- val Entity<*>.id: Int
+ /**
+ * A unique identifier of an [Entity] within the topology.
+ */
+ val Entity<*, Topology>.id: Int
- /**
- * The set of ingoing edges of an [Entity].
- */
- val Entity<*>.ingoingEdges: Set<Edge<*>>
+ /**
+ * The set of ingoing edges of an [Entity].
+ */
+ val Entity<*, Topology>.ingoingEdges: Set<Edge<*>>
- /**
- * The set of outgoing edges of an [Entity].
- */
- val Entity<*>.outgoingEdges: Set<Edge<*>>
+ /**
+ * The set of outgoing edges of an [Entity].
+ */
+ val Entity<*, Topology>.outgoingEdges: Set<Edge<*>>
}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyFactory.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt
index 42b30a94..ab2deeb7 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyFactory.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.model.topology
/**
* An interface for producing [Topology] instances. Implementors of this interface provide a way of generating a
@@ -31,10 +31,10 @@ package nl.atlarge.opendc.topology
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface TopologyFactory {
- /**
- * Create a [MutableTopology] instance.
- *
- * @return A mutable topology.
- */
- fun create(): MutableTopology
+ /**
+ * Create a [MutableTopology] instance.
+ *
+ * @return A mutable topology.
+ */
+ fun create(): MutableTopology
}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyListener.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt
index b5062709..0b4d43f7 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyListener.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt
@@ -22,7 +22,9 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology;
+package com.atlarge.opendc.model.topology;
+
+import com.atlarge.opendc.simulator.Entity
/**
* A listener interface for [Topology] instances. The methods of this interface are invoked on
@@ -31,31 +33,31 @@ package nl.atlarge.opendc.topology;
* @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
*/
interface TopologyListener {
- /**
- * This method is invoked when an [Entity] is added to the [Topology].
- *
- * @param node The entity that has been added to the [Topology].
- */
- fun Topology.onNodeAdded(node: Entity<*>) {}
+ /**
+ * This method is invoked when an [Entity] is added to the [Topology].
+ *
+ * @param node The entity that has been added to the [Topology].
+ */
+ fun Topology.onNodeAdded(node: Entity<*, Topology>) {}
- /**
- * This method is invoked when an [Entity] is removed from the [Topology].
- *
- * @param node The entity that has been removed from the [Topology].
- */
- fun Topology.onNodeRemoved(node: Entity<*>) {}
+ /**
+ * This method is invoked when an [Entity] is removed from the [Topology].
+ *
+ * @param node The entity that has been removed from the [Topology].
+ */
+ fun Topology.onNodeRemoved(node: Entity<*, Topology>) {}
- /**
- * This method is invoked when an [Edge] is added to the [Topology].
- *
- * @param edge The edge that has been added to the [Topology].
- */
- fun Topology.onEdgeAdded(edge: Edge<*>) {}
+ /**
+ * This method is invoked when an [Edge] is added to the [Topology].
+ *
+ * @param edge The edge that has been added to the [Topology].
+ */
+ fun Topology.onEdgeAdded(edge: Edge<*>) {}
- /**
- * This method is invoked when an [Edge] is removed from the [Topology].
- *
- * @param edge The entity that has been removed from the [Topology].
- */
- fun Topology.onEdgeRemoved(edge: Edge<*>) {}
+ /**
+ * This method is invoked when an [Edge] is removed from the [Topology].
+ *
+ * @param edge The entity that has been removed from the [Topology].
+ */
+ fun Topology.onEdgeRemoved(edge: Edge<*>) {}
}
diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Traversable.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Traversable.kt
index e57060ed..23720c46 100644
--- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Traversable.kt
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Traversable.kt
@@ -22,7 +22,7 @@
* SOFTWARE.
*/
-package nl.atlarge.opendc.topology
+package com.atlarge.opendc.model.topology
/**
* Filter a [Set] of [Edge]s based on the tag of the edges and return the origin nodes casted to type `T`.
diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt
new file mode 100644
index 00000000..0f6392ed
--- /dev/null
+++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt
@@ -0,0 +1,44 @@
+package com.atlarge.opendc.simulator
+
+import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn
+
+/**
+ * Try to find the [Context] instance associated with the [Process] in the call chain which has (indirectly) invoked the
+ * caller of this method.
+ *
+ * Note however that this method does not guarantee type-safety as this method allows the user to cast to a context
+ * with different generic type arguments.
+ *
+ * @return The context that has been found or `null` if this method is not called in a simulation context.
+ */
+suspend fun <S, M> contextOrNull(): Context<S, M>? = suspendCoroutineOrReturn { it.context[Context] }
+
+/**
+ * Find the [Context] instance associated with the [Process] in the call chain which has (indirectly) invoked the
+ * caller of this method.
+ *
+ * Note however that this method does not guarantee type-safety as this method allows the user to cast to a context
+ * with different generic type arguments.
+ *
+ * @throws IllegalStateException if the context cannot be found.
+ * @return The context that has been found.
+ */
+suspend fun <S, M> context(): Context<S, M> =
+ contextOrNull() ?: throw IllegalStateException("The suspending call does not have an associated process context")
+
+/**
+ * Try to find the untyped [Context] instance associated with the [Process] in the call chain which has (indirectly)
+ * invoked the caller of this method.
+ *
+ * @return The untyped context that has been found or `null` if this method is not called in a simulation context.
+ */
+suspend fun untypedContextOrNull(): Context<*, *>? = contextOrNull<Any?, Any?>()
+
+/**
+ * Find the [Context] instance associated with the [Process] in the call chain which has (indirectly) invoked the
+ * caller of this method.
+ *
+ * @throws IllegalStateException if the context cannot be found.
+ * @return The untyped context that has been found.
+ */
+suspend fun untypedContext(): Context<*, *> = context<Any?, Any?>()
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/FifoScheduler.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/FifoScheduler.kt
deleted file mode 100644
index 6f5db211..00000000
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/FifoScheduler.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.platform.scheduler
-
-import nl.atlarge.opendc.kernel.Context
-import nl.atlarge.opendc.platform.workload.Job
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.machine.Machine
-import nl.atlarge.opendc.platform.workload.Task
-import java.util.*
-
-/**
- * A [Scheduler] that distributes work according to the first-in-first-out principle.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-class FifoScheduler : Scheduler {
- /**
- * The name of this scheduler.
- */
- override val name: String = "FIFO"
-
- /**
- * The set of machines the scheduler knows of.
- */
- val machines: MutableSet<Machine> = HashSet()
-
- /**
- * The queue of [Task]s that need to be scheduled.
- */
- val queue: Queue<Task> = ArrayDeque()
-
- /**
- * (Re)schedule the tasks submitted to the scheduler over the specified set of machines.
- */
- override suspend fun <E : Entity<*>> Context<E>.schedule() {
- if (queue.isEmpty()) {
- return
- }
-
- // The tasks that need to be rescheduled
- val rescheduled = ArrayDeque<Task>()
- val iterator = queue.iterator()
-
- machines
- .filter { it.state.status != Machine.Status.HALT }
- .forEach { machine ->
- while (iterator.hasNext()) {
- val task = iterator.next()
-
- // TODO What to do with tasks that are not ready yet to be processed
- if (!task.ready) {
- iterator.remove()
- rescheduled.add(task)
- continue
- } else if (task.finished) {
- iterator.remove()
- continue
- }
-
- machine.send(task)
- break
- }
- }
-
- // Reschedule all tasks that are not ready yet
- while (!rescheduled.isEmpty()) {
- queue.add(rescheduled.poll())
- }
- }
-
- /**
- * Submit a [Task] to this scheduler.
- *
- * @param task The task to submit to the scheduler.
- */
- override fun submit(task: Task) {
- queue.add(task)
- }
-
- /**
- * Register a [Machine] to this scheduler.
- *
- * @param machine The machine to register.
- */
- override fun register(machine: Machine) {
- machines.add(machine)
- }
-
- /**
- * Deregister a [Machine] from this scheduler.
- *
- * @param machine The machine to deregister.
- */
- override fun deregister(machine: Machine) {
- machines.remove(machine)
- }
-}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/SrtfScheduler.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/SrtfScheduler.kt
deleted file mode 100644
index 1fbf8c04..00000000
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/SrtfScheduler.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.platform.scheduler
-
-import nl.atlarge.opendc.kernel.Context
-import nl.atlarge.opendc.platform.workload.Task
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.machine.Machine
-import java.util.*
-
-/**
- * A [Scheduler] that distributes work according to the shortest job first policy.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-class SrtfScheduler : Scheduler {
- /**
- * The name of this scheduler.
- */
- override val name: String = "SRTF"
-
- /**
- * The set of machines the scheduler knows of.
- */
- val machines: MutableSet<Machine> = HashSet()
-
- /**
- * The set of [Task]s that need to be scheduled.
- */
- val tasks: MutableSet<Task> = HashSet()
-
- /**
- * (Re)schedule the tasks submitted to the scheduler over the specified set of machines.
- */
- override suspend fun <E : Entity<*>> Context<E>.schedule() {
- if (tasks.isEmpty()) {
- return
- }
-
- val iterator = tasks.sortedBy { it.remaining }.iterator()
-
- machines
- .filter { it.state.status != Machine.Status.HALT }
- .forEach { machine ->
- while (iterator.hasNext()) {
- val task = iterator.next()
-
- // TODO What to do with tasks that are not ready yet to be processed
- if (!task.ready) {
- tasks.add(task)
- continue
- } else if (task.finished) {
- tasks.remove(task)
- continue
- }
-
- machine.send(task)
- break
- }
- }
- }
-
- /**
- * Submit a [Task] to this scheduler.
- *
- * @param task The task to submit to the scheduler.
- */
- override fun submit(task: Task) {
- tasks.add(task)
- }
-
- /**
- * Register a [Machine] to this scheduler.
- *
- * @param machine The machine to register.
- */
- override fun register(machine: Machine) {
- machines.add(machine)
- }
-
- /**
- * Deregister a [Machine] from this scheduler.
- *
- * @param machine The machine to deregister.
- */
- override fun deregister(machine: Machine) {
- machines.remove(machine)
- }
-}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Task.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Task.kt
deleted file mode 100644
index e740cdd8..00000000
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Task.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.platform.workload
-
-import nl.atlarge.opendc.kernel.time.Instant
-import nl.atlarge.opendc.topology.machine.Machine
-
-/**
- * A task that runs as part of a [Job] on a [Machine].
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Task {
- /**
- * The unique identifier of the task.
- */
- val id: Int
-
- /**
- * The amount of flops for this task.
- */
- val flops: Long
-
- /**
- * The dependencies of the task.
- */
- val dependencies: Set<Task>
-
- /**
- * A flag to indicate the task is parallelizable.
- */
- val parallelizable: Boolean
-
- /**
- * The remaining flops for this task.
- */
- val remaining: Long
-
- /**
- * The state of the task.
- */
- val state: TaskState
-
- /**
- * A flag to indicate whether the task is ready to be started.
- */
- val ready: Boolean
- get() = !dependencies.any { !it.finished }
-
- /**
- * A flag to indicate whether the task has finished.
- */
- val finished: Boolean
- get() = state is TaskState.Finished
-
- /**
- * This method is invoked when a task has arrived at a datacenter.
- *
- * @param time The moment in time the task has arrived at the datacenter.
- */
- fun arrive(time: Instant)
-
- /**
- * Consume the given amount of flops of this task.
- *
- * @param time The current moment in time of the consumption.
- * @param flops The total amount of flops to consume.
- */
- fun consume(time: Instant, flops: Long)
-}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/TaskState.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/TaskState.kt
deleted file mode 100644
index d1f908af..00000000
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/TaskState.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.platform.workload
-
-import nl.atlarge.opendc.kernel.time.Instant
-
-
-/**
- * This class hierarchy describes the states of a [Task].
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-sealed class TaskState {
- /**
- * A state to indicate the task has not yet arrived at the [Datacenter].
- */
- object Underway : TaskState()
-
- /**
- * A state to indicate the task has arrived at the [Datacenter].
- *
- * @property at The moment in time the task has arrived.
- */
- data class Queued(val at: Instant) : TaskState()
-
- /**
- * A state to indicate the task has started running on a machine.
- *
- * @property previous The previous state of the task.
- * @property at The moment in time the task started.
- */
- data class Running(val previous: Queued, val at: Instant) : TaskState()
-
- /**
- * A state to indicate the task has finished.
- *
- * @property previous The previous state of the task.
- * @property at The moment in time the task finished.
- */
- data class Finished(val previous: Running, val at: Instant) : TaskState()
-
- /**
- * A state to indicate the task has failed.
- *
- * @property previous The previous state of the task.
- * @property at The moment in time the task failed.
- * @property reason The reason of the failure.
- */
- data class Failed(val previous: Running, val at: Instant, val reason: String) : TaskState()
-}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Datacenter.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Datacenter.kt
deleted file mode 100644
index f7eb29d8..00000000
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Datacenter.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.topology.container
-
-import mu.KotlinLogging
-import nl.atlarge.opendc.topology.destinations
-import nl.atlarge.opendc.kernel.Context
-import nl.atlarge.opendc.kernel.Process
-import nl.atlarge.opendc.kernel.time.Duration
-import nl.atlarge.opendc.platform.scheduler.Scheduler
-import nl.atlarge.opendc.platform.workload.Task
-import nl.atlarge.opendc.topology.Entity
-import nl.atlarge.opendc.topology.machine.Machine
-import java.util.*
-
-/**
- * A representation of a facility used to house computer systems and associated components.
- *
- * @property scheduler The tasks scheduler the datacenter uses.
- * @property interval The interval at which task will be (re)scheduled.
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-interface Datacenter : Entity<Unit>, Process<Datacenter> {
- /**
- * The task scheduler the datacenter uses.
- */
- val scheduler: Scheduler
-
- /**
- * The interval at which task will be (re)scheduled.
- */
- val interval: Duration
-
- /**
- * This method is invoked to start the simulation an [Entity] associated with this [Process].
- *
- * This method is assumed to be running during a simulation, but should hand back control to the simulator at
- * some point by suspending the process. This allows other processes to do work in the current tick of the
- * simulation.
- * Suspending the process can be achieved by calling suspending method in the context:
- * - [Context.tick] - Wait for the next tick to occur
- * - [Context.wait] - Wait for `n` amount of ticks before resuming execution.
- * - [Context.receive] - Wait for a message to be received in the mailbox of the [Entity] before resuming
- * execution.
- *
- * If this method exits early, before the simulation has finished, the entity is assumed to be shutdown and its
- * simulation will not run any further.
- */
- suspend override fun Context<Datacenter>.run() {
- val logger = KotlinLogging.logger {}
-
- // The queue of messages to be processed after a cycle
- val queue: Queue<Any> = ArrayDeque()
- // Find all machines in the datacenter
- val machines = outgoingEdges.destinations<Room>("room").asSequence()
- .flatMap { it.outgoingEdges.destinations<Rack>("rack").asSequence() }
- .flatMap { it.outgoingEdges.destinations<Machine>("machine").asSequence() }.toList()
-
- logger.info { "Initialising datacenter with ${machines.size} machines" }
-
- // Register all machines to the scheduler
- machines.forEach(scheduler::register)
-
- while (true) {
- // Process all messages in the queue
- while (queue.isNotEmpty()) {
- val msg = queue.poll()
- if (msg is Task) {
- msg.arrive(time)
- scheduler.submit(msg)
- }
- }
- // (Re)schedule the tasks
- scheduler.run { schedule() }
-
- // Sleep a time quantum
- wait(interval, queue)
- }
- }
-}
diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Machine.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Machine.kt
deleted file mode 100644
index b5016adb..00000000
--- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Machine.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2017 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 nl.atlarge.opendc.topology.machine
-
-import mu.KotlinLogging
-import nl.atlarge.opendc.topology.destinations
-import nl.atlarge.opendc.platform.workload.Task
-import nl.atlarge.opendc.kernel.Context
-import nl.atlarge.opendc.kernel.Process
-import nl.atlarge.opendc.kernel.time.Duration
-import nl.atlarge.opendc.topology.Entity
-
-/**
- * A Physical Machine (PM) inside a rack of a datacenter. It has a speed, and can be given a workload on which it will
- * work until finished or interrupted.
- *
- * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl)
- */
-open class Machine : Entity<Machine.State>, Process<Machine> {
- /**
- * The logger instance to use for the simulator.
- */
- private val logger = KotlinLogging.logger {}
-
- /**
- * The status of a machine.
- */
- enum class Status {
- HALT, IDLE, RUNNING
- }
-
- /**
- * The shape of the state of a [Machine] entity.
- *
- * @property status The status of the machine.
- * @property task The task assign to the machine.
- * @property memory The memory usage of the machine (defaults to 50mb for the kernel)
- * @property load The load on the machine (defaults to 0.0)
- * @property temperature The temperature of the machine (defaults to 23 degrees Celcius)
- */
- data class State(val status: Status,
- val task: Task? = null,
- val memory: Int = 50,
- val load: Double = 0.0,
- val temperature: Double = 23.0)
-
- /**
- * The initial state of a [Machine] entity.
- */
- override val initialState = State(Status.HALT)
-
- /**
- * Run the simulation kernel for this entity.
- */
- override suspend fun Context<Machine>.run() {
- update(State(Status.IDLE))
-
- val interval: Duration = 10
- val cpus = outgoingEdges.destinations<Cpu>("cpu")
- val speed = cpus.fold(0, { acc, cpu -> acc + cpu.clockRate * cpu.cores })
-
- // Halt the machine if it has not processing units (see bug #4)
- if (cpus.isEmpty()) {
- update(State(Status.HALT))
- return
- }
-
- var task: Task = receiveTask()
- update(State(Status.RUNNING, task, load = 1.0, memory = state.memory + 50, temperature = 30.0))
-
- while (true) {
- if (task.finished) {
- logger.info { "${entity.id}: Task ${task.id} finished. Machine idle at $time" }
- update(State(Status.IDLE))
- task = receiveTask()
- } else {
- task.consume(time, speed * delta)
- }
-
- // Check if we have received a new order in the meantime.
- val msg = receive(interval)
- if (msg is Task) {
- task = msg
- update(State(Status.RUNNING, task, load = 1.0, memory = state.memory + 50, temperature = 30.0))
- }
- }
- }
-
- /**
- * Wait for a [Task] to be received by the [Process] and discard all other messages received in the meantime.
- *
- * @return The task that has been received.
- */
- private suspend fun Context<Machine>.receiveTask(): Task {
- while (true) {
- val msg = receive()
- if (msg is Task)
- return msg
- }
- }
-}
diff --git a/settings.gradle b/settings.gradle
index a92d3d2c..b507653b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -24,7 +24,8 @@
rootProject.name = "opendc-simulator"
include 'opendc-core'
-include 'opendc-omega'
+include 'opendc-kernel-omega'
include 'opendc-stdlib'
-include 'opendc-integration-jpa:core'
-include 'opendc-integration-jpa:mysql'
+include 'opendc-model-odc:core'
+include 'opendc-model-odc:jpa'
+include 'opendc-model-odc:setup'