From b1c4d1f94e35445bdba5a56b614d0ec28a332624 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 11 Jan 2018 16:27:05 +0100 Subject: 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. --- opendc-core/build.gradle | 8 +- .../com/atlarge/opendc/simulator/Bootstrap.kt | 64 ++++ .../kotlin/com/atlarge/opendc/simulator/Context.kt | 184 ++++++++++ .../kotlin/com/atlarge/opendc/simulator/Entity.kt | 44 +++ .../kotlin/com/atlarge/opendc/simulator/Process.kt | 27 ++ .../kotlin/com/atlarge/opendc/simulator/Time.kt | 35 ++ .../com/atlarge/opendc/simulator/kernel/Kernel.kt | 79 ++++ .../opendc/simulator/kernel/KernelFactory.kt | 42 +++ .../opendc/simulator/platform/Experiment.kt | 52 +++ .../kotlin/nl/atlarge/opendc/kernel/Context.kt | 120 ------- .../kotlin/nl/atlarge/opendc/kernel/Interrupt.kt | 32 -- .../main/kotlin/nl/atlarge/opendc/kernel/Kernel.kt | 50 --- .../kotlin/nl/atlarge/opendc/kernel/Process.kt | 51 --- .../kotlin/nl/atlarge/opendc/kernel/Simulation.kt | 100 ------ .../nl/atlarge/opendc/kernel/messaging/Envelope.kt | 50 --- .../nl/atlarge/opendc/kernel/messaging/Readable.kt | 75 ---- .../nl/atlarge/opendc/kernel/messaging/Receipt.kt | 53 --- .../nl/atlarge/opendc/kernel/messaging/Writable.kt | 54 --- .../nl/atlarge/opendc/kernel/sampler/Sampler.kt | 40 --- .../kotlin/nl/atlarge/opendc/kernel/time/Clock.kt | 79 ---- .../nl/atlarge/opendc/kernel/time/TickClock.kt | 60 ---- .../kotlin/nl/atlarge/opendc/kernel/time/Time.kt | 35 -- .../nl/atlarge/opendc/platform/Experiment.kt | 52 --- .../nl/atlarge/opendc/topology/AdjacencyList.kt | 258 ------------- .../kotlin/nl/atlarge/opendc/topology/Component.kt | 33 -- .../main/kotlin/nl/atlarge/opendc/topology/Edge.kt | 59 --- .../kotlin/nl/atlarge/opendc/topology/Entity.kt | 44 --- .../nl/atlarge/opendc/topology/MutableTopology.kt | 62 ---- .../kotlin/nl/atlarge/opendc/topology/Topology.kt | 48 --- .../nl/atlarge/opendc/topology/TopologyBuilder.kt | 40 --- .../nl/atlarge/opendc/topology/TopologyContext.kt | 48 --- .../nl/atlarge/opendc/topology/TopologyFactory.kt | 40 --- .../nl/atlarge/opendc/topology/TopologyListener.kt | 61 ---- .../nl/atlarge/opendc/topology/Traversable.kt | 41 --- opendc-integration-jpa/core/build.gradle | 90 ----- .../nl/atlarge/opendc/integration/jpa/Jpa.kt | 38 -- .../jpa/converter/ParallelizableConverter.kt | 62 ---- .../jpa/converter/SchedulerConverter.kt | 66 ---- .../atlarge/opendc/integration/jpa/schema/Cpu.kt | 58 --- .../opendc/integration/jpa/schema/Datacenter.kt | 66 ---- .../opendc/integration/jpa/schema/Experiment.kt | 60 ---- .../integration/jpa/schema/ExperimentState.kt | 53 --- .../atlarge/opendc/integration/jpa/schema/Gpu.kt | 58 --- .../atlarge/opendc/integration/jpa/schema/Job.kt | 59 --- .../opendc/integration/jpa/schema/Machine.kt | 45 --- .../opendc/integration/jpa/schema/MachineState.kt | 53 --- .../atlarge/opendc/integration/jpa/schema/Path.kt | 40 --- .../atlarge/opendc/integration/jpa/schema/Rack.kt | 52 --- .../atlarge/opendc/integration/jpa/schema/Room.kt | 50 --- .../opendc/integration/jpa/schema/RoomObject.kt | 36 -- .../opendc/integration/jpa/schema/RoomType.kt | 34 -- .../opendc/integration/jpa/schema/Section.kt | 45 --- .../atlarge/opendc/integration/jpa/schema/Task.kt | 117 ------ .../opendc/integration/jpa/schema/TaskState.kt | 49 --- .../atlarge/opendc/integration/jpa/schema/Trace.kt | 44 --- .../nl/atlarge/opendc/platform/JpaExperiment.kt | 192 ---------- .../opendc/platform/JpaExperimentManager.kt | 93 ----- .../atlarge/opendc/platform/JpaPlatformRunner.kt | 65 ---- .../atlarge/opendc/topology/JpaTopologyFactory.kt | 87 ----- .../core/src/main/resources/jpa/schema.xml | 324 ----------------- opendc-integration-jpa/mysql/Dockerfile | 30 -- opendc-integration-jpa/mysql/build.gradle | 38 -- .../src/main/resources/META-INF/persistence.xml | 41 --- opendc-kernel-omega/build.gradle | 86 +++++ .../com/atlarge/opendc/omega/MessageContainer.kt | 48 +++ .../kotlin/com/atlarge/opendc/omega/OmegaKernel.kt | 315 ++++++++++++++++ .../com/atlarge/opendc/omega/OmegaKernelFactory.kt | 47 +++ .../main/kotlin/com/atlarge/opendc/omega/Resume.kt | 39 ++ .../kotlin/com/atlarge/opendc/omega/Timeout.kt | 35 ++ .../kotlin/com/atlarge/opendc/omega/SmokeTest.kt | 116 ++++++ opendc-model-odc/core/build.gradle | 87 +++++ .../com/atlarge/opendc/model/odc/OdcModel.kt | 10 + .../model/odc/platform/scheduler/FifoScheduler.kt | 118 ++++++ .../model/odc/platform/scheduler/Scheduler.kt | 71 ++++ .../model/odc/platform/scheduler/SrtfScheduler.kt | 110 ++++++ .../opendc/model/odc/platform/workload/Job.kt | 53 +++ .../opendc/model/odc/platform/workload/Task.kt | 92 +++++ .../model/odc/platform/workload/TaskState.kt | 72 ++++ .../opendc/model/odc/platform/workload/Trace.kt | 37 ++ .../opendc/model/odc/platform/workload/User.kt | 45 +++ .../model/odc/topology/container/Datacenter.kt | 102 ++++++ .../opendc/model/odc/topology/container/Rack.kt | 36 ++ .../opendc/model/odc/topology/container/Room.kt | 35 ++ .../opendc/model/odc/topology/machine/Cpu.kt | 32 ++ .../opendc/model/odc/topology/machine/Gpu.kt | 33 ++ .../opendc/model/odc/topology/machine/Machine.kt | 123 +++++++ .../model/odc/topology/machine/ProcessingUnit.kt | 50 +++ .../model/odc/topology/network/NetworkUnit.kt | 35 ++ .../opendc/model/odc/topology/power/PowerUnit.kt | 35 ++ .../model/odc/topology/storage/StorageUnit.kt | 35 ++ opendc-model-odc/jpa/build.gradle | 89 +++++ .../com/atlarge/opendc/model/odc/JpaBootstrap.kt | 44 +++ .../com/atlarge/opendc/model/odc/JpaModel.kt | 14 + .../opendc/model/odc/integration/jpa/Jpa.kt | 38 ++ .../jpa/converter/ParallelizableConverter.kt | 62 ++++ .../jpa/converter/SchedulerConverter.kt | 66 ++++ .../opendc/model/odc/integration/jpa/schema/Cpu.kt | 58 +++ .../model/odc/integration/jpa/schema/Datacenter.kt | 66 ++++ .../model/odc/integration/jpa/schema/Experiment.kt | 58 +++ .../odc/integration/jpa/schema/ExperimentState.kt | 53 +++ .../opendc/model/odc/integration/jpa/schema/Gpu.kt | 58 +++ .../opendc/model/odc/integration/jpa/schema/Job.kt | 58 +++ .../model/odc/integration/jpa/schema/Machine.kt | 45 +++ .../odc/integration/jpa/schema/MachineState.kt | 53 +++ .../model/odc/integration/jpa/schema/Path.kt | 40 +++ .../model/odc/integration/jpa/schema/Rack.kt | 52 +++ .../model/odc/integration/jpa/schema/Room.kt | 50 +++ .../model/odc/integration/jpa/schema/RoomObject.kt | 36 ++ .../model/odc/integration/jpa/schema/RoomType.kt | 34 ++ .../model/odc/integration/jpa/schema/Section.kt | 45 +++ .../model/odc/integration/jpa/schema/Task.kt | 117 ++++++ .../model/odc/integration/jpa/schema/TaskState.kt | 49 +++ .../model/odc/integration/jpa/schema/Trace.kt | 44 +++ .../opendc/model/odc/platform/JpaExperiment.kt | 179 +++++++++ .../model/odc/platform/JpaExperimentManager.kt | 93 +++++ .../model/odc/topology/JpaTopologyFactory.kt | 95 +++++ .../jpa/src/main/resources/jpa/schema.xml | 324 +++++++++++++++++ opendc-model-odc/setup/Dockerfile | 30 ++ opendc-model-odc/setup/build.gradle | 87 +++++ .../src/main/kotlin/platform/JpaPlatformRunner.kt | 66 ++++ .../src/main/resources/META-INF/persistence.xml | 41 +++ opendc-omega/build.gradle | 87 ----- .../opendc/kernel/omega/MessageContainer.kt | 68 ---- .../nl/atlarge/opendc/kernel/omega/OmegaKernel.kt | 58 --- .../atlarge/opendc/kernel/omega/OmegaSimulation.kt | 398 --------------------- .../nl/atlarge/opendc/kernel/omega/Resume.kt | 38 -- .../nl/atlarge/opendc/kernel/omega/Timeout.kt | 33 -- .../src/test/kotlin/nl/atlarge/opendc/SmokeTest.kt | 115 ------ opendc-stdlib/build.gradle | 6 +- .../atlarge/opendc/model/topology/AdjacencyList.kt | 260 ++++++++++++++ .../com/atlarge/opendc/model/topology/Bootstrap.kt | 23 ++ .../com/atlarge/opendc/model/topology/Component.kt | 33 ++ .../com/atlarge/opendc/model/topology/Edge.kt | 61 ++++ .../opendc/model/topology/MutableTopology.kt | 65 ++++ .../com/atlarge/opendc/model/topology/Topology.kt | 50 +++ .../opendc/model/topology/TopologyBuilder.kt | 40 +++ .../opendc/model/topology/TopologyContext.kt | 50 +++ .../opendc/model/topology/TopologyFactory.kt | 40 +++ .../opendc/model/topology/TopologyListener.kt | 63 ++++ .../atlarge/opendc/model/topology/Traversable.kt | 41 +++ .../opendc/platform/scheduler/FifoScheduler.kt | 120 ------- .../atlarge/opendc/platform/scheduler/Scheduler.kt | 71 ---- .../opendc/platform/scheduler/SrtfScheduler.kt | 111 ------ .../nl/atlarge/opendc/platform/workload/Job.kt | 53 --- .../nl/atlarge/opendc/platform/workload/Task.kt | 92 ----- .../atlarge/opendc/platform/workload/TaskState.kt | 72 ---- .../nl/atlarge/opendc/platform/workload/Trace.kt | 37 -- .../nl/atlarge/opendc/platform/workload/User.kt | 45 --- .../opendc/topology/container/Datacenter.kt | 102 ------ .../nl/atlarge/opendc/topology/container/Rack.kt | 35 -- .../nl/atlarge/opendc/topology/container/Room.kt | 34 -- .../nl/atlarge/opendc/topology/machine/Cpu.kt | 32 -- .../nl/atlarge/opendc/topology/machine/Gpu.kt | 33 -- .../nl/atlarge/opendc/topology/machine/Machine.kt | 123 ------- .../opendc/topology/machine/ProcessingUnit.kt | 49 --- .../atlarge/opendc/topology/network/NetworkUnit.kt | 34 -- .../nl/atlarge/opendc/topology/power/PowerUnit.kt | 34 -- .../atlarge/opendc/topology/storage/StorageUnit.kt | 34 -- settings.gradle | 7 +- 159 files changed, 5305 insertions(+), 5548 deletions(-) create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Time.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Context.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Interrupt.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Kernel.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Process.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/Simulation.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Envelope.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Readable.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Receipt.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Writable.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/sampler/Sampler.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Clock.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/TickClock.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Time.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/AdjacencyList.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Component.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Edge.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Entity.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/MutableTopology.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Topology.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyBuilder.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyContext.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyFactory.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyListener.kt delete mode 100644 opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Traversable.kt delete mode 100644 opendc-integration-jpa/core/build.gradle delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/Jpa.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/ParallelizableConverter.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/SchedulerConverter.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Cpu.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Datacenter.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Experiment.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/ExperimentState.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Gpu.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Job.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Machine.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/MachineState.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Path.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Rack.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Room.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomObject.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomType.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Section.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Task.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/TaskState.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Trace.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperiment.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaExperimentManager.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt delete mode 100644 opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/topology/JpaTopologyFactory.kt delete mode 100644 opendc-integration-jpa/core/src/main/resources/jpa/schema.xml delete mode 100644 opendc-integration-jpa/mysql/Dockerfile delete mode 100644 opendc-integration-jpa/mysql/build.gradle delete mode 100644 opendc-integration-jpa/mysql/src/main/resources/META-INF/persistence.xml create mode 100644 opendc-kernel-omega/build.gradle create mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt create mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt create mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt create mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt create mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt create mode 100644 opendc-kernel-omega/src/test/kotlin/com/atlarge/opendc/omega/SmokeTest.kt create mode 100644 opendc-model-odc/core/build.gradle create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/OdcModel.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/FifoScheduler.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/SrtfScheduler.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Task.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/TaskState.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Datacenter.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Cpu.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Gpu.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Machine.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt create mode 100644 opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt create mode 100644 opendc-model-odc/jpa/build.gradle create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaBootstrap.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaModel.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomObject.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Task.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperiment.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperimentManager.kt create mode 100644 opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/topology/JpaTopologyFactory.kt create mode 100644 opendc-model-odc/jpa/src/main/resources/jpa/schema.xml create mode 100644 opendc-model-odc/setup/Dockerfile create mode 100644 opendc-model-odc/setup/build.gradle create mode 100644 opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt create mode 100644 opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml delete mode 100644 opendc-omega/build.gradle delete mode 100644 opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/MessageContainer.kt delete mode 100644 opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaKernel.kt delete mode 100644 opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaSimulation.kt delete mode 100644 opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Resume.kt delete mode 100644 opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/Timeout.kt delete mode 100644 opendc-omega/src/test/kotlin/nl/atlarge/opendc/SmokeTest.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/AdjacencyList.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Bootstrap.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Component.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/MutableTopology.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Traversable.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/FifoScheduler.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/Scheduler.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/SrtfScheduler.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Job.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Task.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/TaskState.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Trace.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/User.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Datacenter.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Rack.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Room.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Cpu.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Gpu.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Machine.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/ProcessingUnit.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/network/NetworkUnit.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/power/PowerUnit.kt delete mode 100644 opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/storage/StorageUnit.kt diff --git a/opendc-core/build.gradle b/opendc-core/build.gradle index 92cdb2c4..f1eac0da 100644 --- a/opendc-core/build.gradle +++ b/opendc-core/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.1.4-3' + ext.kotlin_version = '1.2.10' ext.dokka_version = '0.9.15' repositories { @@ -68,8 +68,8 @@ dokka { } /* Project configuration */ -group 'nl.atlarge.opendc' -version '1.0' +group 'com.atlarge.opendc' +version '1.1' repositories { jcenter() @@ -78,7 +78,7 @@ repositories { 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.kotlinx:kotlinx-coroutines-core:0.21" testCompile "org.junit.jupiter:junit-jupiter-api:5.0.0-RC3" testRuntime "org.junit.jupiter:junit-jupiter-engine:5.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..199e1701 --- /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 { + /** + * Bootstrap a model `M` for a kernel in the given context. + * + * @param context The context to bootstrap to model in. + * @return The initialised model for the simulation. + */ + fun bootstrap(context: Context): M + + /** + * A context for the bootstrap 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 { + /** + * 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 for processing by a [Context]. + * + * @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 bootstrap for a model of type `M`. + * + * @param block The block to produce the bootstrap. + * @return The bootstrap procedure that has been built. + */ + fun create(block: (Context) -> M): Bootstrap = object : Bootstrap { + override fun bootstrap(context: Context) = 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..c4e906dd --- /dev/null +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt @@ -0,0 +1,184 @@ +/* + * 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.Queue + +/** + * 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 { + /** + * 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 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 , 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. + */ + suspend fun Entity<*, *>.interrupt() + + /** + * 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) + + /** + * 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 after which the message [Envelope] is + * transformed through `transform` to return the transformed result. + * + * @param transform The block to transform the message with in an envelope context, providing access to the sender + * of the message. + * @return The transformed message. + */ + suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T + + /** + * 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 after which the message + * [Envelope] is transformed through `transform` to return the transformed result or the timeout has been reached. + * + * @param timeout The duration to wait before resuming execution. + * @param transform The block to transform the message with in an envelope context, providing access to the sender + * of the message. + * @return The processed message or `null` if the timeout was reached. + */ + suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? + + /** + * 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 = receive { it } + + /** + * 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? = receive(timeout) { it } + + /** + * 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 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) +} + +/** + * The message envelope that is sent to an [Entity], also containing the metadata of the message. + * + * @param T The shape of the message inside the envelope. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Envelope { + /** + * The message in this envelope. + */ + val message: T + + /** + * The sender of the message. + */ + val sender: Entity<*, *>? + + /** + * The destination of the message. + */ + val destination: Entity<*, *> +} + +/** + * An [Interrupt] message is sent to a [Entity] process in order to interrupt its suspended state. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +object Interrupt: Throwable("The entity process has been interrupted by another entity") diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt new file mode 100644 index 00000000..800f2f1d --- /dev/null +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt @@ -0,0 +1,44 @@ +/* + * 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 + +/** + * An entity in some model `M`. + * + *

A [Entity] directly contains its immutable properties that remain unchanged during simulation. + * + *

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 { + /** + * 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..30280657 --- /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: Entity { + /** + * 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.run() +} diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Time.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Time.kt new file mode 100644 index 00000000..64e3cb80 --- /dev/null +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Time.kt @@ -0,0 +1,35 @@ +/* + * 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 + +/** + * An instantaneous point on the time-line, used to record event time-stamps in a simulation. + */ +typealias Instant = Long + +/** + * A time interval which represents the amount of elapsed time between two events. + */ +typealias Duration = Long diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt new file mode 100644 index 00000000..3eee0f67 --- /dev/null +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt @@ -0,0 +1,79 @@ +/* + * 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.Bootstrap +import com.atlarge.opendc.simulator.Instant +import com.atlarge.opendc.simulator.Entity + +/** + * A message based discrete event simulation kernel. + * + * The kernel is created by bootstrapping some model `M` (see [Bootstrap]) to simulate and controls the simulation by + * allowing the user to step over cycles in the simulation and inspect the internal state using [Entity.state]. + * + * A kernel should provide additionally a [KernelFactory] to create new kernel instances given a certain model + * [Bootstrap]. + * + * @param M The shape of the model over which the simulation runs. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Kernel { + /** + * 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 , 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/com/atlarge/opendc/simulator/kernel/KernelFactory.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt new file mode 100644 index 00000000..93667eb8 --- /dev/null +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt @@ -0,0 +1,42 @@ +/* + * 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.Bootstrap + +/** + * A factory for bootstrapping simulation [Kernel] instances. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface KernelFactory { + /** + * Create a simulation over the given model facilitated by this simulation kernel. + * + * @param bootstrap The bootstrap procedure to bootstrap the simulation with. + * @return A [Kernel] instance to control the simulation. + */ + fun create(bootstrap: Bootstrap): Kernel +} diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt new file mode 100644 index 00000000..88b606fd --- /dev/null +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt @@ -0,0 +1,52 @@ +/* + * 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.platform + +import com.atlarge.opendc.simulator.kernel.KernelFactory +import com.atlarge.opendc.simulator.Duration + +/** + * A blueprint for a reproducible simulation in a pre-defined setting. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Experiment { + /** + * 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: KernelFactory): 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: KernelFactory, 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> : 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 , 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 , E : Entity, 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) - - /** - * 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> { - /** - * 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.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 , 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/Envelope.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Envelope.kt deleted file mode 100644 index 608d325f..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/messaging/Envelope.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.messaging - -import nl.atlarge.opendc.topology.Entity - -/** - * The envelope of a message that is sent to an [Entity], also containing the metadata of the message. - * - * @param T The shape of the message inside the envelope. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Envelope { - /** - * The message in this envelope. - */ - val message: T - - /** - * The sender of the message. - */ - val sender: Entity<*>? - - /** - * The destination of the message. - */ - val destination: Entity<*> -} 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 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 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. - * - *

[Sampler]s work by observing [Entity] instances in the simulation and transforming this stream of events into a - * stream of data points. - * - *

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 The data type of result generated by this sampler. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Sampler 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/kernel/time/Time.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Time.kt deleted file mode 100644 index af9d547b..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/kernel/time/Time.kt +++ /dev/null @@ -1,35 +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 - -/** - * An instantaneous point on the time-line, used to record event time-stamps in a simulation. - */ -typealias Instant = Long - -/** - * A time interval which represents the amount of elapsed time between two events. - */ -typealias Duration = Long diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt deleted file mode 100644 index 6aed5364..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/platform/Experiment.kt +++ /dev/null @@ -1,52 +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.kernel.Kernel -import nl.atlarge.opendc.kernel.time.Duration - -/** - * A blueprint for a reproducible simulation in a pre-defined setting. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Experiment { - /** - * Run the experiment on the specified simulation [Kernel]. - * - * @param kernel The simulation kernel to run the experiment. - * @return The result of the experiment. - */ - fun run(kernel: Kernel): T - - /** - * Run the experiment on the specified simulation [Kernel]. - * - * @param kernel The simulation kernel to run the experiment. - * @param timeout The maximum duration of the experiment before returning to the caller. - * @return The result of the experiment or `null`. - */ - fun run(kernel: Kernel, timeout: Duration): T? -} diff --git a/opendc-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, Node> = HashMap() - - // Topology - - /** - * The listeners of this topology. - */ - override val listeners: MutableSet = 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> - get() = nodes[this]!!.ingoingEdges - - /** - * The set of outgoing edges of this node. - */ - override val Entity<*>.outgoingEdges: MutableSet> - 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 connect(from: Entity<*>, to: Entity<*>, label: T, tag: String?): BaseEdge { - 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>): 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>): 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>): 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>): 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> = nodes.keys.iterator() - - /** - * The internal representation of a node within the graph. - */ - internal data class Node(val id: Int) { - val ingoingEdges: MutableSet> = HashSet() - val outgoingEdges: MutableSet> = HashSet() - } - - /** - * The internal representation of an edge within the graph. - */ - internal class Edge(override val label: T, - override val tag: String?, - override val from: Entity<*>, - override val to: Entity<*>) : BaseEdge -} diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Component.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Component.kt deleted file mode 100644 index 3c383892..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Component.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.topology - -/** - * A component within a [Topology], which is either a node or an [Edge] representing the relationship between - * entities within a logical topology of a cloud network. - ** - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Component diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Edge.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Edge.kt deleted file mode 100644 index 3be14dec..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Edge.kt +++ /dev/null @@ -1,59 +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 - -/** - * An edge that represents a directed relationship between exactly two nodes in a logical topology of a cloud network. - * - * @param T The relationship type the edge represents within a logical topology. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Edge : Component { - /** - * The label of this edge. - */ - val label: T - - /** - * 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 O(1), but must be at least - * O(n), with respect to the size of the topology. - */ - val from: Entity<*> - - /** - * The destination of the edge. - * - * This property is not guaranteed to have a runtime complexity of O(1), but must be at least - * O(n), with respect to the size of the topology. - */ - val to: Entity<*> -} diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Entity.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Entity.kt deleted file mode 100644 index 66a31d77..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Entity.kt +++ /dev/null @@ -1,44 +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 - -/** - * An entity within a cloud network, represented as a node within a topology. - * - *

A [Entity] contains immutable properties given by the topology configuration at the start of a simulation and - * remain unchanged during simulation. - * - *

In addition, other entities in a 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. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Entity : Component { - /** - * The initial state of the entity. - */ - val initialState: S -} 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> { - /** - * 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 connect(from: Entity<*>, to: Entity<*>, label: T, tag: String? = null): Edge - - /** - * 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 = 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 = connect(this, dest) -} diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Topology.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Topology.kt deleted file mode 100644 index 27c1c889..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Topology.kt +++ /dev/null @@ -1,48 +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 graph data structure which represents the logical topology of a cloud network consisting of one or more - * datacenters. - * - * A topology is [Iterable] and allows implementation-dependent iteration of the nodes in the topology. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Topology : TopologyContext, Cloneable, Set> { - /** - * The listeners of this topology. - */ - val listeners: MutableSet - - /** - * 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-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyBuilder.kt deleted file mode 100644 index bb9c7e8e..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyBuilder.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.topology - -/** - * A builder for [Topology] instances. - * - * @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) -} diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyContext.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyContext.kt deleted file mode 100644 index 22e7dd94..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyContext.kt +++ /dev/null @@ -1,48 +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 [TopologyContext] represents the context for entities in a specific topology, providing access to the identifier - * and ingoing and outgoing edges of the [Entity] within a [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 - - /** - * The set of ingoing edges of an [Entity]. - */ - val Entity<*>.ingoingEdges: Set> - - /** - * The set of outgoing edges of an [Entity]. - */ - val Entity<*>.outgoingEdges: Set> -} diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyFactory.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyFactory.kt deleted file mode 100644 index 42b30a94..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyFactory.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.topology - -/** - * An interface for producing [Topology] instances. Implementors of this interface provide a way of generating a - * topology based on the state of the factory. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface TopologyFactory { - /** - * 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-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyListener.kt deleted file mode 100644 index b5062709..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/TopologyListener.kt +++ /dev/null @@ -1,61 +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 listener interface for [Topology] instances. The methods of this interface are invoked on - * mutation of the topology the listener is listening to. - * - * @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 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 [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<*>) {} -} diff --git a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Traversable.kt b/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Traversable.kt deleted file mode 100644 index e57060ed..00000000 --- a/opendc-core/src/main/kotlin/nl/atlarge/opendc/topology/Traversable.kt +++ /dev/null @@ -1,41 +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 - -/** - * Filter a [Set] of [Edge]s based on the tag of the edges and return the origin nodes casted to type `T`. - * - * @param tag The tag of the edges to get. - * @return An [Iterable] of the specified type `T` with the given tag. - */ -inline fun Set>.origins(tag: String) = filter { it.tag == tag }.map { it.from as T } - -/** - * Filter a [Set] of [Edge]s based on the tag of the edges and return the destination nodes casted to type `T`. - * - * @param tag The tag of the edges to get. - * @return An [Iterable] of the specified type `T` with the given tag. - */ -inline fun Set>.destinations(tag: String) = filter { it.tag == tag }.map { it.to as T } diff --git a/opendc-integration-jpa/core/build.gradle b/opendc-integration-jpa/core/build.gradle deleted file mode 100644 index ed510560..00000000 --- a/opendc-integration-jpa/core/build.gradle +++ /dev/null @@ -1,90 +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. - */ - -/* Build configuration */ -buildscript { - ext.kotlin_version = '1.1.4-3' - 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 'nl.atlarge.opendc' -version '1.0' - -repositories { - 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' - - 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/Jpa.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/Jpa.kt deleted file mode 100644 index cbbe280a..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/Jpa.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.integration.jpa - -import javax.persistence.EntityManager - -/** - * Run the given block in a transaction, committing on return of the block. - * - * @param block The block to execute in the transaction. - */ -inline fun EntityManager.transaction(block: () -> Unit) { - 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/ParallelizableConverter.kt deleted file mode 100644 index 11d5836e..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/ParallelizableConverter.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.integration.jpa.converter - -import javax.persistence.AttributeConverter - -/** - * An internal [AttributeConverter] that maps the values _PARALLEL_ and _SEQUENTIAL_ to a - * boolean value indicating whether a task is parallelizable. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -class ParallelizableConverter : AttributeConverter { - /** - * 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" -} diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/SchedulerConverter.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/SchedulerConverter.kt deleted file mode 100644 index 95027440..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/converter/SchedulerConverter.kt +++ /dev/null @@ -1,66 +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.converter - -import nl.atlarge.opendc.platform.scheduler.FifoScheduler -import nl.atlarge.opendc.platform.scheduler.Scheduler -import nl.atlarge.opendc.platform.scheduler.SrtfScheduler -import javax.persistence.AttributeConverter - -/** - * An internal [AttributeConverter] that maps a name of a scheduler to the actual scheduler implementation. - * The converter currently chooses between the following two schedulers: - * - [FifoScheduler] (default) - * - [SrtfScheduler] - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -class SchedulerConverter : AttributeConverter { - /** - * 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" -} diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Cpu.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Cpu.kt deleted file mode 100644 index b775eb6e..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Cpu.kt +++ /dev/null @@ -1,58 +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.topology.machine.Cpu -import javax.persistence.Entity - -/** - * A cpu entity in the persistent schema. - * - * @property id The unique identifier of the cpu. - * @property manufacturer The manufacturer of the cpu. - * @property family The family of the cpu. - * @property generation The generation of the cpu. - * @property model The model of the cpu. - * @property clockRate The clock rate of the cpu. - * @property cores The amount of cores in the gpu. - * @property energyConsumption The energy consumption of the cpu in Watt. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@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 -) : Cpu { - /** - * 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Datacenter.kt deleted file mode 100644 index 1e6eaa2b..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Datacenter.kt +++ /dev/null @@ -1,66 +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.Duration -import nl.atlarge.opendc.platform.scheduler.Scheduler -import nl.atlarge.opendc.topology.container.Datacenter -import javax.persistence.Entity - -/** - * A datacenter entity in the persistent schema. - * - * @property id The unique identifier of the datacenter. - * @property rooms The rooms in the datacenter. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class Datacenter( - val id: Int, - val rooms: Set -): 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 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 -} diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Experiment.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Experiment.kt deleted file mode 100644 index 0b352cb4..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Experiment.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.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 javax.persistence.Entity - -/** - * An experiment definition for the OpenDC database schema. - * - * @property id The identifier of the experiment. - * @property name The name of the experiment. - * @property scheduler The scheduler used in the experiment. - * @property trace The trace used for the simulation. - * @property path The path of the experiment. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class Experiment( - 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 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/ExperimentState.kt deleted file mode 100644 index 96fc112c..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/ExperimentState.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.integration.jpa.schema - -/** - * Enumerations of the states an [Experiment] can assume. - * - * @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 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 has finished simulating. - */ - FINISHED, -} diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Gpu.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Gpu.kt deleted file mode 100644 index 94625242..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Gpu.kt +++ /dev/null @@ -1,58 +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.topology.machine.Gpu -import javax.persistence.Entity - -/** - * A gpu entity in the persistent schema. - * - * @property id The unique identifier of the gpu. - * @property manufacturer The manufacturer of the gpu. - * @property family The family of the gpu. - * @property generation The generation of the gpu. - * @property model The model of the gpu. - * @property clockRate The clock rate of the gpu. - * @property cores The amount of cores in the gpu. - * @property energyConsumption The energy consumption of the gpu in Watt. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@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 -) : Gpu { - /** - * 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Job.kt deleted file mode 100644 index 394cf478..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Job.kt +++ /dev/null @@ -1,59 +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.platform.workload.Job -import nl.atlarge.opendc.platform.workload.Task -import nl.atlarge.opendc.platform.workload.User -import javax.persistence.* - -/** - * A [Job] backed by the JPA API and an underlying database connection. - * - * @property id The unique identifier of the job. - * @property tasks The collection of tasks the job consists of. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class Job( - override val id: Int, - override val tasks: Set -) : 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 unique identifier of the user. - */ - override val id: Int = 0 - - /** - * The name of this user. - */ - 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Machine.kt deleted file mode 100644 index 4071b342..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Machine.kt +++ /dev/null @@ -1,45 +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.topology.machine.Machine -import javax.persistence.Entity - -/** - * A machine entity in the persistent schema. - * - * @property id The unique identifier of the machine. - * @property position The position of the machine in the rack. - * @property cpus The CPUs in the machine. - * @property gpus The GPUs in the machine. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class Machine( - val id: Int, - val position: Int, - val cpus: Set, - val gpus: Set -): Machine() diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/MachineState.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/MachineState.kt deleted file mode 100644 index 23efe888..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/MachineState.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.integration.jpa.schema - -import nl.atlarge.opendc.kernel.time.Instant -import javax.persistence.Entity - -/** - * The state of a [Machine]. - * - * @property id The unique identifier of the state. - * @property machine The machine of the state. - * @property task The task the machine has been assigned. - * @property experiment The experiment the machine is running in. - * @property time The current moment in time. - * @property temperature The temperature of the machine. - * @property memoryUsage The memory usage of the machine. - * @property load The load of the machine. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@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 -) diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Path.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Path.kt deleted file mode 100644 index ccf3b6e8..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Path.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.integration.jpa.schema - -import javax.persistence.Entity - -/** - * A [Path] holds all sections of the parent experiment. - * - * @property id The unique identifier of the path. - * @property sections The sections of the path. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -open class Path( - val id: Int, - val sections: List

-) diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Rack.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Rack.kt deleted file mode 100644 index 2d2099a2..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Rack.kt +++ /dev/null @@ -1,52 +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.topology.container.Rack -import javax.persistence.Entity - -/** - * A rack entity in a room in the persistent schema. - * - * @property id The unique identifier of the rack. - * @property name The name of the rack. - * @property capacity The capacity of the rack in terms of units. - * @property powerCapacity The power capacity of the rack in Watt. - * @property machines The machines in the rack. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -class Rack( - id: Int, - val name: String, - val capacity: Int, - val powerCapacity: Int, - val machines: List -): 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Room.kt deleted file mode 100644 index f3b7ae06..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Room.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.integration.jpa.schema - -import nl.atlarge.opendc.topology.container.Room -import javax.persistence.Entity - -/** - * A room entity in the persistent schema. - * - * @property id The unique identifier of the room. - * @property name The name of the room. - * @property type The type of the room. - * @property objects The objects in the room. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class Room( - val id: Int, - val name: String, - val type: RoomType, - val objects: Set -): 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomObject.kt deleted file mode 100644 index 0e9fb84f..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomObject.kt +++ /dev/null @@ -1,36 +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 javax.persistence.Entity - -/** - * An object in a room. - * - * @property id The unique identifier of the room. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -abstract class RoomObject(val id: Int) diff --git a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomType.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomType.kt deleted file mode 100644 index 5e138947..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/RoomType.kt +++ /dev/null @@ -1,34 +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 - -/** - * This enumeration defines the room types available in the OpenDC frontend. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -enum class RoomType { - 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Section.kt deleted file mode 100644 index e3b8c350..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Section.kt +++ /dev/null @@ -1,45 +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 javax.persistence.Entity - -/** - * A [Section] holds a datacenter and the tick on which the parent experiment should - * switch to this section. - * - * @property id The unique identifier of the section. - * @property datacenter The datacenter of this section. - * @property startTime The position in time when the experiment should start using the - * topology of this section. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class Section( - val id: Int, - val datacenter: Datacenter, - val startTime: Instant -) 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 - 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/TaskState.kt deleted file mode 100644 index 14441752..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/TaskState.kt +++ /dev/null @@ -1,49 +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 javax.persistence.Entity - -/** - * The state of a [Task]. - * - * @property id The unique identifier of the state. - * @property task The task this is the state of. - * @property experiment The experiment the machine is running in. - * @property time The current moment in time. - * @property remaining The remaining flops for the task. - * @property cores The cores used for the task. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class TaskState( - 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-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Trace.kt deleted file mode 100644 index cd3d9348..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/integration/jpa/schema/Trace.kt +++ /dev/null @@ -1,44 +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.platform.workload.Job -import nl.atlarge.opendc.platform.workload.Trace -import javax.persistence.Entity - -/** - * A [Trace] backed by the JPA API and an underlying database connection. - * - * @property id The unique identifier of the trace. - * @property name The name of the trace. - * @property jobs The collection of jobs for this trace. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -@Entity -data class Trace( - val id: Int, - val name: String, - override val jobs: Set -) : Trace 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, 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").asSequence() - .flatMap { it.outgoingEdges.destinations("rack").asSequence() } - .flatMap { it.outgoingEdges.destinations("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/platform/JpaPlatformRunner.kt b/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt deleted file mode 100644 index 104f1aec..00000000 --- a/opendc-integration-jpa/core/src/main/kotlin/nl/atlarge/opendc/platform/JpaPlatformRunner.kt +++ /dev/null @@ -1,65 +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.kernel.omega.OmegaKernel -import java.util.concurrent.Executors -import javax.persistence.Persistence - -val logger = KotlinLogging.logger {} - -/** - * The main entry point of the program. This program polls experiments from a database and runs the - * simulation and reports the results back to the database. - * - * @param args The command line arguments of the program. - */ -fun main(args: Array) { - val properties = HashMap() - 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 - - 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) - } -} 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 @@ - - - - - nl.atlarge.opendc.integration.jpa.schema - - - - - - - - - - - - - STRING - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - STRING - - - - - - - - - - - - - - - - - - - - - RACK - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/opendc-integration-jpa/mysql/Dockerfile b/opendc-integration-jpa/mysql/Dockerfile deleted file mode 100644 index 75e419b4..00000000 --- a/opendc-integration-jpa/mysql/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -# Docker mysql image for the OpenDC simulator project -# This image requires the context to be set to the root directory of the project in order to correctly build. -FROM gradle:alpine -MAINTAINER Fabian Mastenbroek - -# Set the home directory to our gradle user's home. -ENV HOME=/home/gradle -ENV APP_HOME=$HOME/simulator - -# Copy OpenDC simulator -COPY ./ $APP_HOME - -# Build as root -USER root - -# Set the working directory to the simulator -WORKDIR $APP_HOME - -# Build the application -RUN gradle --no-daemon :opendc-integration-jpa:mysql:installDist - -# Fix permissions -RUN chown -R gradle:gradle $APP_HOME - -# Downgrade user -USER gradle - -# Start the Gradle application on run -CMD opendc-integration-jpa/mysql/build/install/mysql/bin/mysql - 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-integration-jpa/mysql/src/main/resources/META-INF/persistence.xml b/opendc-integration-jpa/mysql/src/main/resources/META-INF/persistence.xml deleted file mode 100644 index 0e40dc6e..00000000 --- a/opendc-integration-jpa/mysql/src/main/resources/META-INF/persistence.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - jpa/schema.xml - - - - - - - - - diff --git a/opendc-kernel-omega/build.gradle b/opendc-kernel-omega/build.gradle new file mode 100644 index 00000000..ea463f5a --- /dev/null +++ b/opendc-kernel-omega/build.gradle @@ -0,0 +1,86 @@ +/* + * 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.10' + 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.0-RC3' + } +} + +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 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/MessageContainer.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt new file mode 100644 index 00000000..af13d1fd --- /dev/null +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt @@ -0,0 +1,48 @@ +/* + * 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.Instant +import com.atlarge.opendc.simulator.Entity +import com.atlarge.opendc.simulator.Envelope + +/** + * 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 { + /** + * A flag to indicate the message has been canceled. + */ + internal var canceled: Boolean = false +} diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt new file mode 100644 index 00000000..fb5ce24b --- /dev/null +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt @@ -0,0 +1,315 @@ +/* + * 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.Kernel +import com.atlarge.opendc.simulator.Bootstrap +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 OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Context { + /** + * 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, OmegaContext<*>> = HashMap() + + /** + * The message queue. + */ + private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) + + /** + * The simulation time. + */ + override var time: Instant = 0 + + /** + * The model of simulation. + */ + override val model: M = bootstrap.bootstrap(this) + + override val , S> E.state: S + get() = context?.state ?: initialState + + /** + * The context associated with an [Entity]. + */ + @Suppress("UNCHECKED_CAST") + private val , S, M> E.context: OmegaContext? + get() = registry[this] as? OmegaContext + + override fun register(entity: Entity<*, M>): Boolean { + if (!registry.containsKey(entity) && entity !is Process) { + return false + } + + @Suppress("UNCHECKED_CAST") + val process = entity as Process + val context = OmegaContext(entity).also { registry.put(entity, it) } + + // Bootstrap the process coroutine + val block: suspend () -> Unit = { process.run { context.run() } } + block.startCoroutine(context) + + 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)) + + 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 + } + } + + private fun schedule(envelope: MessageContainer) { + queue.add(envelope) + } + + private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, + delay: Duration): MessageContainer { + require(delay >= 0) { "The amount of time to delay the message must be a positive number" } + return MessageContainer(message, time + delay, sender, destination) + } + + /** + * This internal class provides the default implementation for the [Context] interface for this simulator. + */ + private inner class OmegaContext(val process: Process) : Context, Continuation { + /** + * The continuation to resume the execution of the process. + */ + lateinit var continuation: Continuation> + + /** + * The last point in time the process has done some work. + */ + var last: Instant = -1 + + /** + * The model in which the process exists. + */ + override val model: M + get() = this@OmegaKernel.model + + /** + * The state of the entity. + */ + override var state: S = process.initialState + + /** + * The current point in simulation time. + */ + override val time: Instant + get() = this@OmegaKernel.time + + /** + * 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 [CoroutineContext] for a [Context]. + */ + override val context: CoroutineContext = EmptyCoroutineContext + + /** + * The observable state of an [Entity] within the simulation is provided by the context of the simulation. + */ + override val , S> T.state: S + get() = context?.state ?: initialState + + /** + * 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(): Envelope<*> = suspendCoroutine { continuation = it } + + suspend override fun receive(transform: suspend Envelope<*>.(Any) -> T): T { + val envelope = receiveEnvelope() + return transform(envelope, envelope.message) + } + + + suspend override fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? { + val send = prepare(Timeout, process, process, timeout).also { schedule(it) } + + try { + val received = receiveEnvelope() + + if (received.message !is Timeout) { + send.canceled = true + return transform(received, received.message) + } + + return null + } finally { + send.canceled = true + } + } + + suspend override fun Entity<*, *>.send(msg: Any, delay: Duration) = send(msg, process, delay) + + suspend override fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = + schedule(prepare(msg, sender, delay = delay)) + + suspend override fun Entity<*, *>.interrupt() = send(Interrupt) + + suspend override 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() is Resume) + return + } + } finally { + envelope.canceled = true + } + } + + suspend override fun hold(duration: Duration, queue: Queue) { + 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 is Resume) + return + queue.add(msg) + } + } finally { + envelope.canceled = true + } + } + + + // 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/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt new file mode 100644 index 00000000..dcad4dce --- /dev/null +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt @@ -0,0 +1,47 @@ +/* + * 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.kernel.KernelFactory +import com.atlarge.opendc.simulator.kernel.Kernel +import com.atlarge.opendc.simulator.Bootstrap + +/** + * 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. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +object OmegaKernelFactory : KernelFactory { + /** + * Create a simulation over the given model facilitated by this simulation kernel. + * + * @param bootstrap The bootstrap procedure to bootstrap the simulation with. + * @return A [Kernel] instance to control the simulation. + */ + override fun create(bootstrap: Bootstrap): Kernel = OmegaKernel(bootstrap) +} diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt new file mode 100644 index 00000000..d4bd8536 --- /dev/null +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt @@ -0,0 +1,39 @@ +/* + * 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.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 diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt new file mode 100644 index 00000000..c205f6b5 --- /dev/null +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt @@ -0,0 +1,35 @@ +/* + * 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.Process + +/** + * 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-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..b358d618 --- /dev/null +++ b/opendc-kernel-omega/src/test/kotlin/com/atlarge/opendc/omega/SmokeTest.kt @@ -0,0 +1,116 @@ +/* + * 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.Context +import com.atlarge.opendc.simulator.Process +import com.atlarge.opendc.simulator.Bootstrap +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 { + override val initialState = Unit + suspend override fun Context.run() { + while (true) { + receive { + sender?.send(message) + } + } + } + } + + /** + * Run a large amount of simulations and test if any exceptions occur. + */ + @Test + fun smoke() { + val n = 1000 + val messages = 100 + val bootstrap: Bootstrap = Bootstrap.create { ctx -> + repeat(n) { + EchoProcess().also { + ctx.register(it) + + for (i in 1 until messages) { + ctx.schedule(i, it, delay = i.toLong()) + } + } + } + } + val kernel = OmegaKernelFactory.create(bootstrap) + kernel.run() + } + + class NullProcess : Process { + override val initialState = Unit + suspend override fun Context.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 = Bootstrap.create { ctx -> + process.also { + ctx.register(it) + ctx.schedule(0, it) + } + } + + val kernel = OmegaKernelFactory.create(bootstrap) + kernel.run() + } + + class CrashProcess : Process { + override val initialState = Unit + suspend override fun Context.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 = Bootstrap.create { ctx -> + process.also { + ctx.register(it) + ctx.schedule(0, it) + } + } + + val kernel = OmegaKernelFactory.create(bootstrap) + kernel.run() + } +} diff --git a/opendc-model-odc/core/build.gradle b/opendc-model-odc/core/build.gradle new file mode 100644 index 00000000..c8336196 --- /dev/null +++ b/opendc-model-odc/core/build.gradle @@ -0,0 +1,87 @@ +/* + * 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.10' + 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.0-RC3' + } +} + +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 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.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..01ffbd2c --- /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..d2cbcdfe --- /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.simulator.Context +import com.atlarge.opendc.model.odc.platform.workload.Task +import com.atlarge.opendc.model.odc.topology.machine.Machine +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 = HashSet() + + /** + * The queue of [Task]s that need to be scheduled. + */ + val queue: Queue = ArrayDeque() + + /** + * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. + */ + override suspend fun Context.schedule() { + if (queue.isEmpty()) { + return + } + + // The tasks that need to be rescheduled + val rescheduled = ArrayDeque() + 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-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt new file mode 100644 index 00000000..ee965af9 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt @@ -0,0 +1,71 @@ +/* + * 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.simulator.Context +import com.atlarge.opendc.simulator.Entity +import com.atlarge.opendc.model.odc.platform.workload.Task +import com.atlarge.opendc.model.odc.topology.machine.Machine + +/** + * A task scheduler that is coupled to an [Entity] in the topology of the cloud network. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Scheduler { + /** + * 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 Context.schedule() + + /** + * 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) + + /** + * 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..0e497b56 --- /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.simulator.Context +import com.atlarge.opendc.model.odc.platform.workload.Task +import com.atlarge.opendc.model.odc.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 = HashSet() + + /** + * The set of [Task]s that need to be scheduled. + */ + val tasks: MutableSet = HashSet() + + /** + * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. + */ + override suspend fun Context.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-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt new file mode 100644 index 00000000..c42bb667 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt @@ -0,0 +1,53 @@ +/* + * 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 + +/** + * A bag of tasks which are submitted by a [User] to the cloud network. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Job { + /** + * A unique identifier of the job. + */ + val id: Int + + /** + * The owner of this job. + */ + val owner: User + + /** + * The tasks this job consists of. + */ + val tasks: Set + + /** + * 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..f7b9d60f --- /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.simulator.Instant +import com.atlarge.opendc.model.odc.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 + + /** + * 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..2fb3acd9 --- /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-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt new file mode 100644 index 00000000..b2d65277 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt @@ -0,0 +1,37 @@ +/* + * 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 + +/** + * A timestamped sequence of jobs received in a cloud network. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Trace { + /** + * The [Job]s in the trace. + */ + val jobs: Set +} diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt new file mode 100644 index 00000000..6099db3e --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt @@ -0,0 +1,45 @@ +/* + * 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 + +/** + * A user of a cloud network that provides [Job]s for the simulation. + * + * Each user in a simulation has its own logical view of the cloud network which is used to route its jobs in the + * physical network. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface User { + /** + * The unique identifier of the user. + */ + val id: Int + + /** + * 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..2b682410 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Datacenter.kt @@ -0,0 +1,102 @@ +/* + * 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 mu.KotlinLogging +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 com.atlarge.opendc.model.odc.platform.scheduler.Scheduler +import com.atlarge.opendc.model.odc.platform.workload.Task +import com.atlarge.opendc.model.odc.topology.machine.Machine +import com.atlarge.opendc.model.topology.Topology +import com.atlarge.opendc.model.topology.destinations +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 { + /** + * 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. + */ + suspend override fun Context.run() = model.run { + val logger = KotlinLogging.logger {} + + // The queue of messages to be processed after a cycle + val queue: Queue = ArrayDeque() + // Find all machines in the datacenter + val machines = outgoingEdges.destinations("room").asSequence() + .flatMap { it.outgoingEdges.destinations("rack").asSequence() } + .flatMap { it.outgoingEdges.destinations("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) { + msg.arrive(time) + scheduler.submit(msg) + } + } + // (Re)schedule the tasks + scheduler.run { schedule() } + + // Sleep a time quantum + hold(interval, queue) + } + } +} diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt new file mode 100644 index 00000000..0ec43f9a --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt @@ -0,0 +1,36 @@ +/* + * 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.simulator.Entity +import com.atlarge.opendc.model.topology.Topology + +/** + * A type of physical steel and electronic framework that is designed to house servers, networking devices, cables and + * other datacenter computing equipment. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Rack : Entity diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt new file mode 100644 index 00000000..50cfc3e6 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt @@ -0,0 +1,35 @@ +/* + * 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.simulator.Entity +import com.atlarge.opendc.model.topology.Topology + +/** + * 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 diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Cpu.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Cpu.kt new file mode 100644 index 00000000..58eacdc1 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Cpu.kt @@ -0,0 +1,32 @@ +/* + * 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 + +/** + * A central processing unit. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Cpu : ProcessingUnit diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Gpu.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Gpu.kt new file mode 100644 index 00000000..84afc711 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/Gpu.kt @@ -0,0 +1,33 @@ +/* + * 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 + +/** + * A graphics processing unit. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Gpu : ProcessingUnit + 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..4f4ce645 --- /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.simulator.Context +import com.atlarge.opendc.simulator.Process +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.Duration +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 { + /** + * 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.run() = model.run { + state = State(Status.IDLE) + + val interval: Duration = 10 + val cpus = outgoingEdges.destinations("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.receiveTask(): Task { + while (true) { + val msg = receive() + if (msg is Task) + return msg + } + } +} diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt new file mode 100644 index 00000000..0b8989de --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt @@ -0,0 +1,50 @@ +/* + * 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.simulator.Entity +import com.atlarge.opendc.model.topology.Topology + +/** + * 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 { + /** + * The speed of this [ProcessingUnit] per core in MHz. + */ + val clockRate: Int + + /** + * The amount of cores within this [ProcessingUnit]. + */ + val cores: Int + + /** + * The energy consumption of this [ProcessingUnit] in Watt. + */ + val energyConsumption: Double +} diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt new file mode 100644 index 00000000..a41a8326 --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt @@ -0,0 +1,35 @@ +/* + * 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.network + +import com.atlarge.opendc.simulator.Entity +import com.atlarge.opendc.model.topology.Topology + +/** + * A generic interface for a network unit in a cloud network. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface NetworkUnit : Entity diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt new file mode 100644 index 00000000..8650b5dc --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt @@ -0,0 +1,35 @@ +/* + * 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.power + +import com.atlarge.opendc.simulator.Entity +import com.atlarge.opendc.model.topology.Topology + +/** + * 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 diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt new file mode 100644 index 00000000..b5bb4dfb --- /dev/null +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt @@ -0,0 +1,35 @@ +/* + * 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.storage + +import com.atlarge.opendc.simulator.Entity +import com.atlarge.opendc.model.topology.Topology + +/** + * A generic interface for a storage unit in a cloud network. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface StorageUnit : Entity diff --git a/opendc-model-odc/jpa/build.gradle b/opendc-model-odc/jpa/build.gradle new file mode 100644 index 00000000..819ef735 --- /dev/null +++ b/opendc-model-odc/jpa/build.gradle @@ -0,0 +1,89 @@ +/* + * 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.10' + 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 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..10fc54b5 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/JpaBootstrap.kt @@ -0,0 +1,44 @@ +package com.atlarge.opendc.model.odc + +import com.atlarge.opendc.simulator.Bootstrap +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 + +/** + * 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 { + /** + * Bootstrap a model `M` for a kernel in the given context. + * + * @param context The context to bootstrap to model in. + * @return The initialised model for the simulation. + */ + override fun bootstrap(context: Bootstrap.Context): JpaModel { + val section = experiment.path.sections.first() + + // TODO We should not modify parts of the experiment in a bootstrap as the bootstrap should be reproducible. + // Important: initialise the scheduler of the datacenter + section.datacenter.scheduler = experiment.scheduler + + val topology = JpaTopologyFactory(section) + .create() + .bootstrap() + .bootstrap(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) { + 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..6b12a68a --- /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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt new file mode 100644 index 00000000..4f683f65 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt @@ -0,0 +1,38 @@ +/* + * 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 + +import javax.persistence.EntityManager + +/** + * Run the given block in a transaction, committing on return of the block. + * + * @param block The block to execute in the transaction. + */ +inline fun EntityManager.transaction(block: () -> Unit) { + transaction.begin() + block() + transaction.commit() +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt new file mode 100644 index 00000000..c1123490 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt @@ -0,0 +1,62 @@ +/* + * 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.converter + +import javax.persistence.AttributeConverter + +/** + * An internal [AttributeConverter] that maps the values _PARALLEL_ and _SEQUENTIAL_ to a + * boolean value indicating whether a task is parallelizable. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +class ParallelizableConverter : AttributeConverter { + /** + * 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" +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt new file mode 100644 index 00000000..7c793cba --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt @@ -0,0 +1,66 @@ +/* + * 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.converter + +import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler +import com.atlarge.opendc.model.odc.platform.scheduler.FifoScheduler +import com.atlarge.opendc.model.odc.platform.scheduler.SrtfScheduler +import javax.persistence.AttributeConverter + +/** + * An internal [AttributeConverter] that maps a name of a scheduler to the actual scheduler implementation. + * The converter currently chooses between the following two schedulers: + * - [FifoScheduler] (default) + * - [SrtfScheduler] + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +class SchedulerConverter : AttributeConverter { + /** + * 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" +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt new file mode 100644 index 00000000..98a51401 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt @@ -0,0 +1,58 @@ +/* + * 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.topology.machine.Cpu +import javax.persistence.Entity + +/** + * A cpu entity in the persistent schema. + * + * @property id The unique identifier of the cpu. + * @property manufacturer The manufacturer of the cpu. + * @property family The family of the cpu. + * @property generation The generation of the cpu. + * @property model The model of the cpu. + * @property clockRate The clock rate of the cpu. + * @property cores The amount of cores in the gpu. + * @property energyConsumption The energy consumption of the cpu in Watt. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@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 +) : Cpu { + /** + * The initial state of the entity. + */ + override val initialState = Unit +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt new file mode 100644 index 00000000..8dcc1fc5 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt @@ -0,0 +1,66 @@ +/* + * 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.simulator.Duration +import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler +import com.atlarge.opendc.model.odc.topology.container.Datacenter +import javax.persistence.Entity + +/** + * A datacenter entity in the persistent schema. + * + * @property id The unique identifier of the datacenter. + * @property rooms The rooms in the datacenter. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class Datacenter( + val id: Int, + val rooms: Set +): 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 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 +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt new file mode 100644 index 00000000..62a56bab --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt @@ -0,0 +1,58 @@ +/* + * 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.simulator.Instant +import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler +import javax.persistence.Entity + +/** + * An experiment definition for the OpenDC database schema. + * + * @property id The identifier of the experiment. + * @property name The name of the experiment. + * @property scheduler The scheduler used in the experiment. + * @property trace The trace used for the simulation. + * @property path The path of the experiment. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class Experiment( + 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 last tick that has been simulated. + */ + var last: Instant = 0 +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt new file mode 100644 index 00000000..3e84707f --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt @@ -0,0 +1,53 @@ +/* + * 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 + +/** + * Enumerations of the states an [Experiment] can assume. + * + * @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 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 has finished simulating. + */ + FINISHED, +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt new file mode 100644 index 00000000..6b4f77a5 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt @@ -0,0 +1,58 @@ +/* + * 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.topology.machine.Gpu +import javax.persistence.Entity + +/** + * A gpu entity in the persistent schema. + * + * @property id The unique identifier of the gpu. + * @property manufacturer The manufacturer of the gpu. + * @property family The family of the gpu. + * @property generation The generation of the gpu. + * @property model The model of the gpu. + * @property clockRate The clock rate of the gpu. + * @property cores The amount of cores in the gpu. + * @property energyConsumption The energy consumption of the gpu in Watt. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@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 +) : Gpu { + /** + * The initial state of the entity. + */ + override val initialState = Unit +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt new file mode 100644 index 00000000..192e345c --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt @@ -0,0 +1,58 @@ +/* + * 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.Job +import com.atlarge.opendc.model.odc.platform.workload.User +import javax.persistence.* + +/** + * A [Job] backed by the JPA API and an underlying database connection. + * + * @property id The unique identifier of the job. + * @property tasks The collection of tasks the job consists of. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class Job( + override val id: Int, + override val tasks: Set +) : 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 unique identifier of the user. + */ + override val id: Int = 0 + + /** + * The name of this user. + */ + override val name: String = "admin" + } +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt new file mode 100644 index 00000000..b1a2e428 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt @@ -0,0 +1,45 @@ +/* + * 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.topology.machine.Machine +import javax.persistence.Entity + +/** + * A machine entity in the persistent schema. + * + * @property id The unique identifier of the machine. + * @property position The position of the machine in the rack. + * @property cpus The CPUs in the machine. + * @property gpus The GPUs in the machine. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class Machine( + val id: Int, + val position: Int, + val cpus: Set, + val gpus: Set +): Machine() diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt new file mode 100644 index 00000000..3bd017bc --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt @@ -0,0 +1,53 @@ +/* + * 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.simulator.Instant +import javax.persistence.Entity + +/** + * The state of a [Machine]. + * + * @property id The unique identifier of the state. + * @property machine The machine of the state. + * @property task The task the machine has been assigned. + * @property experiment The experiment the machine is running in. + * @property time The current moment in time. + * @property temperature The temperature of the machine. + * @property memoryUsage The memory usage of the machine. + * @property load The load of the machine. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@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 +) diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt new file mode 100644 index 00000000..f24cf6a0 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt @@ -0,0 +1,40 @@ +/* + * 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 javax.persistence.Entity + +/** + * A [Path] holds all sections of the parent experiment. + * + * @property id The unique identifier of the path. + * @property sections The sections of the path. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +open class Path( + val id: Int, + val sections: List
+) diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt new file mode 100644 index 00000000..571c6e88 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt @@ -0,0 +1,52 @@ +/* + * 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.topology.container.Rack +import javax.persistence.Entity + +/** + * A rack entity in a room in the persistent schema. + * + * @property id The unique identifier of the rack. + * @property name The name of the rack. + * @property capacity The capacity of the rack in terms of units. + * @property powerCapacity The power capacity of the rack in Watt. + * @property machines The machines in the rack. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +class Rack( + id: Int, + val name: String, + val capacity: Int, + val powerCapacity: Int, + val machines: List +): RoomObject(id), Rack { + /** + * The initial state of the entity. + */ + override val initialState = Unit +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt new file mode 100644 index 00000000..70f326c2 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt @@ -0,0 +1,50 @@ +/* + * 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.topology.container.Room +import javax.persistence.Entity + +/** + * A room entity in the persistent schema. + * + * @property id The unique identifier of the room. + * @property name The name of the room. + * @property type The type of the room. + * @property objects The objects in the room. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class Room( + val id: Int, + val name: String, + val type: RoomType, + val objects: Set +): Room { + /** + * The initial state of the entity. + */ + override val initialState = Unit +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomObject.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomObject.kt new file mode 100644 index 00000000..49db076c --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomObject.kt @@ -0,0 +1,36 @@ +/* + * 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 javax.persistence.Entity + +/** + * An object in a room. + * + * @property id The unique identifier of the room. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +abstract class RoomObject(val id: Int) diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt new file mode 100644 index 00000000..574677da --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt @@ -0,0 +1,34 @@ +/* + * 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 + +/** + * This enumeration defines the room types available in the OpenDC frontend. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +enum class RoomType { + COOLING, HALLWAY, OFFICE, POWER, SERVER +} diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt new file mode 100644 index 00000000..79b2d74d --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt @@ -0,0 +1,45 @@ +/* + * 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.simulator.Instant +import javax.persistence.Entity + +/** + * A [Section] holds a datacenter and the tick on which the parent experiment should + * switch to this section. + * + * @property id The unique identifier of the section. + * @property datacenter The datacenter of this section. + * @property startTime The position in time when the experiment should start using the + * topology of this section. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class Section( + 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..9379478f --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Task.kt @@ -0,0 +1,117 @@ +/* + * 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.simulator.Instant +import com.atlarge.opendc.model.odc.platform.workload.Task +import com.atlarge.opendc.model.odc.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 + 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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt new file mode 100644 index 00000000..dab8b345 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt @@ -0,0 +1,49 @@ +/* + * 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.simulator.Instant +import javax.persistence.Entity + +/** + * The state of a [Task]. + * + * @property id The unique identifier of the state. + * @property task The task this is the state of. + * @property experiment The experiment the machine is running in. + * @property time The current moment in time. + * @property remaining The remaining flops for the task. + * @property cores The cores used for the task. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class TaskState( + val id: Int, + val task: Task, + val experiment: Experiment, + val time: Instant, + val remaining: Int, + val cores: Int +) diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt new file mode 100644 index 00000000..eddc1a03 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt @@ -0,0 +1,44 @@ +/* + * 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.Job +import com.atlarge.opendc.model.odc.platform.workload.Trace +import javax.persistence.Entity + +/** + * A [Trace] backed by the JPA API and an underlying database connection. + * + * @property id The unique identifier of the trace. + * @property name The name of the trace. + * @property jobs The collection of jobs for this trace. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +@Entity +data class Trace( + val id: Int, + val name: String, + override val jobs: Set +) : 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..08e89c59 --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaExperiment.kt @@ -0,0 +1,179 @@ +/* + * 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 mu.KotlinLogging +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.schema.TaskState as InternalTaskState +import com.atlarge.opendc.model.odc.integration.jpa.schema.Trace as InternalTrace +import com.atlarge.opendc.model.odc.integration.jpa.transaction +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.simulator.kernel.KernelFactory +import com.atlarge.opendc.simulator.Duration +import com.atlarge.opendc.model.odc.JpaBootstrap +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.simulator.platform.Experiment +import com.atlarge.opendc.model.topology.destinations +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, AutoCloseable { + /** + * 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: KernelFactory, 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").asSequence() + .flatMap { it.outgoingEdges.destinations("rack").asSequence() } + .flatMap { it.outgoingEdges.destinations("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) + } + + trace.jobs.asSequence() + .flatMap { it.tasks.asSequence() } + .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.run(simulation.time + 1) + } + + // Set the experiment state + manager.transaction { + experiment.state = ExperimentState.FINISHED + } + + logger.info { "Kernel 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: KernelFactory) = 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..698a1129 --- /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.simulator.platform.Experiment +import com.atlarge.opendc.model.odc.integration.jpa.transaction +import com.atlarge.opendc.model.odc.integration.jpa.schema.Experiment as InternalExperiment +import com.atlarge.opendc.model.odc.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 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..3f7c1b8e --- /dev/null +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/topology/JpaTopologyFactory.kt @@ -0,0 +1,95 @@ +/* + * 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.AdjacencyList +import com.atlarge.opendc.model.topology.Topology +import com.atlarge.opendc.model.topology.MutableTopology +import com.atlarge.opendc.model.topology.TopologyBuilder +import com.atlarge.opendc.model.topology.TopologyFactory + +/** + * 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..9c5e58bd --- /dev/null +++ b/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml @@ -0,0 +1,324 @@ + + + + + com.atlarge.opendc.model.odc.integration.jpa.schema + + + + + + + + + + + + + STRING + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + STRING + + + + + + + + + + + + + + + + + + + + + RACK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendc-model-odc/setup/Dockerfile b/opendc-model-odc/setup/Dockerfile new file mode 100644 index 00000000..70e6fe11 --- /dev/null +++ b/opendc-model-odc/setup/Dockerfile @@ -0,0 +1,30 @@ +# Docker mysql image for the OpenDC simulator project +# This image requires the context to be set to the root directory of the project in order to correctly build. +FROM gradle:alpine +MAINTAINER Fabian Mastenbroek + +# Set the home directory to our gradle user's home. +ENV HOME=/home/gradle +ENV APP_HOME=$HOME/simulator + +# Copy OpenDC simulator +COPY ./ $APP_HOME + +# Build as root +USER root + +# Set the working directory to the simulator +WORKDIR $APP_HOME + +# Build the application +RUN gradle --no-daemon :opendc-model-odc:setup:installDist + +# Fix permissions +RUN chown -R gradle:gradle $APP_HOME + +# Downgrade user +USER gradle + +# Start the Gradle application on run +CMD opendc-odc-model/setup/build/install/setup/bin/setup + diff --git a/opendc-model-odc/setup/build.gradle b/opendc-model-odc/setup/build.gradle new file mode 100644 index 00000000..042b8f37 --- /dev/null +++ b/opendc-model-odc/setup/build.gradle @@ -0,0 +1,87 @@ +/* + * 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.10' + 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" + } +} + +apply plugin: 'java' +apply plugin: 'application' +apply plugin: 'kotlin' +apply plugin: 'org.jetbrains.dokka' + +mainClassName = "nl.atlarge.opendc.model.odc.platform.JpaPlatformRunnerKt" + +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 project(':opendc-model-odc:jpa') + compile project(':opendc-kernel-omega') + + 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-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt b/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt new file mode 100644 index 00000000..3f0fe589 --- /dev/null +++ b/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt @@ -0,0 +1,66 @@ +/* + * 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 platform + +import com.atlarge.opendc.model.odc.platform.JpaExperimentManager +import com.atlarge.opendc.omega.OmegaKernelFactory +import mu.KotlinLogging +import java.util.concurrent.Executors +import javax.persistence.Persistence + +val logger = KotlinLogging.logger {} + +/** + * The main entry point of the program. This program polls experiments from a database and runs the + * simulation and reports the results back to the database. + * + * @param args The command line arguments of the program. + */ +fun main(args: Array) { + val properties = HashMap() + 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 = OmegaKernelFactory + + 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) + } +} diff --git a/opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml b/opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml new file mode 100644 index 00000000..0e40dc6e --- /dev/null +++ b/opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,41 @@ + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + jpa/schema.xml + + + + + + + + + diff --git a/opendc-omega/build.gradle b/opendc-omega/build.gradle deleted file mode 100644 index 89b5740d..00000000 --- a/opendc-omega/build.gradle +++ /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. - */ - -/* Build configuration */ -buildscript { - ext.kotlin_version = '1.1.4-3' - 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.0-RC3' - } -} - -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 'nl.atlarge.opendc' -version '1.0' - -repositories { - jcenter() -} - -dependencies { - 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 project(':opendc-stdlib') -} 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, 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/OmegaKernel.kt b/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaKernel.kt deleted file mode 100644 index cbc25b63..00000000 --- a/opendc-omega/src/main/kotlin/nl/atlarge/opendc/kernel/omega/OmegaKernel.kt +++ /dev/null @@ -1,58 +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.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 - -/** - * 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. - * - * @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) -} 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, OmegaContext<*, *>> = HashMap() - - /** - * The message queue. - */ - private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) - - /** - * The context associated with an [Entity]. - */ - @Suppress("UNCHECKED_CAST") - private val , S> E.context: OmegaContext? - get() = registry[this] as? OmegaContext - - /** - * The observable state of an [Entity] in simulation, which is provided by the simulation context. - */ - override val , 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 - 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, S>(override val entity: E) : Context, - Continuation, TopologyContext by topology { - /** - * The continuation to resume the execution of the process. - */ - lateinit var continuation: Continuation> - - /** - * 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 , 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 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 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) { - 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. - * - *

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 , E : Entity, S> C.update(next: S) { - @Suppress("UNCHECKED_CAST") - (this as OmegaContext).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, Process { - override val initialState = Unit - suspend override fun Context.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, Process { - override val initialState = Unit - suspend override fun Context.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..ea463f5a 100644 --- a/opendc-stdlib/build.gradle +++ b/opendc-stdlib/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.1.4-3' + ext.kotlin_version = '1.2.10' ext.dokka_version = '0.9.15' repositories { @@ -68,8 +68,8 @@ dokka { } /* Project configuration */ -group 'nl.atlarge.opendc' -version '1.0' +group 'com.atlarge.opendc' +version '1.1' repositories { jcenter() 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..c042a2d5 --- /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 com.atlarge.opendc.model.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, Node> = HashMap() + + // Topology + + /** + * The listeners of this topology. + */ + override val listeners: MutableSet = 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> + get() = nodes[this]!!.ingoingEdges + + /** + * The set of outgoing edges of this node. + */ + override val Entity<*, Topology>.outgoingEdges: MutableSet> + 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 connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String?): BaseEdge { + 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>): 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>): 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>): 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>): 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> = nodes.keys.iterator() + + /** + * The internal representation of a node within the graph. + */ + internal data class Node(val id: Int) { + val ingoingEdges: MutableSet> = HashSet() + val outgoingEdges: MutableSet> = HashSet() + } + + /** + * The internal representation of an edge within the graph. + */ + internal class Edge(override val label: T, + override val tag: String?, + override val from: Entity<*, Topology>, + override val to: Entity<*, Topology>) : BaseEdge +} 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..de9a41d5 --- /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 bootstrap procedure for the topology. + */ +fun T.bootstrap(): Bootstrap = 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-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Component.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Component.kt new file mode 100644 index 00000000..5e8611a0 --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Component.kt @@ -0,0 +1,33 @@ +/* + * 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 + +/** + * A component within a [Topology], which is either a node or an [Edge] representing the relationship between + * entities within a logical topology of a cloud network. + ** + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Component diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt new file mode 100644 index 00000000..3e507887 --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt @@ -0,0 +1,61 @@ +/* + * 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 + +/** + * An edge that represents a directed relationship between exactly two nodes in a logical topology of a cloud network. + * + * @param T The relationship type the edge represents within a logical topology. + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Edge : Component { + /** + * The label of this edge. + */ + val label: T + + /** + * 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 O(1), but must be at least + * O(n), 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 O(1), but must be at least + * O(n), 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..ac1b4ba5 --- /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> { + /** + * 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 connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String? = null): Edge + + /** + * 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 = + 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 = connect(this, dest) +} diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt new file mode 100644 index 00000000..1e5a404f --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt @@ -0,0 +1,50 @@ +/* + * 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 graph data structure which represents the logical topology of a cloud network consisting of one or more + * datacenters. + * + * A topology is [Iterable] and allows implementation-dependent iteration of the nodes in the topology. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface Topology : TopologyContext, Cloneable, Set> { + /** + * The listeners of this topology. + */ + val listeners: MutableSet + + /** + * 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-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt new file mode 100644 index 00000000..44b1cb4e --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt @@ -0,0 +1,40 @@ +/* + * 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 + +/** + * A builder for [Topology] instances. + * + * @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) +} diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt new file mode 100644 index 00000000..2bf87a39 --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt @@ -0,0 +1,50 @@ +/* + * 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 [TopologyContext] represents the context for entities in a specific topology, providing access to the identifier + * and ingoing and outgoing edges of the [Entity] within a [Topology]. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface TopologyContext { + /** + * A unique identifier of an [Entity] within the topology. + */ + val Entity<*, Topology>.id: Int + + /** + * The set of ingoing edges of an [Entity]. + */ + val Entity<*, Topology>.ingoingEdges: Set> + + /** + * The set of outgoing edges of an [Entity]. + */ + val Entity<*, Topology>.outgoingEdges: Set> +} diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt new file mode 100644 index 00000000..35cfa97a --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt @@ -0,0 +1,40 @@ +/* + * 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 + +/** + * An interface for producing [Topology] instances. Implementors of this interface provide a way of generating a + * topology based on the state of the factory. + * + * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) + */ +interface TopologyFactory { + /** + * Create a [MutableTopology] instance. + * + * @return A mutable topology. + */ + fun create(): MutableTopology +} diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt new file mode 100644 index 00000000..93108cc0 --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt @@ -0,0 +1,63 @@ +/* + * 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 listener interface for [Topology] instances. The methods of this interface are invoked on + * mutation of the topology the listener is listening to. + * + * @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<*, 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<*, 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 removed from the [Topology]. + * + * @param edge The entity that has been removed from the [Topology]. + */ + fun Topology.onEdgeRemoved(edge: Edge<*>) {} +} diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Traversable.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Traversable.kt new file mode 100644 index 00000000..23720c46 --- /dev/null +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Traversable.kt @@ -0,0 +1,41 @@ +/* + * 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 + +/** + * Filter a [Set] of [Edge]s based on the tag of the edges and return the origin nodes casted to type `T`. + * + * @param tag The tag of the edges to get. + * @return An [Iterable] of the specified type `T` with the given tag. + */ +inline fun Set>.origins(tag: String) = filter { it.tag == tag }.map { it.from as T } + +/** + * Filter a [Set] of [Edge]s based on the tag of the edges and return the destination nodes casted to type `T`. + * + * @param tag The tag of the edges to get. + * @return An [Iterable] of the specified type `T` with the given tag. + */ +inline fun Set>.destinations(tag: String) = filter { it.tag == tag }.map { it.to as T } 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 = HashSet() - - /** - * The queue of [Task]s that need to be scheduled. - */ - val queue: Queue = ArrayDeque() - - /** - * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. - */ - override suspend fun > Context.schedule() { - if (queue.isEmpty()) { - return - } - - // The tasks that need to be rescheduled - val rescheduled = ArrayDeque() - 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-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/Scheduler.kt deleted file mode 100644 index 578bef9c..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/scheduler/Scheduler.kt +++ /dev/null @@ -1,71 +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 - -/** - * A task scheduler that is coupled to an [Entity] in the topology of the cloud network. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Scheduler { - /** - * 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 > Context.schedule() - - /** - * 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) - - /** - * Deregister a [Machine] from this scheduler. - * - * @param machine The machine to deregister. - */ - fun deregister(machine: 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 = HashSet() - - /** - * The set of [Task]s that need to be scheduled. - */ - val tasks: MutableSet = HashSet() - - /** - * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. - */ - override suspend fun > Context.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-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Job.kt deleted file mode 100644 index df2f2b6a..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Job.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.platform.workload - -/** - * A bag of tasks which are submitted by a [User] to the cloud network. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Job { - /** - * A unique identifier of the job. - */ - val id: Int - - /** - * The owner of this job. - */ - val owner: User - - /** - * The tasks this job consists of. - */ - val tasks: Set - - /** - * A flag to indicate the job has finished. - */ - val finished: Boolean - get() = !tasks.any { !it.finished } -} 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 - - /** - * 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/platform/workload/Trace.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Trace.kt deleted file mode 100644 index 6dd2efb8..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/Trace.kt +++ /dev/null @@ -1,37 +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 - -/** - * A timestamped sequence of jobs received in a cloud network. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Trace { - /** - * The [Job]s in the trace. - */ - val jobs: Set -} diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/User.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/User.kt deleted file mode 100644 index d827fee5..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/platform/workload/User.kt +++ /dev/null @@ -1,45 +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 - -/** - * A user of a cloud network that provides [Job]s for the simulation. - * - * Each user in a simulation has its own logical view of the cloud network which is used to route its jobs in the - * physical network. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface User { - /** - * The unique identifier of the user. - */ - val id: Int - - /** - * The name of this user. - */ - val name: String -} 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, Process { - /** - * 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.run() { - val logger = KotlinLogging.logger {} - - // The queue of messages to be processed after a cycle - val queue: Queue = ArrayDeque() - // Find all machines in the datacenter - val machines = outgoingEdges.destinations("room").asSequence() - .flatMap { it.outgoingEdges.destinations("rack").asSequence() } - .flatMap { it.outgoingEdges.destinations("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/container/Rack.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Rack.kt deleted file mode 100644 index 25429f71..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Rack.kt +++ /dev/null @@ -1,35 +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 nl.atlarge.opendc.topology.Entity - -/** - * A type of physical steel and electronic framework that is designed to house servers, networking devices, cables and - * other datacenter computing equipment. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Rack : Entity diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Room.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Room.kt deleted file mode 100644 index 3b338899..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/container/Room.kt +++ /dev/null @@ -1,34 +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 nl.atlarge.opendc.topology.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 diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Cpu.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Cpu.kt deleted file mode 100644 index f97e73e9..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Cpu.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.topology.machine - -/** - * A central processing unit. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Cpu : ProcessingUnit diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Gpu.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Gpu.kt deleted file mode 100644 index 15c5263f..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/Gpu.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.topology.machine - -/** - * A graphics processing unit. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Gpu : ProcessingUnit - 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, Process { - /** - * 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.run() { - update(State(Status.IDLE)) - - val interval: Duration = 10 - val cpus = outgoingEdges.destinations("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.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-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/ProcessingUnit.kt deleted file mode 100644 index abc8608b..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/machine/ProcessingUnit.kt +++ /dev/null @@ -1,49 +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 nl.atlarge.opendc.topology.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 { - /** - * The speed of this [ProcessingUnit] per core in MHz. - */ - val clockRate: Int - - /** - * The amount of cores within this [ProcessingUnit]. - */ - val cores: Int - - /** - * 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-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/network/NetworkUnit.kt deleted file mode 100644 index d3a9eefe..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/network/NetworkUnit.kt +++ /dev/null @@ -1,34 +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.network - -import nl.atlarge.opendc.topology.Entity - -/** - * A generic interface for a network unit in a cloud network. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface NetworkUnit : Entity diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/power/PowerUnit.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/power/PowerUnit.kt deleted file mode 100644 index b9602e55..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/power/PowerUnit.kt +++ /dev/null @@ -1,34 +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.power - -import nl.atlarge.opendc.topology.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 diff --git a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/storage/StorageUnit.kt b/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/storage/StorageUnit.kt deleted file mode 100644 index f719f152..00000000 --- a/opendc-stdlib/src/main/kotlin/nl/atlarge/opendc/topology/storage/StorageUnit.kt +++ /dev/null @@ -1,34 +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.storage - -import nl.atlarge.opendc.topology.Entity - -/** - * A generic interface for a storage unit in a cloud network. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface StorageUnit : Entity 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' -- cgit v1.2.3 From 67c8bc6cdd421262c4f59ce03506463a830af6e6 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 12 Feb 2018 14:02:21 +0100 Subject: refactor(#18): Update dependencies This change bumps the version of the dependencies used by the project. --- opendc-core/build.gradle | 7 ++----- opendc-kernel-omega/build.gradle | 8 +++++--- opendc-model-odc/core/build.gradle | 6 ++++-- opendc-model-odc/jpa/build.gradle | 4 +++- opendc-model-odc/setup/build.gradle | 2 +- opendc-stdlib/build.gradle | 6 ++++-- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/opendc-core/build.gradle b/opendc-core/build.gradle index f1eac0da..4a45b911 100644 --- a/opendc-core/build.gradle +++ b/opendc-core/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.10' + ext.kotlin_version = '1.2.21' ext.dokka_version = '0.9.15' repositories { @@ -35,7 +35,7 @@ buildscript { 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' + classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3' } } @@ -77,11 +77,8 @@ repositories { 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.21" 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/build.gradle b/opendc-kernel-omega/build.gradle index ea463f5a..1ca00aa6 100644 --- a/opendc-kernel-omega/build.gradle +++ b/opendc-kernel-omega/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.10' + ext.kotlin_version = '1.2.21' ext.dokka_version = '0.9.15' repositories { @@ -35,7 +35,7 @@ buildscript { 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' + classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3' } } @@ -76,7 +76,9 @@ repositories { } dependencies { - compile project(':opendc-core') + 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" diff --git a/opendc-model-odc/core/build.gradle b/opendc-model-odc/core/build.gradle index c8336196..ffd37db6 100644 --- a/opendc-model-odc/core/build.gradle +++ b/opendc-model-odc/core/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.10' + ext.kotlin_version = '1.2.21' ext.dokka_version = '0.9.15' repositories { @@ -35,7 +35,7 @@ buildscript { 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' + classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3' } } @@ -76,6 +76,8 @@ repositories { } dependencies { + 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" diff --git a/opendc-model-odc/jpa/build.gradle b/opendc-model-odc/jpa/build.gradle index 819ef735..d312f89d 100644 --- a/opendc-model-odc/jpa/build.gradle +++ b/opendc-model-odc/jpa/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.10' + ext.kotlin_version = '1.2.21' ext.dokka_version = '0.9.15' repositories { @@ -78,6 +78,8 @@ repositories { } dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile project(':opendc-core') compile project(':opendc-stdlib') compile project(':opendc-model-odc:core') diff --git a/opendc-model-odc/setup/build.gradle b/opendc-model-odc/setup/build.gradle index 042b8f37..3962018e 100644 --- a/opendc-model-odc/setup/build.gradle +++ b/opendc-model-odc/setup/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.10' + ext.kotlin_version = '1.2.21' ext.dokka_version = '0.9.15' repositories { diff --git a/opendc-stdlib/build.gradle b/opendc-stdlib/build.gradle index ea463f5a..6dccaff0 100644 --- a/opendc-stdlib/build.gradle +++ b/opendc-stdlib/build.gradle @@ -24,7 +24,7 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.10' + ext.kotlin_version = '1.2.21' ext.dokka_version = '0.9.15' repositories { @@ -35,7 +35,7 @@ buildscript { 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' + classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.3' } } @@ -76,6 +76,8 @@ repositories { } 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" -- cgit v1.2.3 From e97d9bf3f2cccf19a21631e26d55d60c9f4d7c7a Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 12 Feb 2018 14:26:44 +0100 Subject: refactor(#18): Align formatting with official Kotlin Style Guide This change aligns the code formatting of the project with the official Kotlin Style Guide. They can be found at http://kotlinlang.org/docs/reference/coding-conventions.html. --- .editorconfig | 2 +- opendc-core/build.gradle | 54 +- .../com/atlarge/opendc/simulator/Bootstrap.kt | 98 ++-- .../kotlin/com/atlarge/opendc/simulator/Context.kt | 268 ++++----- .../kotlin/com/atlarge/opendc/simulator/Entity.kt | 8 +- .../kotlin/com/atlarge/opendc/simulator/Process.kt | 32 +- .../com/atlarge/opendc/simulator/kernel/Kernel.kt | 62 +-- .../opendc/simulator/kernel/KernelFactory.kt | 14 +- .../opendc/simulator/platform/Experiment.kt | 32 +- opendc-kernel-omega/build.gradle | 56 +- .../com/atlarge/opendc/omega/MessageContainer.kt | 16 +- .../kotlin/com/atlarge/opendc/omega/OmegaKernel.kt | 543 ++++++++++--------- .../com/atlarge/opendc/omega/OmegaKernelFactory.kt | 18 +- .../kotlin/com/atlarge/opendc/omega/SmokeTest.kt | 142 ++--- opendc-model-odc/core/build.gradle | 60 +-- .../com/atlarge/opendc/model/odc/OdcModel.kt | 2 +- .../model/odc/platform/scheduler/FifoScheduler.kt | 140 ++--- .../model/odc/platform/scheduler/Scheduler.kt | 62 +-- .../model/odc/platform/scheduler/SrtfScheduler.kt | 126 ++--- .../opendc/model/odc/platform/workload/Job.kt | 34 +- .../opendc/model/odc/platform/workload/Task.kt | 96 ++-- .../model/odc/platform/workload/TaskState.kt | 64 +-- .../opendc/model/odc/platform/workload/Trace.kt | 8 +- .../opendc/model/odc/platform/workload/User.kt | 16 +- .../model/odc/topology/container/Datacenter.kt | 106 ++-- .../opendc/model/odc/topology/container/Rack.kt | 2 +- .../opendc/model/odc/topology/container/Room.kt | 2 +- .../opendc/model/odc/topology/machine/Machine.kt | 146 ++--- .../model/odc/topology/machine/ProcessingUnit.kt | 26 +- .../model/odc/topology/network/NetworkUnit.kt | 2 +- .../opendc/model/odc/topology/power/PowerUnit.kt | 2 +- .../model/odc/topology/storage/StorageUnit.kt | 2 +- opendc-model-odc/jpa/build.gradle | 62 +-- .../com/atlarge/opendc/model/odc/JpaBootstrap.kt | 52 +- .../com/atlarge/opendc/model/odc/JpaModel.kt | 2 +- .../opendc/model/odc/integration/jpa/Jpa.kt | 6 +- .../jpa/converter/ParallelizableConverter.kt | 50 +- .../jpa/converter/SchedulerConverter.kt | 50 +- .../opendc/model/odc/integration/jpa/schema/Cpu.kt | 24 +- .../model/odc/integration/jpa/schema/Datacenter.kt | 46 +- .../model/odc/integration/jpa/schema/Experiment.kt | 28 +- .../odc/integration/jpa/schema/ExperimentState.kt | 34 +- .../opendc/model/odc/integration/jpa/schema/Gpu.kt | 24 +- .../opendc/model/odc/integration/jpa/schema/Job.kt | 26 +- .../model/odc/integration/jpa/schema/Machine.kt | 10 +- .../odc/integration/jpa/schema/MachineState.kt | 16 +- .../model/odc/integration/jpa/schema/Path.kt | 4 +- .../model/odc/integration/jpa/schema/Rack.kt | 20 +- .../model/odc/integration/jpa/schema/Room.kt | 18 +- .../model/odc/integration/jpa/schema/RoomType.kt | 2 +- .../model/odc/integration/jpa/schema/Section.kt | 6 +- .../model/odc/integration/jpa/schema/Task.kt | 137 ++--- .../model/odc/integration/jpa/schema/TaskState.kt | 12 +- .../model/odc/integration/jpa/schema/Trace.kt | 6 +- .../opendc/model/odc/platform/JpaExperiment.kt | 269 ++++----- .../model/odc/platform/JpaExperimentManager.kt | 100 ++-- .../model/odc/topology/JpaTopologyFactory.kt | 96 ++-- .../jpa/src/main/resources/jpa/schema.xml | 600 +++++++++++---------- opendc-model-odc/setup/build.gradle | 56 +- .../src/main/kotlin/platform/JpaPlatformRunner.kt | 42 +- .../src/main/resources/META-INF/persistence.xml | 30 +- opendc-stdlib/build.gradle | 58 +- .../atlarge/opendc/model/topology/AdjacencyList.kt | 414 +++++++------- .../com/atlarge/opendc/model/topology/Bootstrap.kt | 22 +- .../com/atlarge/opendc/model/topology/Edge.kt | 44 +- .../opendc/model/topology/MutableTopology.kt | 54 +- .../com/atlarge/opendc/model/topology/Topology.kt | 20 +- .../opendc/model/topology/TopologyBuilder.kt | 14 +- .../opendc/model/topology/TopologyContext.kt | 24 +- .../opendc/model/topology/TopologyFactory.kt | 12 +- .../opendc/model/topology/TopologyListener.kt | 48 +- 71 files changed, 2389 insertions(+), 2390 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 4a45b911..223e73f9 100644 --- a/opendc-core/build.gradle +++ b/opendc-core/build.gradle @@ -24,19 +24,19 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.21' - 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.3' - } + 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,26 +45,26 @@ 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 */ @@ -72,13 +72,13 @@ 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:$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.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 index 199e1701..10a89704 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt @@ -8,57 +8,57 @@ package com.atlarge.opendc.simulator * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Bootstrap { - /** - * Bootstrap a model `M` for a kernel in the given context. - * - * @param context The context to bootstrap to model in. - * @return The initialised model for the simulation. - */ - fun bootstrap(context: Context): M + /** + * Bootstrap a model `M` for a kernel in the given context. + * + * @param context The context to bootstrap to model in. + * @return The initialised model for the simulation. + */ + fun bootstrap(context: Context): M - /** - * A context for the bootstrap 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 { - /** - * 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 + /** + * A context for the bootstrap 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 { + /** + * 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 + /** + * 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 for processing by a [Context]. - * - * @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) - } + /** + * Schedule a message for processing by a [Context]. + * + * @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 bootstrap for a model of type `M`. - * - * @param block The block to produce the bootstrap. - * @return The bootstrap procedure that has been built. - */ - fun create(block: (Context) -> M): Bootstrap = object : Bootstrap { - override fun bootstrap(context: Context) = block(context) - } - } + companion object { + /** + * Create a [Bootstrap] procedure using the given block to produce a bootstrap for a model of type `M`. + * + * @param block The block to produce the bootstrap. + * @return The bootstrap procedure that has been built. + */ + fun create(block: (Context) -> M): Bootstrap = object : Bootstrap { + override fun bootstrap(context: Context) = 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 index c4e906dd..c89bdb59 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt @@ -24,7 +24,7 @@ package com.atlarge.opendc.simulator -import java.util.Queue +import java.util.* /** * This interface provides a context for simulation of [Entity] instances, by defining the environment in which the @@ -34,123 +34,123 @@ import java.util.Queue * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Context { - /** - * 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 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 , 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. - */ - suspend fun Entity<*, *>.interrupt() - - /** - * 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) - - /** - * 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 after which the message [Envelope] is - * transformed through `transform` to return the transformed result. - * - * @param transform The block to transform the message with in an envelope context, providing access to the sender - * of the message. - * @return The transformed message. - */ - suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T - - /** - * 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 after which the message - * [Envelope] is transformed through `transform` to return the transformed result or the timeout has been reached. - * - * @param timeout The duration to wait before resuming execution. - * @param transform The block to transform the message with in an envelope context, providing access to the sender - * of the message. - * @return The processed message or `null` if the timeout was reached. - */ - suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? - - /** - * 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 = receive { it } - - /** - * 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? = receive(timeout) { it } - - /** - * 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 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) + /** + * 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 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 , 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. + */ + suspend fun Entity<*, *>.interrupt() + + /** + * 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) + + /** + * 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 after which the message [Envelope] is + * transformed through `transform` to return the transformed result. + * + * @param transform The block to transform the message with in an envelope context, providing access to the sender + * of the message. + * @return The transformed message. + */ + suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T + + /** + * 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 after which the message + * [Envelope] is transformed through `transform` to return the transformed result or the timeout has been reached. + * + * @param timeout The duration to wait before resuming execution. + * @param transform The block to transform the message with in an envelope context, providing access to the sender + * of the message. + * @return The processed message or `null` if the timeout was reached. + */ + suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? + + /** + * 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 = receive { it } + + /** + * 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? = receive(timeout) { it } + + /** + * 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 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) } /** @@ -159,21 +159,21 @@ interface Context { * @param T The shape of the message inside the envelope. * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -interface Envelope { - /** - * 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 Envelope { + /** + * The message in this envelope. + */ + val message: T + + /** + * The sender of the message. + */ + val sender: Entity<*, *>? + + /** + * The destination of the message. + */ + val destination: Entity<*, *> } /** @@ -181,4 +181,4 @@ interface Envelope { * * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -object Interrupt: Throwable("The entity process has been interrupted by another entity") +object Interrupt : Throwable("The entity process has been interrupted by another entity") diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt index 800f2f1d..56704c5d 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Entity.kt @@ -37,8 +37,8 @@ package com.atlarge.opendc.simulator * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Entity { - /** - * The initial state of the entity. - */ - val initialState: S + /** + * 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 index 30280657..e8b4d988 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt @@ -8,20 +8,20 @@ package com.atlarge.opendc.simulator * @param M The shape of the model in which the process exists. * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -interface Process: Entity { - /** - * 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.run() +interface Process : Entity { + /** + * 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.run() } diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt index 3eee0f67..29b3bdee 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt @@ -25,8 +25,8 @@ package com.atlarge.opendc.simulator.kernel import com.atlarge.opendc.simulator.Bootstrap -import com.atlarge.opendc.simulator.Instant import com.atlarge.opendc.simulator.Entity +import com.atlarge.opendc.simulator.Instant /** * A message based discrete event simulation kernel. @@ -41,39 +41,39 @@ import com.atlarge.opendc.simulator.Entity * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Kernel { - /** - * The model in which the simulation runs. - */ - val model: M + /** + * The model in which the simulation runs. + */ + val model: M - /** - * The simulation time. - */ - var time: Instant + /** + * The simulation time. + */ + var time: Instant - /** - * The observable state of an [Entity] in simulation, which is provided by the simulation context. - */ - val , S> E.state: S + /** + * The observable state of an [Entity] in simulation, which is provided by the simulation context. + */ + val , 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() + /** + * 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. + * 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) + /** + * 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/com/atlarge/opendc/simulator/kernel/KernelFactory.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt index 93667eb8..30abb7ca 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt @@ -32,11 +32,11 @@ import com.atlarge.opendc.simulator.Bootstrap * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface KernelFactory { - /** - * Create a simulation over the given model facilitated by this simulation kernel. - * - * @param bootstrap The bootstrap procedure to bootstrap the simulation with. - * @return A [Kernel] instance to control the simulation. - */ - fun create(bootstrap: Bootstrap): Kernel + /** + * Create a simulation over the given model facilitated by this simulation kernel. + * + * @param bootstrap The bootstrap procedure to bootstrap the simulation with. + * @return A [Kernel] instance to control the simulation. + */ + fun create(bootstrap: Bootstrap): Kernel } diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt index 88b606fd..92d56be1 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.simulator.platform -import com.atlarge.opendc.simulator.kernel.KernelFactory import com.atlarge.opendc.simulator.Duration +import com.atlarge.opendc.simulator.kernel.KernelFactory /** * A blueprint for a reproducible simulation in a pre-defined setting. @@ -33,20 +33,20 @@ import com.atlarge.opendc.simulator.Duration * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Experiment { - /** - * 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: KernelFactory): 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: KernelFactory): 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: KernelFactory, 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: KernelFactory, timeout: Duration): T? } diff --git a/opendc-kernel-omega/build.gradle b/opendc-kernel-omega/build.gradle index 1ca00aa6..e02da931 100644 --- a/opendc-kernel-omega/build.gradle +++ b/opendc-kernel-omega/build.gradle @@ -24,19 +24,19 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.21' - 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.3' - } + 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,26 +45,26 @@ 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 */ @@ -72,17 +72,17 @@ group 'com.atlarge.opendc' version '1.1' repositories { - jcenter() + 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" + 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-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt index af13d1fd..32f27111 100644 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt @@ -24,9 +24,9 @@ package com.atlarge.opendc.omega -import com.atlarge.opendc.simulator.Instant import com.atlarge.opendc.simulator.Entity import com.atlarge.opendc.simulator.Envelope +import com.atlarge.opendc.simulator.Instant /** * A wrapper around a message that has been scheduled for processing. @@ -38,11 +38,11 @@ import com.atlarge.opendc.simulator.Envelope * @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 { - /** - * A flag to indicate the message has been canceled. - */ - internal var canceled: Boolean = false + val time: Instant, + override val sender: Entity<*, *>?, + override val destination: Entity<*, *>) : Envelope { + /** + * A flag to indicate the message has been canceled. + */ + internal var canceled: Boolean = false } diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt index fb5ce24b..c729a63d 100644 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt @@ -26,7 +26,6 @@ package com.atlarge.opendc.omega import com.atlarge.opendc.simulator.* import com.atlarge.opendc.simulator.kernel.Kernel -import com.atlarge.opendc.simulator.Bootstrap import mu.KotlinLogging import java.util.* import kotlin.coroutines.experimental.* @@ -41,275 +40,275 @@ import kotlin.coroutines.experimental.* * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Context { - /** - * 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, OmegaContext<*>> = HashMap() - - /** - * The message queue. - */ - private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) - - /** - * The simulation time. - */ - override var time: Instant = 0 - - /** - * The model of simulation. - */ - override val model: M = bootstrap.bootstrap(this) - - override val , S> E.state: S - get() = context?.state ?: initialState - - /** - * The context associated with an [Entity]. - */ - @Suppress("UNCHECKED_CAST") - private val , S, M> E.context: OmegaContext? - get() = registry[this] as? OmegaContext - - override fun register(entity: Entity<*, M>): Boolean { - if (!registry.containsKey(entity) && entity !is Process) { - return false - } - - @Suppress("UNCHECKED_CAST") - val process = entity as Process - val context = OmegaContext(entity).also { registry.put(entity, it) } - - // Bootstrap the process coroutine - val block: suspend () -> Unit = { process.run { context.run() } } - block.startCoroutine(context) - - 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)) - - 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 - } - } - - private fun schedule(envelope: MessageContainer) { - queue.add(envelope) - } - - private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, - delay: Duration): MessageContainer { - require(delay >= 0) { "The amount of time to delay the message must be a positive number" } - return MessageContainer(message, time + delay, sender, destination) - } - - /** - * This internal class provides the default implementation for the [Context] interface for this simulator. - */ - private inner class OmegaContext(val process: Process) : Context, Continuation { - /** - * The continuation to resume the execution of the process. - */ - lateinit var continuation: Continuation> - - /** - * The last point in time the process has done some work. - */ - var last: Instant = -1 - - /** - * The model in which the process exists. - */ - override val model: M - get() = this@OmegaKernel.model - - /** - * The state of the entity. - */ - override var state: S = process.initialState - - /** - * The current point in simulation time. - */ - override val time: Instant - get() = this@OmegaKernel.time - - /** - * 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 [CoroutineContext] for a [Context]. - */ - override val context: CoroutineContext = EmptyCoroutineContext - - /** - * The observable state of an [Entity] within the simulation is provided by the context of the simulation. - */ - override val , S> T.state: S - get() = context?.state ?: initialState - - /** - * 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(): Envelope<*> = suspendCoroutine { continuation = it } - - suspend override fun receive(transform: suspend Envelope<*>.(Any) -> T): T { - val envelope = receiveEnvelope() - return transform(envelope, envelope.message) - } - - - suspend override fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? { - val send = prepare(Timeout, process, process, timeout).also { schedule(it) } - - try { - val received = receiveEnvelope() - - if (received.message !is Timeout) { - send.canceled = true - return transform(received, received.message) - } - - return null - } finally { - send.canceled = true - } - } - - suspend override fun Entity<*, *>.send(msg: Any, delay: Duration) = send(msg, process, delay) - - suspend override fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = - schedule(prepare(msg, sender, delay = delay)) - - suspend override fun Entity<*, *>.interrupt() = send(Interrupt) - - suspend override 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() is Resume) - return - } - } finally { - envelope.canceled = true - } - } - - suspend override fun hold(duration: Duration, queue: Queue) { - 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 is Resume) - return - queue.add(msg) - } - } finally { - envelope.canceled = true - } - } - - - // 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" } - } - } + /** + * 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, OmegaContext<*>> = HashMap() + + /** + * The message queue. + */ + private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) + + /** + * The simulation time. + */ + override var time: Instant = 0 + + /** + * The model of simulation. + */ + override val model: M = bootstrap.bootstrap(this) + + override val , S> E.state: S + get() = context?.state ?: initialState + + /** + * The context associated with an [Entity]. + */ + @Suppress("UNCHECKED_CAST") + private val , S, M> E.context: OmegaContext? + get() = registry[this] as? OmegaContext + + override fun register(entity: Entity<*, M>): Boolean { + if (!registry.containsKey(entity) && entity !is Process) { + return false + } + + @Suppress("UNCHECKED_CAST") + val process = entity as Process + val context = OmegaContext(entity).also { registry[entity] = it } + + // Bootstrap the process coroutine + val block: suspend () -> Unit = { process.run { context.run() } } + block.startCoroutine(context) + + 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)) + + 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 + } + } + + private fun schedule(envelope: MessageContainer) { + queue.add(envelope) + } + + private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, + delay: Duration): MessageContainer { + require(delay >= 0) { "The amount of time to delay the message must be a positive number" } + return MessageContainer(message, time + delay, sender, destination) + } + + /** + * This internal class provides the default implementation for the [Context] interface for this simulator. + */ + private inner class OmegaContext(val process: Process) : Context, Continuation { + /** + * The continuation to resume the execution of the process. + */ + lateinit var continuation: Continuation> + + /** + * The last point in time the process has done some work. + */ + var last: Instant = -1 + + /** + * The model in which the process exists. + */ + override val model: M + get() = this@OmegaKernel.model + + /** + * The state of the entity. + */ + override var state: S = process.initialState + + /** + * The current point in simulation time. + */ + override val time: Instant + get() = this@OmegaKernel.time + + /** + * 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 [CoroutineContext] for a [Context]. + */ + override val context: CoroutineContext = EmptyCoroutineContext + + /** + * The observable state of an [Entity] within the simulation is provided by the context of the simulation. + */ + override val , S> T.state: S + get() = context?.state ?: initialState + + /** + * 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(): Envelope<*> = suspendCoroutine { continuation = it } + + override suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T { + val envelope = receiveEnvelope() + return transform(envelope, envelope.message) + } + + + override suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? { + val send = prepare(Timeout, process, process, timeout).also { schedule(it) } + + try { + val received = receiveEnvelope() + + if (received.message == Timeout) { + send.canceled = true + return transform(received, received.message) + } + + return null + } finally { + send.canceled = true + } + } + + override suspend fun Entity<*, *>.send(msg: Any, delay: Duration) = send(msg, process, delay) + + override suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = + schedule(prepare(msg, sender, delay = delay)) + + override suspend fun Entity<*, *>.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) { + 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 + } + } + + + // 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/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt index dcad4dce..139cbd19 100644 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt @@ -24,9 +24,9 @@ package com.atlarge.opendc.omega -import com.atlarge.opendc.simulator.kernel.KernelFactory -import com.atlarge.opendc.simulator.kernel.Kernel import com.atlarge.opendc.simulator.Bootstrap +import com.atlarge.opendc.simulator.kernel.Kernel +import com.atlarge.opendc.simulator.kernel.KernelFactory /** * The Omega simulation kernel is the reference simulation kernel implementation for the OpenDC Simulator core. @@ -37,11 +37,11 @@ import com.atlarge.opendc.simulator.Bootstrap * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ object OmegaKernelFactory : KernelFactory { - /** - * Create a simulation over the given model facilitated by this simulation kernel. - * - * @param bootstrap The bootstrap procedure to bootstrap the simulation with. - * @return A [Kernel] instance to control the simulation. - */ - override fun create(bootstrap: Bootstrap): Kernel = OmegaKernel(bootstrap) + /** + * Create a simulation over the given model facilitated by this simulation kernel. + * + * @param bootstrap The bootstrap procedure to bootstrap the simulation with. + * @return A [Kernel] instance to control the simulation. + */ + override fun create(bootstrap: Bootstrap): Kernel = OmegaKernel(bootstrap) } 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 index b358d618..a1ec8e88 100644 --- 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 @@ -24,9 +24,9 @@ package com.atlarge.opendc.omega +import com.atlarge.opendc.simulator.Bootstrap import com.atlarge.opendc.simulator.Context import com.atlarge.opendc.simulator.Process -import com.atlarge.opendc.simulator.Bootstrap import org.junit.jupiter.api.Test /** @@ -35,82 +35,82 @@ import org.junit.jupiter.api.Test * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ internal class SmokeTest { - class EchoProcess : Process { - override val initialState = Unit - suspend override fun Context.run() { - while (true) { - receive { - sender?.send(message) - } - } - } - } + class EchoProcess : Process { + override val initialState = Unit + override suspend fun Context.run() { + while (true) { + receive { + sender?.send(message) + } + } + } + } - /** - * Run a large amount of simulations and test if any exceptions occur. - */ - @Test - fun smoke() { - val n = 1000 - val messages = 100 - val bootstrap: Bootstrap = Bootstrap.create { ctx -> - repeat(n) { - EchoProcess().also { - ctx.register(it) + /** + * Run a large amount of simulations and test if any exceptions occur. + */ + @Test + fun smoke() { + val n = 1000 + val messages = 100 + val bootstrap: Bootstrap = Bootstrap.create { ctx -> + repeat(n) { + EchoProcess().also { + ctx.register(it) - for (i in 1 until messages) { - ctx.schedule(i, it, delay = i.toLong()) - } - } - } - } - val kernel = OmegaKernelFactory.create(bootstrap) - kernel.run() - } + for (i in 1 until messages) { + ctx.schedule(i, it, delay = i.toLong()) + } + } + } + } + val kernel = OmegaKernelFactory.create(bootstrap) + kernel.run() + } - class NullProcess : Process { - override val initialState = Unit - suspend override fun Context.run() {} - } + class NullProcess : Process { + override val initialState = Unit + override suspend fun Context.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 = Bootstrap.create { ctx -> - process.also { - ctx.register(it) - ctx.schedule(0, it) - } - } + /** + * 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 = Bootstrap.create { ctx -> + process.also { + ctx.register(it) + ctx.schedule(0, it) + } + } - val kernel = OmegaKernelFactory.create(bootstrap) - kernel.run() - } + val kernel = OmegaKernelFactory.create(bootstrap) + kernel.run() + } - class CrashProcess : Process { - override val initialState = Unit - suspend override fun Context.run() { - TODO("This process should crash") - } - } + class CrashProcess : Process { + override val initialState = Unit + override suspend fun Context.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 = Bootstrap.create { ctx -> - process.also { - ctx.register(it) - ctx.schedule(0, it) - } - } + /** + * 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 = Bootstrap.create { ctx -> + process.also { + ctx.register(it) + ctx.schedule(0, it) + } + } - val kernel = OmegaKernelFactory.create(bootstrap) - kernel.run() - } + val kernel = OmegaKernelFactory.create(bootstrap) + kernel.run() + } } diff --git a/opendc-model-odc/core/build.gradle b/opendc-model-odc/core/build.gradle index ffd37db6..e423da50 100644 --- a/opendc-model-odc/core/build.gradle +++ b/opendc-model-odc/core/build.gradle @@ -24,19 +24,19 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.21' - 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.3' - } + 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,26 +45,26 @@ 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 */ @@ -72,18 +72,18 @@ group 'com.atlarge.opendc' version '1.1' repositories { - jcenter() + jcenter() } dependencies { 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" + 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.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-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 index 01ffbd2c..298a14cf 100644 --- 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 @@ -7,4 +7,4 @@ import com.atlarge.opendc.model.topology.MutableTopology * * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -interface OdcModel: MutableTopology +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 index d2cbcdfe..e743586c 100644 --- 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 @@ -24,9 +24,9 @@ package com.atlarge.opendc.model.odc.platform.scheduler -import com.atlarge.opendc.simulator.Context 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.* /** @@ -35,84 +35,84 @@ import java.util.* * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ class FifoScheduler : Scheduler { - /** - * The name of this scheduler. - */ - override val name: String = "FIFO" + /** + * The name of this scheduler. + */ + override val name: String = "FIFO" - /** - * The set of machines the scheduler knows of. - */ - val machines: MutableSet = HashSet() + /** + * The set of machines the scheduler knows of. + */ + private val machines: MutableSet = HashSet() - /** - * The queue of [Task]s that need to be scheduled. - */ - val queue: Queue = ArrayDeque() + /** + * The queue of [Task]s that need to be scheduled. + */ + private val queue: Queue = ArrayDeque() - /** - * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. - */ - override suspend fun Context.schedule() { - if (queue.isEmpty()) { - return - } + /** + * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. + */ + override suspend fun Context.schedule() { + if (queue.isEmpty()) { + return + } - // The tasks that need to be rescheduled - val rescheduled = ArrayDeque() - val iterator = queue.iterator() + // The tasks that need to be rescheduled + val rescheduled = ArrayDeque() + val iterator = queue.iterator() - machines - .filter { it.state.status != Machine.Status.HALT } - .forEach { machine -> - while (iterator.hasNext()) { - val task = iterator.next() + 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 - } + // 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 - } - } + machine.send(task) + break + } + } - // Reschedule all tasks that are not ready yet - while (!rescheduled.isEmpty()) { - queue.add(rescheduled.poll()) - } - } + // 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) - } + /** + * 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) - } + /** + * 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) - } + /** + * Deregister a [Machine] from this scheduler. + * + * @param machine The machine to deregister. + */ + override fun deregister(machine: Machine) { + machines.remove(machine) + } } diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt index ee965af9..79486ee6 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/scheduler/Scheduler.kt @@ -24,10 +24,10 @@ package com.atlarge.opendc.model.odc.platform.scheduler -import com.atlarge.opendc.simulator.Context -import com.atlarge.opendc.simulator.Entity 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 com.atlarge.opendc.model.odc.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 Context.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 Context.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 index 0e497b56..d3f067df 100644 --- 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 @@ -24,9 +24,9 @@ package com.atlarge.opendc.model.odc.platform.scheduler -import com.atlarge.opendc.simulator.Context 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.* /** @@ -35,76 +35,76 @@ import java.util.* * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ class SrtfScheduler : Scheduler { - /** - * The name of this scheduler. - */ - override val name: String = "SRTF" + /** + * The name of this scheduler. + */ + override val name: String = "SRTF" - /** - * The set of machines the scheduler knows of. - */ - val machines: MutableSet = HashSet() + /** + * The set of machines the scheduler knows of. + */ + private val machines: MutableSet = HashSet() - /** - * The set of [Task]s that need to be scheduled. - */ - val tasks: MutableSet = HashSet() + /** + * The set of [Task]s that need to be scheduled. + */ + private val tasks: MutableSet = HashSet() - /** - * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. - */ - override suspend fun Context.schedule() { - if (tasks.isEmpty()) { - return - } + /** + * (Re)schedule the tasks submitted to the scheduler over the specified set of machines. + */ + override suspend fun Context.schedule() { + if (tasks.isEmpty()) { + return + } - val iterator = tasks.sortedBy { it.remaining }.iterator() + val iterator = tasks.sortedBy { it.remaining }.iterator() - machines - .filter { it.state.status != Machine.Status.HALT } - .forEach { machine -> - while (iterator.hasNext()) { - val task = iterator.next() + 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 - } + // 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 - } - } - } + 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) - } + /** + * 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) - } + /** + * 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) - } + /** + * Deregister a [Machine] from this scheduler. + * + * @param machine The machine to deregister. + */ + override fun deregister(machine: Machine) { + machines.remove(machine) + } } diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt index c42bb667..3e6c6821 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Job.kt @@ -30,24 +30,24 @@ package com.atlarge.opendc.model.odc.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 + /** + * The tasks this job consists of. + */ + val tasks: Set - /** - * 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 index f7b9d60f..d68cceba 100644 --- 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 @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.platform.workload -import com.atlarge.opendc.simulator.Instant 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]. @@ -33,60 +33,60 @@ import com.atlarge.opendc.model.odc.topology.machine.Machine * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Task { - /** - * The unique identifier of the task. - */ - val id: Int + /** + * The unique identifier of the task. + */ + val id: Int - /** - * The amount of flops for this task. - */ - val flops: Long + /** + * The amount of flops for this task. + */ + val flops: Long - /** - * The dependencies of the task. - */ - val dependencies: Set + /** + * The dependencies of the task. + */ + val dependencies: Set - /** - * A flag to indicate the task is parallelizable. - */ - val parallelizable: Boolean + /** + * A flag to indicate the task is parallelizable. + */ + val parallelizable: Boolean - /** - * The remaining flops for this task. - */ - val remaining: Long + /** + * The remaining flops for this task. + */ + val remaining: Long - /** - * The state of the task. - */ - val state: TaskState + /** + * 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 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 + /** + * 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) + /** + * 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) + /** + * 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 index 2fb3acd9..78963ca3 100644 --- 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 @@ -33,40 +33,40 @@ import com.atlarge.opendc.simulator.Instant * @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 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 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 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 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() + /** + * 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-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt index b2d65277..25bcad83 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/Trace.kt @@ -30,8 +30,8 @@ package com.atlarge.opendc.model.odc.platform.workload * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Trace { - /** - * The [Job]s in the trace. - */ - val jobs: Set + /** + * The [Job]s in the trace. + */ + val jobs: Set } diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt index 6099db3e..da696d88 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/platform/workload/User.kt @@ -33,13 +33,13 @@ package com.atlarge.opendc.model.odc.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 index 2b682410..b9b804d3 100644 --- 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 @@ -24,16 +24,16 @@ package com.atlarge.opendc.model.odc.topology.container -import mu.KotlinLogging -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 com.atlarge.opendc.model.odc.platform.scheduler.Scheduler import com.atlarge.opendc.model.odc.platform.workload.Task 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.* /** @@ -44,59 +44,59 @@ import java.util.* * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Datacenter : Process { - /** - * The task scheduler the datacenter uses. - */ - val scheduler: Scheduler + /** + * The task scheduler the datacenter uses. + */ + val scheduler: Scheduler - /** - * The interval at which task will be (re)scheduled. - */ - val interval: Duration + /** + * 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. - */ - suspend override fun Context.run() = model.run { - val logger = KotlinLogging.logger {} + /** + * 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.run() = model.run { + val logger = KotlinLogging.logger {} - // The queue of messages to be processed after a cycle - val queue: Queue = ArrayDeque() - // Find all machines in the datacenter - val machines = outgoingEdges.destinations("room").asSequence() - .flatMap { it.outgoingEdges.destinations("rack").asSequence() } - .flatMap { it.outgoingEdges.destinations("machine").asSequence() }.toList() + // The queue of messages to be processed after a cycle + val queue: Queue = ArrayDeque() + // Find all machines in the datacenter + val machines = outgoingEdges.destinations("room").asSequence() + .flatMap { it.outgoingEdges.destinations("rack").asSequence() } + .flatMap { it.outgoingEdges.destinations("machine").asSequence() }.toList() - logger.info { "Initialising datacenter with ${machines.size} machines" } + logger.info { "Initialising datacenter with ${machines.size} machines" } - // Register all machines to the scheduler - machines.forEach(scheduler::register) + // 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) { - msg.arrive(time) - scheduler.submit(msg) - } - } - // (Re)schedule the tasks - scheduler.run { schedule() } + while (true) { + // Context 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 - hold(interval, queue) - } - } + // Sleep a time quantum + hold(interval, queue) + } + } } diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt index 0ec43f9a..42fdc9cf 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Rack.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.topology.container -import com.atlarge.opendc.simulator.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 diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt index 50cfc3e6..5e07b0ce 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/container/Room.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.topology.container -import com.atlarge.opendc.simulator.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. 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 index 4f4ce645..642723f5 100644 --- 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 @@ -24,12 +24,12 @@ package com.atlarge.opendc.model.odc.topology.machine -import com.atlarge.opendc.simulator.Context -import com.atlarge.opendc.simulator.Process 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 /** @@ -39,85 +39,85 @@ import mu.KotlinLogging * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ open class Machine : Process { - /** - * The logger instance to use for the simulator. - */ - private val logger = KotlinLogging.logger {} + /** + * 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 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 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) + /** + * The initial state of a [Machine] entity. + */ + override val initialState = State(Status.HALT) - /** - * Run the simulation kernel for this entity. - */ - override suspend fun Context.run() = model.run { - state = State(Status.IDLE) + /** + * Run the simulation kernel for this entity. + */ + override suspend fun Context.run() = model.run { + state = State(Status.IDLE) - val interval: Duration = 10 - val cpus = outgoingEdges.destinations("cpu") - val speed = cpus.fold(0, { acc, cpu -> acc + cpu.clockRate * cpu.cores }) + val interval: Duration = 10 + val cpus = outgoingEdges.destinations("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 - } + // 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) + 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) - } + 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) - } - } - } + // 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.receiveTask(): Task { - while (true) { - val msg = receive() - if (msg is Task) - return msg - } - } + /** + * 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.receiveTask(): Task { + while (true) { + val msg = receive() + if (msg is Task) + return msg + } + } } diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt index 0b8989de..e5d30173 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/machine/ProcessingUnit.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.topology.machine -import com.atlarge.opendc.simulator.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]. @@ -33,18 +33,18 @@ import com.atlarge.opendc.model.topology.Topology * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface ProcessingUnit : Entity { - /** - * The speed of this [ProcessingUnit] per core in MHz. - */ - val clockRate: Int + /** + * 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-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt index a41a8326..5ffc19bf 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/network/NetworkUnit.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.topology.network -import com.atlarge.opendc.simulator.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. diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt index 8650b5dc..3e9248c4 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/power/PowerUnit.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.topology.power -import com.atlarge.opendc.simulator.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. diff --git a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt index b5bb4dfb..eb622f2c 100644 --- a/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt +++ b/opendc-model-odc/core/src/main/kotlin/com/atlarge/opendc/model/odc/topology/storage/StorageUnit.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.topology.storage -import com.atlarge.opendc.simulator.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. diff --git a/opendc-model-odc/jpa/build.gradle b/opendc-model-odc/jpa/build.gradle index d312f89d..191ca787 100644 --- a/opendc-model-odc/jpa/build.gradle +++ b/opendc-model-odc/jpa/build.gradle @@ -24,20 +24,20 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.21' - 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.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' @@ -47,26 +47,26 @@ 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 */ @@ -74,18 +74,18 @@ group 'com.atlarge.opendc' version '1.1' repositories { - jcenter() + 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' + 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' + 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 index 10fc54b5..09d8f4b3 100644 --- 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 @@ -1,10 +1,10 @@ package com.atlarge.opendc.model.odc -import com.atlarge.opendc.simulator.Bootstrap 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 /** * A [Bootstrap] procedure for experiments retrieved from a JPA data store. @@ -12,33 +12,33 @@ import com.atlarge.opendc.model.topology.bootstrap * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ class JpaBootstrap(val experiment: Experiment) : Bootstrap { - /** - * Bootstrap a model `M` for a kernel in the given context. - * - * @param context The context to bootstrap to model in. - * @return The initialised model for the simulation. - */ - override fun bootstrap(context: Bootstrap.Context): JpaModel { - val section = experiment.path.sections.first() + /** + * Bootstrap a model `M` for a kernel in the given context. + * + * @param context The context to bootstrap to model in. + * @return The initialised model for the simulation. + */ + override fun bootstrap(context: Bootstrap.Context): JpaModel { + val section = experiment.path.sections.first() - // TODO We should not modify parts of the experiment in a bootstrap as the bootstrap should be reproducible. - // Important: initialise the scheduler of the datacenter - section.datacenter.scheduler = experiment.scheduler + // TODO We should not modify parts of the experiment in a bootstrap as the bootstrap should be reproducible. + // Important: initialise the scheduler of the datacenter + section.datacenter.scheduler = experiment.scheduler - val topology = JpaTopologyFactory(section) - .create() - .bootstrap() - .bootstrap(context) - val trace = experiment.trace - val tasks = trace.jobs.flatMap { it.tasks } + val topology = JpaTopologyFactory(section) + .create() + .bootstrap() + .bootstrap(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) { - context.schedule(task, section.datacenter, delay = task.startTime) - } - } + // Schedule all messages in the trace + tasks.forEach { task -> + if (task is Task) { + context.schedule(task, section.datacenter, delay = task.startTime) + } + } - return JpaModel(experiment, topology) - } + 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 index 6b12a68a..44c1fb69 100644 --- 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 @@ -10,5 +10,5 @@ import com.atlarge.opendc.model.topology.MutableTopology * @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 +data class JpaModel(val experiment: Experiment, val topology: MutableTopology) : OdcModel, MutableTopology by topology diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt index 4f683f65..cb3181f8 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/Jpa.kt @@ -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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt index c1123490..e9635b2e 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/ParallelizableConverter.kt @@ -33,30 +33,30 @@ import javax.persistence.AttributeConverter * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ class ParallelizableConverter : AttributeConverter { - /** - * 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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt index 7c793cba..15f6a905 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/converter/SchedulerConverter.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.integration.jpa.converter -import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler 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 { - /** - * 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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt index 98a51401..11553477 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Cpu.kt @@ -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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt index 8dcc1fc5..e65eef8b 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Datacenter.kt @@ -24,9 +24,9 @@ package com.atlarge.opendc.model.odc.integration.jpa.schema -import com.atlarge.opendc.simulator.Duration 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 -): 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 +) : 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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt index 62a56bab..ce489b1f 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Experiment.kt @@ -24,8 +24,8 @@ package com.atlarge.opendc.model.odc.integration.jpa.schema -import com.atlarge.opendc.simulator.Instant import com.atlarge.opendc.model.odc.platform.scheduler.Scheduler +import com.atlarge.opendc.simulator.Instant import javax.persistence.Entity /** @@ -40,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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt index 3e84707f..fecfe060 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/ExperimentState.kt @@ -30,24 +30,24 @@ package com.atlarge.opendc.model.odc.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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt index 6b4f77a5..c04262cc 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Gpu.kt @@ -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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt index 192e345c..67ffba32 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Job.kt @@ -26,7 +26,7 @@ package com.atlarge.opendc.model.odc.integration.jpa.schema import com.atlarge.opendc.model.odc.platform.workload.Job import com.atlarge.opendc.model.odc.platform.workload.User -import javax.persistence.* +import javax.persistence.Entity /** * A [Job] backed by the JPA API and an underlying database connection. @@ -37,22 +37,22 @@ import javax.persistence.* */ @Entity data class Job( - override val id: Int, - override val tasks: Set + override val id: Int, + override val tasks: Set ) : 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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt index b1a2e428..925ab1d2 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Machine.kt @@ -38,8 +38,8 @@ import javax.persistence.Entity */ @Entity data class Machine( - val id: Int, - val position: Int, - val cpus: Set, - val gpus: Set -): Machine() + val id: Int, + val position: Int, + val cpus: Set, + val gpus: Set +) : Machine() diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt index 3bd017bc..f3149adb 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/MachineState.kt @@ -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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt index f24cf6a0..a6e915f3 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Path.kt @@ -35,6 +35,6 @@ import javax.persistence.Entity */ @Entity open class Path( - val id: Int, - val sections: List

+ val id: Int, + val sections: List
) diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt index 571c6e88..dd48480d 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Rack.kt @@ -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 -): 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 +) : RoomObject(id), Rack { + /** + * The initial state of the entity. + */ + override val initialState = Unit } diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt index 70f326c2..1a1c721f 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Room.kt @@ -38,13 +38,13 @@ import javax.persistence.Entity */ @Entity data class Room( - val id: Int, - val name: String, - val type: RoomType, - val objects: Set -): Room { - /** - * The initial state of the entity. - */ - override val initialState = Unit + val id: Int, + val name: String, + val type: RoomType, + val objects: Set +) : Room { + /** + * The initial state of the entity. + */ + override val initialState = Unit } diff --git a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt index 574677da..ed0f89d3 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/RoomType.kt @@ -30,5 +30,5 @@ package com.atlarge.opendc.model.odc.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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt index 79b2d74d..c6de2e50 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Section.kt @@ -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 index 9379478f..4a296255 100644 --- 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 @@ -24,10 +24,11 @@ package com.atlarge.opendc.model.odc.integration.jpa.schema -import com.atlarge.opendc.simulator.Instant import com.atlarge.opendc.model.odc.platform.workload.Task import com.atlarge.opendc.model.odc.platform.workload.TaskState -import javax.persistence.* +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. @@ -41,77 +42,77 @@ import javax.persistence.* */ @Entity data class Task( - override val id: Int, - override val flops: Long, - private val dependency: Task?, - override val parallelizable: Boolean, - val startTime: Instant + 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 - private set + /** + * The dependencies of the task. + */ + override lateinit var dependencies: Set + private set - /** - * The remaining flops for this task. - */ - override var remaining: Long = 0 - 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 + /** + * 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 + /** + * 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 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) - } + /** + * 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) - } - } + /** + * 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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt index dab8b345..6ab43b93 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/TaskState.kt @@ -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-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt index eddc1a03..e2ed78a2 100644 --- a/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt +++ b/opendc-model-odc/jpa/src/main/kotlin/com/atlarge/opendc/model/odc/integration/jpa/schema/Trace.kt @@ -38,7 +38,7 @@ import javax.persistence.Entity */ @Entity data class Trace( - val id: Int, - val name: String, - override val jobs: Set + val id: Int, + val name: String, + override val jobs: Set ) : 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 index 08e89c59..6c3ad5e8 100644 --- 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 @@ -24,24 +24,25 @@ package com.atlarge.opendc.model.odc.platform -import mu.KotlinLogging +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.schema.TaskState as InternalTaskState -import com.atlarge.opendc.model.odc.integration.jpa.schema.Trace as InternalTrace import com.atlarge.opendc.model.odc.integration.jpa.transaction -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.simulator.kernel.KernelFactory -import com.atlarge.opendc.simulator.Duration -import com.atlarge.opendc.model.odc.JpaBootstrap 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.simulator.platform.Experiment import com.atlarge.opendc.model.topology.destinations +import com.atlarge.opendc.simulator.Duration +import com.atlarge.opendc.simulator.kernel.KernelFactory +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. @@ -51,129 +52,129 @@ import javax.persistence.EntityManager * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ class JpaExperiment(private val manager: EntityManager, - private val experiment: InternalExperiment): Experiment, AutoCloseable { - /** - * 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: KernelFactory, 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").asSequence() - .flatMap { it.outgoingEdges.destinations("rack").asSequence() } - .flatMap { it.outgoingEdges.destinations("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) - } - - trace.jobs.asSequence() - .flatMap { it.tasks.asSequence() } - .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.run(simulation.time + 1) - } - - // Set the experiment state - manager.transaction { - experiment.state = ExperimentState.FINISHED - } - - logger.info { "Kernel 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: KernelFactory) = 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() + private val experiment: InternalExperiment) : Experiment, 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: KernelFactory, 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").asSequence() + .flatMap { it.outgoingEdges.destinations("rack").asSequence() } + .flatMap { it.outgoingEdges.destinations("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) + } + + trace.jobs.asSequence() + .flatMap { it.tasks.asSequence() } + .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.run(simulation.time + 1) + } + + // Set the experiment state + manager.transaction { + experiment.state = ExperimentState.FINISHED + } + + logger.info { "Kernel 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: KernelFactory) = 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 index 698a1129..5dbb9a8b 100644 --- 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 @@ -24,12 +24,12 @@ package com.atlarge.opendc.model.odc.platform -import com.atlarge.opendc.simulator.platform.Experiment -import com.atlarge.opendc.model.odc.integration.jpa.transaction -import com.atlarge.opendc.model.odc.integration.jpa.schema.Experiment as InternalExperiment 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. @@ -38,56 +38,56 @@ import javax.persistence.EntityManagerFactory * 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() +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() - } + /** + * 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 + /** + * 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 - } + 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() + /** + * 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 index 3f7c1b8e..65961413 100644 --- 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 @@ -28,11 +28,7 @@ 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.AdjacencyList -import com.atlarge.opendc.model.topology.Topology -import com.atlarge.opendc.model.topology.MutableTopology -import com.atlarge.opendc.model.topology.TopologyBuilder -import com.atlarge.opendc.model.topology.TopologyFactory +import com.atlarge.opendc.model.topology.* /** * A [TopologyFactory] that converts a [Section] of an experiment as defined by the API, into a proper [Topology]. @@ -42,54 +38,54 @@ import com.atlarge.opendc.model.topology.TopologyFactory * @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") + /** + * 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) } - } - } + 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 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") + /** + * 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.cpus.forEach { cpu -> + add(cpu) + connect(machine, cpu, tag = "cpu") + } - machine.gpus.forEach { gpu -> - add(gpu) - connect(machine, gpu, tag = "gpu") - } - } - } + 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 index 9c5e58bd..142c3ee8 100644 --- a/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml +++ b/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml @@ -22,303 +22,305 @@ ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ~ SOFTWARE. --> - - - com.atlarge.opendc.model.odc.integration.jpa.schema - - - - - - - - - - - - - STRING - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - STRING - - - - - - - - - - - - - - - - - - - - - RACK - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + com.atlarge.opendc.model.odc.integration.jpa.schema + + + + + + + + + + + + + STRING + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + STRING + + + + + + + + + + + + + + + + + + + + + RACK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/opendc-model-odc/setup/build.gradle b/opendc-model-odc/setup/build.gradle index 3962018e..ddb5860b 100644 --- a/opendc-model-odc/setup/build.gradle +++ b/opendc-model-odc/setup/build.gradle @@ -24,19 +24,19 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.21' - 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" - } + 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' @@ -47,26 +47,26 @@ apply plugin: 'org.jetbrains.dokka' mainClassName = "nl.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 */ @@ -74,14 +74,14 @@ group 'com.atlarge.opendc' version '1.1' repositories { - jcenter() + jcenter() } dependencies { - compile project(':opendc-model-odc:jpa') - compile project(':opendc-kernel-omega') + compile project(':opendc-model-odc:jpa') + compile project(':opendc-kernel-omega') - 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' + 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-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt b/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt index 3f0fe589..8fe49844 100644 --- a/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt +++ b/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt @@ -39,28 +39,28 @@ val logger = KotlinLogging.logger {} * @param args The command line arguments of the program. */ fun main(args: Array) { - val properties = HashMap() - 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() + 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 = OmegaKernelFactory + val timeout = 10000L + val threads = 4 + val executorService = Executors.newFixedThreadPool(threads) + val experiments = JpaExperimentManager(factory) + val kernel = OmegaKernelFactory - 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-model-odc/setup/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-model-odc/setup/src/main/resources/META-INF/persistence.xml +++ b/opendc-model-odc/setup/src/main/resources/META-INF/persistence.xml @@ -23,19 +23,19 @@ ~ SOFTWARE. --> - - - org.hibernate.jpa.HibernatePersistenceProvider - jpa/schema.xml - - - - - - - - + + + org.hibernate.jpa.HibernatePersistenceProvider + jpa/schema.xml + + + + + + + + diff --git a/opendc-stdlib/build.gradle b/opendc-stdlib/build.gradle index 6dccaff0..e02da931 100644 --- a/opendc-stdlib/build.gradle +++ b/opendc-stdlib/build.gradle @@ -24,19 +24,19 @@ /* Build configuration */ buildscript { - ext.kotlin_version = '1.2.21' - 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.3' - } + 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,26 +45,26 @@ 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 */ @@ -72,17 +72,17 @@ group 'com.atlarge.opendc' version '1.1' repositories { - jcenter() + 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" + 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 index c042a2d5..db117917 100644 --- 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 @@ -25,8 +25,8 @@ package com.atlarge.opendc.model.topology import com.atlarge.opendc.simulator.Entity -import com.atlarge.opendc.model.topology.Edge as BaseEdge 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. @@ -37,12 +37,12 @@ import java.util.concurrent.atomic.AtomicInteger * *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() + /** + * Return a [TopologyBuilder] that constructs the topology represents as an adjacency list. + * + * @return A [TopologyBuilder] instance. + */ + fun builder(): TopologyBuilder = AdjacencyListTopologyBuilder() } /** @@ -51,210 +51,210 @@ object AdjacencyList { * @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() + /** + * 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, Node> = HashMap() - - // Topology - - /** - * The listeners of this topology. - */ - override val listeners: MutableSet = 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> - get() = nodes[this]!!.ingoingEdges - - /** - * The set of outgoing edges of this node. - */ - override val Entity<*, Topology>.outgoingEdges: MutableSet> - 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 connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String?): BaseEdge { - 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>): 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>): 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>): 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>): 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> = nodes.keys.iterator() - - /** - * The internal representation of a node within the graph. - */ - internal data class Node(val id: Int) { - val ingoingEdges: MutableSet> = HashSet() - val outgoingEdges: MutableSet> = HashSet() - } - - /** - * The internal representation of an edge within the graph. - */ - internal class Edge(override val label: T, - override val tag: String?, - override val from: Entity<*, Topology>, - override val to: Entity<*, Topology>) : BaseEdge + /** + * 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, Node> = HashMap() + + // Topology + + /** + * The listeners of this topology. + */ + override val listeners: MutableSet = 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> + get() = nodes[this]!!.ingoingEdges + + /** + * The set of outgoing edges of this node. + */ + override val Entity<*, Topology>.outgoingEdges: MutableSet> + 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 connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String?): BaseEdge { + 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>): 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>): 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>): 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>): 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> = nodes.keys.iterator() + + /** + * The internal representation of a node within the graph. + */ + internal data class Node(val id: Int) { + val ingoingEdges: MutableSet> = HashSet() + val outgoingEdges: MutableSet> = HashSet() + } + + /** + * The internal representation of an edge within the graph. + */ + internal class Edge(override val label: T, + override val tag: String?, + override val from: Entity<*, Topology>, + override val to: Entity<*, Topology>) : BaseEdge } 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 index de9a41d5..1a5bbcaf 100644 --- 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 @@ -8,16 +8,16 @@ import com.atlarge.opendc.simulator.Entity * * @return A bootstrap procedure for the topology. */ -fun T.bootstrap(): Bootstrap = Bootstrap.create { ctx -> - forEach { ctx.register(it) } - listeners += object : TopologyListener { - override fun Topology.onNodeAdded(node: Entity<*, Topology>) { - ctx.register(node) - } +fun T.bootstrap(): Bootstrap = 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 + override fun Topology.onNodeRemoved(node: Entity<*, Topology>) { + ctx.deregister(node) + } + } + this } diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt index 3e507887..1963a056 100644 --- a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Edge.kt @@ -33,29 +33,29 @@ import com.atlarge.opendc.simulator.Entity * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Edge : 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 O(1), but must be at least - * O(n), with respect to the size of the topology. - */ - val from: Entity<*, Topology> + /** + * The source of the edge. + * + * This property is not guaranteed to have a runtime complexity of O(1), but must be at least + * O(n), 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 O(1), but must be at least - * O(n), with respect to the size of the topology. - */ - val to: Entity<*, Topology> + /** + * The destination of the edge. + * + * This property is not guaranteed to have a runtime complexity of O(1), but must be at least + * O(n), 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 index ac1b4ba5..7cf80702 100644 --- 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 @@ -33,33 +33,33 @@ import com.atlarge.opendc.simulator.Entity * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface MutableTopology : Topology, MutableSet> { - /** - * 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 connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String? = null): Edge + /** + * 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 connect(from: Entity<*, Topology>, to: Entity<*, Topology>, label: T, tag: String? = null): Edge - /** - * 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 = - connect(from, to, Unit, tag) + /** + * 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 = + 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 = connect(this, dest) + /** + * 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 = connect(this, dest) } diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt index 1e5a404f..e277bc9f 100644 --- a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/Topology.kt @@ -35,16 +35,16 @@ import com.atlarge.opendc.simulator.Entity * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface Topology : TopologyContext, Cloneable, Set> { - /** - * The listeners of this topology. - */ - val listeners: MutableSet + /** + * The listeners of this topology. + */ + val listeners: MutableSet - /** - * 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-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt index 44b1cb4e..8bdc37c0 100644 --- a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyBuilder.kt @@ -30,11 +30,11 @@ package com.atlarge.opendc.model.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-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt index 2bf87a39..9d78b5eb 100644 --- a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyContext.kt @@ -33,18 +33,18 @@ import com.atlarge.opendc.simulator.Entity * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ interface TopologyContext { - /** - * A unique identifier of an [Entity] within the topology. - */ - val Entity<*, Topology>.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<*, Topology>.ingoingEdges: Set> + /** + * The set of ingoing edges of an [Entity]. + */ + val Entity<*, Topology>.ingoingEdges: Set> - /** - * The set of outgoing edges of an [Entity]. - */ - val Entity<*, Topology>.outgoingEdges: Set> + /** + * The set of outgoing edges of an [Entity]. + */ + val Entity<*, Topology>.outgoingEdges: Set> } diff --git a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt index 35cfa97a..ab2deeb7 100644 --- a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyFactory.kt @@ -31,10 +31,10 @@ package com.atlarge.opendc.model.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-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt index 93108cc0..0b4d43f7 100644 --- a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/model/topology/TopologyListener.kt @@ -33,31 +33,31 @@ import com.atlarge.opendc.simulator.Entity * @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<*, Topology>) {} + /** + * 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<*, 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<*, 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<*>) {} } -- cgit v1.2.3 From 407877ff24d3c54747c8b15bba73b93b38c8b6e7 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 12 Feb 2018 22:27:44 +0100 Subject: refactor(#18): Launch processes at initial run This change will make the simulation kernel launch the processes at the initial run instead of when the processes are registered. --- .../kotlin/com/atlarge/opendc/omega/OmegaKernel.kt | 37 ++++++++++++++++------ .../kotlin/com/atlarge/opendc/omega/SmokeTest.kt | 36 ++++++++++++++++++--- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt index c729a63d..91150078 100644 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt @@ -55,6 +55,11 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co */ private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) + /** + * The processes to be spawned. + */ + private val spawnings: Queue> = ArrayDeque() + /** * The simulation time. */ @@ -80,14 +85,8 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co return false } - @Suppress("UNCHECKED_CAST") - val process = entity as Process - val context = OmegaContext(entity).also { registry[entity] = it } - - // Bootstrap the process coroutine - val block: suspend () -> Unit = { process.run { context.run() } } - block.startCoroutine(context) - + val process = entity as Process<*, M> + spawnings.add(process) return true } @@ -102,6 +101,17 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co override fun step() { while (true) { + // Initialise all spawned processes + while (spawnings.isNotEmpty()) { + val process = spawnings.poll() + val context = OmegaContext(process).also { registry[process] = it } + + // Bootstrap the process coroutine + val block: suspend () -> Unit = { context.start() } + block.startCoroutine(context) + + } + val envelope = queue.peek() ?: return val delivery = envelope.time @@ -136,7 +146,7 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co override fun run() { - while (queue.isNotEmpty()) { + while (queue.isNotEmpty() || spawnings.isNotEmpty()) { step() } } @@ -148,7 +158,7 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co return } - while (time < until && queue.isNotEmpty()) { + while (time < until && (queue.isNotEmpty() || spawnings.isNotEmpty())) { step() } @@ -219,6 +229,13 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co override val , S> T.state: S get() = context?.state ?: initialState + /** + * 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. 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 index a1ec8e88..48b4f02a 100644 --- 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 @@ -27,6 +27,8 @@ 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 /** @@ -68,7 +70,7 @@ internal class SmokeTest { kernel.run() } - class NullProcess : Process { + object NullProcess : Process { override val initialState = Unit override suspend fun Context.run() {} } @@ -78,7 +80,7 @@ internal class SmokeTest { */ @Test fun `sending message to process that has gracefully stopped`() { - val process = NullProcess() + val process = NullProcess val bootstrap: Bootstrap = Bootstrap.create { ctx -> process.also { ctx.register(it) @@ -90,7 +92,7 @@ internal class SmokeTest { kernel.run() } - class CrashProcess : Process { + object CrashProcess : Process { override val initialState = Unit override suspend fun Context.run() { TODO("This process should crash") @@ -102,7 +104,7 @@ internal class SmokeTest { */ @Test fun `sending message to process that has crashed`() { - val process = CrashProcess() + val process = CrashProcess val bootstrap: Bootstrap = Bootstrap.create { ctx -> process.also { ctx.register(it) @@ -113,4 +115,30 @@ internal class SmokeTest { val kernel = OmegaKernelFactory.create(bootstrap) kernel.run() } + + class ModelProcess(private val value: Int) : Process { + override val initialState = false + override suspend fun Context.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 = Bootstrap.create { ctx -> + ctx.register(process) + value + } + + val kernel = OmegaKernelFactory.create(bootstrap) + kernel.run(5) + + assertTrue(kernel.run { process.state }) + } } -- cgit v1.2.3 From 2e819d59934b5308bc58d6c69709112e2a6af402 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Tue, 13 Feb 2018 14:27:15 +0100 Subject: refactor(#18): Fix OpenDC model deployment This change fixes the deployment of the OpenDC simulation model. --- .../kotlin/com/atlarge/opendc/omega/OmegaKernel.kt | 4 +- .../model/odc/topology/container/Datacenter.kt | 5 ++ .../com/atlarge/opendc/model/odc/JpaBootstrap.kt | 7 +++ .../opendc/model/odc/platform/JpaExperiment.kt | 24 ++++---- opendc-model-odc/setup/Dockerfile | 5 +- opendc-model-odc/setup/build.gradle | 2 +- .../opendc/model/odc/platform/JpaPlatformRunner.kt | 66 ++++++++++++++++++++++ .../src/main/kotlin/platform/JpaPlatformRunner.kt | 66 ---------------------- 8 files changed, 94 insertions(+), 85 deletions(-) create mode 100644 opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt delete mode 100644 opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt index 91150078..6ece73aa 100644 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt @@ -122,7 +122,7 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co break } else if (delivery < time) { // Tick has already occurred - logger.warn { "message processed out of order" } + logger.warn { "Message processed out of order" } } queue.poll() @@ -270,7 +270,7 @@ internal class OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Co override suspend fun Entity<*, *>.send(msg: Any, delay: Duration) = send(msg, process, delay) override suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = - schedule(prepare(msg, sender, delay = delay)) + schedule(prepare(msg, this, sender, delay)) override suspend fun Entity<*, *>.interrupt() = send(Interrupt) 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 index b9b804d3..7293d9f7 100644 --- 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 @@ -26,6 +26,7 @@ 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 @@ -88,6 +89,10 @@ interface Datacenter : Process { 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) } 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 index 09d8f4b3..8c32c54d 100644 --- 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 @@ -5,6 +5,7 @@ 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. @@ -12,6 +13,11 @@ import com.atlarge.opendc.simulator.Bootstrap * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ class JpaBootstrap(val experiment: Experiment) : Bootstrap { + /** + * The logging instance. + */ + private val logger = KotlinLogging.logger {} + /** * Bootstrap a model `M` for a kernel in the given context. * @@ -35,6 +41,7 @@ class JpaBootstrap(val experiment: Experiment) : Bootstrap { // 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) } } 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 index 6c3ad5e8..74f96ccb 100644 --- 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 @@ -115,22 +115,20 @@ class JpaExperiment(private val manager: EntityManager, manager.persist(wrapped) } - trace.jobs.asSequence() - .flatMap { it.tasks.asSequence() } - .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) - } + 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.run(simulation.time + 1) + simulation.step() } // Set the experiment state diff --git a/opendc-model-odc/setup/Dockerfile b/opendc-model-odc/setup/Dockerfile index 70e6fe11..bfebc044 100644 --- a/opendc-model-odc/setup/Dockerfile +++ b/opendc-model-odc/setup/Dockerfile @@ -17,7 +17,7 @@ USER root WORKDIR $APP_HOME # Build the application -RUN gradle --no-daemon :opendc-model-odc:setup: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-odc-model/setup/build/install/setup/bin/setup - +CMD opendc-model-odc/setup/build/install/setup/bin/setup diff --git a/opendc-model-odc/setup/build.gradle b/opendc-model-odc/setup/build.gradle index ddb5860b..1cca2a6e 100644 --- a/opendc-model-odc/setup/build.gradle +++ b/opendc-model-odc/setup/build.gradle @@ -44,7 +44,7 @@ apply plugin: 'application' apply plugin: 'kotlin' apply plugin: 'org.jetbrains.dokka' -mainClassName = "nl.atlarge.opendc.model.odc.platform.JpaPlatformRunnerKt" +mainClassName = "com.atlarge.opendc.model.odc.platform.JpaPlatformRunnerKt" compileKotlin { kotlinOptions { diff --git a/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt b/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt new file mode 100644 index 00000000..eb819a5b --- /dev/null +++ b/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt @@ -0,0 +1,66 @@ +/* + * 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.platform.JpaExperimentManager +import com.atlarge.opendc.omega.OmegaKernelFactory +import mu.KotlinLogging +import java.util.concurrent.Executors +import javax.persistence.Persistence + +val logger = KotlinLogging.logger {} + +/** + * The main entry point of the program. This program polls experiments from a database and runs the + * simulation and reports the results back to the database. + * + * @param args The command line arguments of the program. + */ +fun main(args: Array) { + val properties = HashMap() + 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 = OmegaKernelFactory + + 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) + } +} diff --git a/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt b/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt deleted file mode 100644 index 8fe49844..00000000 --- a/opendc-model-odc/setup/src/main/kotlin/platform/JpaPlatformRunner.kt +++ /dev/null @@ -1,66 +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 platform - -import com.atlarge.opendc.model.odc.platform.JpaExperimentManager -import com.atlarge.opendc.omega.OmegaKernelFactory -import mu.KotlinLogging -import java.util.concurrent.Executors -import javax.persistence.Persistence - -val logger = KotlinLogging.logger {} - -/** - * The main entry point of the program. This program polls experiments from a database and runs the - * simulation and reports the results back to the database. - * - * @param args The command line arguments of the program. - */ -fun main(args: Array) { - val properties = HashMap() - 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 = OmegaKernelFactory - - 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) - } -} -- cgit v1.2.3 From 157d30beb52c75831e29a1a22c199b95d6d30b42 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Wed, 14 Feb 2018 12:32:57 +0100 Subject: refactor(#18): Create distinction between kernel and simulation This change creates a distinction between a kernel and a simulation. A single simulation is represented by a `Simulation` object which provides control over the simulation, while the `Kernel` interface allows users to create a new simulation using that kernel as backend. --- .../com/atlarge/opendc/simulator/Bootstrap.kt | 20 +- .../com/atlarge/opendc/simulator/kernel/Kernel.kt | 50 +--- .../opendc/simulator/kernel/KernelFactory.kt | 42 --- .../atlarge/opendc/simulator/kernel/Simulation.kt | 74 +++++ .../opendc/simulator/platform/Experiment.kt | 6 +- .../kotlin/com/atlarge/opendc/omega/OmegaKernel.kt | 300 +------------------ .../com/atlarge/opendc/omega/OmegaKernelFactory.kt | 47 --- .../com/atlarge/opendc/omega/OmegaSimulation.kt | 331 +++++++++++++++++++++ .../kotlin/com/atlarge/opendc/omega/SmokeTest.kt | 18 +- .../com/atlarge/opendc/model/odc/JpaBootstrap.kt | 8 +- .../opendc/model/odc/platform/JpaExperiment.kt | 8 +- .../opendc/model/odc/platform/JpaPlatformRunner.kt | 5 +- .../com/atlarge/opendc/model/topology/Bootstrap.kt | 2 +- 13 files changed, 453 insertions(+), 458 deletions(-) delete mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt create mode 100644 opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Simulation.kt delete mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt create mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt 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 index 10a89704..5f41c727 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Bootstrap.kt @@ -9,15 +9,15 @@ package com.atlarge.opendc.simulator */ interface Bootstrap { /** - * Bootstrap a model `M` for a kernel in the given context. + * Apply the apply procedure for model `M` for a simulation in the given context. * - * @param context The context to bootstrap to model in. - * @return The initialised model for the simulation. + * @param context The context to apply to model in. + * @return The initialised, resulting model for the simulation. */ - fun bootstrap(context: Context): M + fun apply(context: Context): M /** - * A context for the bootstrap of some model type `M` that allows the model to register the entities of the model to + * 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) @@ -40,7 +40,7 @@ interface Bootstrap { fun deregister(entity: Entity<*, M>): Boolean /** - * Schedule a message for processing by a [Context]. + * Schedule a message to be received by the given [Entity]. * * @param message The message to schedule. * @param destination The destination of the message. @@ -52,13 +52,13 @@ interface Bootstrap { companion object { /** - * Create a [Bootstrap] procedure using the given block to produce a bootstrap for a model of type `M`. + * 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 bootstrap. - * @return The bootstrap procedure that has been built. + * @param block The block to produce the apply. + * @return The apply procedure that has been built. */ fun create(block: (Context) -> M): Bootstrap = object : Bootstrap { - override fun bootstrap(context: Context) = block(context) + override fun apply(context: Context) = block(context) } } } diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt index 29b3bdee..d4995283 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/Kernel.kt @@ -25,55 +25,19 @@ package com.atlarge.opendc.simulator.kernel import com.atlarge.opendc.simulator.Bootstrap -import com.atlarge.opendc.simulator.Entity -import com.atlarge.opendc.simulator.Instant /** - * A message based discrete event simulation kernel. + * A message-based discrete event simulator (DES). This interface is a factory for creating [Simulation]s using the + * provided [Bootstrap] for the model. * - * The kernel is created by bootstrapping some model `M` (see [Bootstrap]) to simulate and controls the simulation by - * allowing the user to step over cycles in the simulation and inspect the internal state using [Entity.state]. - * - * A kernel should provide additionally a [KernelFactory] to create new kernel instances given a certain model - * [Bootstrap]. - * - * @param M The shape of the model over which the simulation runs. * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -interface Kernel { - /** - * 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 , 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() - +interface Kernel { /** - * 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. + * Create a simulation over the given model facilitated by this simulation kernel. * - * @param until The point in simulation time at which the simulation should be paused and the control is handed - * back to the user. + * @param bootstrap The apply procedure to apply the simulation with. + * @return A [Simulation] instance representing the simulation. */ - fun run(until: Instant) + fun create(bootstrap: Bootstrap): Simulation } diff --git a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt deleted file mode 100644 index 30abb7ca..00000000 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/kernel/KernelFactory.kt +++ /dev/null @@ -1,42 +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 com.atlarge.opendc.simulator.kernel - -import com.atlarge.opendc.simulator.Bootstrap - -/** - * A factory for bootstrapping simulation [Kernel] instances. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface KernelFactory { - /** - * Create a simulation over the given model facilitated by this simulation kernel. - * - * @param bootstrap The bootstrap procedure to bootstrap the simulation with. - * @return A [Kernel] instance to control the simulation. - */ - fun create(bootstrap: Bootstrap): Kernel -} 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 { + /** + * 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 , 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/com/atlarge/opendc/simulator/platform/Experiment.kt b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt index 92d56be1..eb959ded 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/platform/Experiment.kt @@ -25,7 +25,7 @@ package com.atlarge.opendc.simulator.platform import com.atlarge.opendc.simulator.Duration -import com.atlarge.opendc.simulator.kernel.KernelFactory +import com.atlarge.opendc.simulator.kernel.Kernel /** * A blueprint for a reproducible simulation in a pre-defined setting. @@ -39,7 +39,7 @@ interface Experiment { * @param factory The factory to create the simulation kernel with. * @return The result of the experiment. */ - fun run(factory: KernelFactory): T + fun run(factory: Kernel): T /** * Run the experiment on the specified kernel implementation. @@ -48,5 +48,5 @@ interface Experiment { * @param timeout The maximum duration of the experiment before returning to the caller. * @return The result of the experiment or `null`. */ - fun run(factory: KernelFactory, timeout: Duration): T? + fun run(factory: Kernel, timeout: Duration): T? } diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt index 6ece73aa..e0d70eed 100644 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt @@ -24,11 +24,9 @@ package com.atlarge.opendc.omega -import com.atlarge.opendc.simulator.* +import com.atlarge.opendc.simulator.Bootstrap +import com.atlarge.opendc.simulator.kernel.Simulation import com.atlarge.opendc.simulator.kernel.Kernel -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. @@ -36,296 +34,14 @@ import kotlin.coroutines.experimental.* * 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 OmegaKernel(bootstrap: Bootstrap) : Kernel, Bootstrap.Context { +object OmegaKernel : Kernel { /** - * The logger instance to use for the simulator. + * 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. */ - private val logger = KotlinLogging.logger {} - - /** - * The registry of the simulation kernels used in the experiment. - */ - private val registry: MutableMap, OmegaContext<*>> = HashMap() - - /** - * The message queue. - */ - private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) - - /** - * The processes to be spawned. - */ - private val spawnings: Queue> = ArrayDeque() - - /** - * The simulation time. - */ - override var time: Instant = 0 - - /** - * The model of simulation. - */ - override val model: M = bootstrap.bootstrap(this) - - override val , S> E.state: S - get() = context?.state ?: initialState - - /** - * The context associated with an [Entity]. - */ - @Suppress("UNCHECKED_CAST") - private val , S, M> E.context: OmegaContext? - get() = registry[this] as? OmegaContext - - override fun register(entity: Entity<*, M>): Boolean { - if (!registry.containsKey(entity) && entity !is Process) { - return false - } - - val process = entity as Process<*, M> - spawnings.add(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)) - - override fun step() { - while (true) { - // Initialise all spawned processes - while (spawnings.isNotEmpty()) { - val process = spawnings.poll() - val context = OmegaContext(process).also { registry[process] = it } - - // Bootstrap the process coroutine - val block: suspend () -> Unit = { context.start() } - block.startCoroutine(context) - - } - - 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() || spawnings.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() || spawnings.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 - } - } - - private fun schedule(envelope: MessageContainer) { - queue.add(envelope) - } - - private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, - delay: Duration): MessageContainer { - require(delay >= 0) { "The amount of time to delay the message must be a positive number" } - return MessageContainer(message, time + delay, sender, destination) - } - - /** - * This internal class provides the default implementation for the [Context] interface for this simulator. - */ - private inner class OmegaContext(val process: Process) : Context, Continuation { - /** - * The continuation to resume the execution of the process. - */ - lateinit var continuation: Continuation> - - /** - * The last point in time the process has done some work. - */ - var last: Instant = -1 - - /** - * The model in which the process exists. - */ - override val model: M - get() = this@OmegaKernel.model - - /** - * The state of the entity. - */ - override var state: S = process.initialState - - /** - * The current point in simulation time. - */ - override val time: Instant - get() = this@OmegaKernel.time - - /** - * 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 [CoroutineContext] for a [Context]. - */ - override val context: CoroutineContext = EmptyCoroutineContext - - /** - * The observable state of an [Entity] within the simulation is provided by the context of the simulation. - */ - override val , S> T.state: S - get() = context?.state ?: initialState - - /** - * 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(): Envelope<*> = suspendCoroutine { continuation = it } - - override suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T { - val envelope = receiveEnvelope() - return transform(envelope, envelope.message) - } - - - override suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? { - val send = prepare(Timeout, process, process, timeout).also { schedule(it) } - - try { - val received = receiveEnvelope() - - if (received.message == Timeout) { - send.canceled = true - return transform(received, received.message) - } - - return null - } finally { - send.canceled = true - } - } - - override suspend fun Entity<*, *>.send(msg: Any, delay: Duration) = send(msg, process, delay) - - override suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = - schedule(prepare(msg, this, sender, delay)) - - override suspend fun Entity<*, *>.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) { - 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 - } - } - - - // 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" } - } - } + override fun create(bootstrap: Bootstrap): Simulation = OmegaSimulation(bootstrap) } diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt deleted file mode 100644 index 139cbd19..00000000 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernelFactory.kt +++ /dev/null @@ -1,47 +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 com.atlarge.opendc.omega - -import com.atlarge.opendc.simulator.Bootstrap -import com.atlarge.opendc.simulator.kernel.Kernel -import com.atlarge.opendc.simulator.kernel.KernelFactory - -/** - * 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. - * - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -object OmegaKernelFactory : KernelFactory { - /** - * Create a simulation over the given model facilitated by this simulation kernel. - * - * @param bootstrap The bootstrap procedure to bootstrap the simulation with. - * @return A [Kernel] instance to control the simulation. - */ - override fun create(bootstrap: Bootstrap): Kernel = OmegaKernel(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..80ac4600 --- /dev/null +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt @@ -0,0 +1,331 @@ +/* + * 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(bootstrap: Bootstrap) : Simulation, Bootstrap.Context { + /** + * 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, OmegaContext<*>> = HashMap() + + /** + * The message queue. + */ + private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) + + /** + * The processes to be spawned. + */ + private val spawnings: Queue> = ArrayDeque() + + /** + * The simulation time. + */ + override var time: Instant = 0 + + /** + * The model of simulation. + */ + override val model: M = bootstrap.apply(this) + + override val , S> E.state: S + get() = context?.state ?: initialState + + /** + * The context associated with an [Entity]. + */ + @Suppress("UNCHECKED_CAST") + private val , S, M> E.context: OmegaContext? + get() = registry[this] as? OmegaContext + + override fun register(entity: Entity<*, M>): Boolean { + if (!registry.containsKey(entity) && entity !is Process) { + return false + } + + val process = entity as Process<*, M> + spawnings.add(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)) + + override fun step() { + while (true) { + // Initialise all spawned processes + while (spawnings.isNotEmpty()) { + val process = spawnings.poll() + val context = OmegaContext(process).also { registry[process] = it } + + // Bootstrap the process coroutine + val block: suspend () -> Unit = { context.start() } + block.startCoroutine(context) + + } + + 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() || spawnings.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() || spawnings.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 + } + } + + private fun schedule(envelope: MessageContainer) { + queue.add(envelope) + } + + private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, + delay: Duration): MessageContainer { + require(delay >= 0) { "The amount of time to delay the message must be a positive number" } + return MessageContainer(message, time + delay, sender, destination) + } + + /** + * This internal class provides the default implementation for the [Context] interface for this simulator. + */ + private inner class OmegaContext(val process: Process) : Context, Continuation { + /** + * The continuation to resume the execution of the process. + */ + lateinit var continuation: Continuation> + + /** + * The last point in time the process has done some work. + */ + var last: Instant = -1 + + /** + * The model in which the process exists. + */ + override val model: M + get() = this@OmegaSimulation.model + + /** + * The state of the entity. + */ + override var state: S = process.initialState + + /** + * The current point in simulation time. + */ + override val time: Instant + get() = this@OmegaSimulation.time + + /** + * 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 [CoroutineContext] for a [Context]. + */ + override val context: CoroutineContext = EmptyCoroutineContext + + /** + * The observable state of an [Entity] within the simulation is provided by the context of the simulation. + */ + override val , S> T.state: S + get() = context?.state ?: initialState + + /** + * 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(): Envelope<*> = suspendCoroutine { continuation = it } + + override suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T { + val envelope = receiveEnvelope() + return transform(envelope, envelope.message) + } + + + override suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? { + val send = prepare(Timeout, process, process, timeout).also { schedule(it) } + + try { + val received = receiveEnvelope() + + if (received.message == Timeout) { + send.canceled = true + return transform(received, received.message) + } + + return null + } finally { + send.canceled = true + } + } + + override suspend fun Entity<*, *>.send(msg: Any, delay: Duration) = send(msg, process, delay) + + override suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = + schedule(prepare(msg, this, sender, delay)) + + override suspend fun Entity<*, *>.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) { + 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 + } + } + + + // 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 index 48b4f02a..74fa686b 100644 --- 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 @@ -66,8 +66,8 @@ internal class SmokeTest { } } } - val kernel = OmegaKernelFactory.create(bootstrap) - kernel.run() + val simulation = OmegaKernel.create(bootstrap) + simulation.run() } object NullProcess : Process { @@ -88,8 +88,8 @@ internal class SmokeTest { } } - val kernel = OmegaKernelFactory.create(bootstrap) - kernel.run() + val simulation = OmegaKernel.create(bootstrap) + simulation.run() } object CrashProcess : Process { @@ -112,8 +112,8 @@ internal class SmokeTest { } } - val kernel = OmegaKernelFactory.create(bootstrap) - kernel.run() + val simulation = OmegaKernel.create(bootstrap) + simulation.run() } class ModelProcess(private val value: Int) : Process { @@ -136,9 +136,9 @@ internal class SmokeTest { value } - val kernel = OmegaKernelFactory.create(bootstrap) - kernel.run(5) + val simulation = OmegaKernel.create(bootstrap) + simulation.run(5) - assertTrue(kernel.run { process.state }) + assertTrue(simulation.run { process.state }) } } 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 index 8c32c54d..0a0c792c 100644 --- 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 @@ -21,20 +21,20 @@ class JpaBootstrap(val experiment: Experiment) : Bootstrap { /** * Bootstrap a model `M` for a kernel in the given context. * - * @param context The context to bootstrap to model in. + * @param context The context to apply to model in. * @return The initialised model for the simulation. */ - override fun bootstrap(context: Bootstrap.Context): JpaModel { + override fun apply(context: Bootstrap.Context): JpaModel { val section = experiment.path.sections.first() - // TODO We should not modify parts of the experiment in a bootstrap as the bootstrap should be reproducible. + // 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() - .bootstrap(context) + .apply(context) val trace = experiment.trace val tasks = trace.jobs.flatMap { it.tasks } 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 index 74f96ccb..4e88b3d4 100644 --- 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 @@ -34,7 +34,7 @@ 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.KernelFactory +import com.atlarge.opendc.simulator.kernel.Kernel import com.atlarge.opendc.simulator.platform.Experiment import mu.KotlinLogging import java.io.Closeable @@ -65,7 +65,7 @@ class JpaExperiment(private val manager: EntityManager, * @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: KernelFactory, timeout: Duration): Unit? { + override fun run(factory: Kernel, timeout: Duration): Unit? { if (experiment.state != ExperimentState.CLAIMED) { throw IllegalStateException("The experiment is in illegal state ${experiment.state}") } @@ -136,7 +136,7 @@ class JpaExperiment(private val manager: EntityManager, experiment.state = ExperimentState.FINISHED } - logger.info { "Kernel done" } + 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) @@ -165,7 +165,7 @@ class JpaExperiment(private val manager: EntityManager, * @param factory The factory to create the simulation kernel with. * @throws IllegalStateException if the simulation is already running or finished. */ - override fun run(factory: KernelFactory) = run(factory, -1)!! + override fun run(factory: Kernel) = run(factory, -1)!! /** * Closes this resource, relinquishing any underlying resources. diff --git a/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt b/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt index eb819a5b..13f322bc 100644 --- a/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt +++ b/opendc-model-odc/setup/src/main/kotlin/com/atlarge/opendc/model/odc/platform/JpaPlatformRunner.kt @@ -24,8 +24,7 @@ package com.atlarge.opendc.model.odc.platform -import com.atlarge.opendc.model.odc.platform.JpaExperimentManager -import com.atlarge.opendc.omega.OmegaKernelFactory +import com.atlarge.opendc.omega.OmegaKernel import mu.KotlinLogging import java.util.concurrent.Executors import javax.persistence.Persistence @@ -50,7 +49,7 @@ fun main(args: Array) { val threads = 4 val executorService = Executors.newFixedThreadPool(threads) val experiments = JpaExperimentManager(factory) - val kernel = OmegaKernelFactory + val kernel = OmegaKernel logger.info { "Waiting for enqueued experiments..." } while (true) { 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 index 1a5bbcaf..e0b54a28 100644 --- 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 @@ -6,7 +6,7 @@ import com.atlarge.opendc.simulator.Entity /** * Create a [Bootstrap] procedure for the given [Topology]. * - * @return A bootstrap procedure for the topology. + * @return A apply procedure for the topology. */ fun T.bootstrap(): Bootstrap = Bootstrap.create { ctx -> forEach { ctx.register(it) } -- cgit v1.2.3 From 99dc5592bbca0f7d3a9d411268608c112b135896 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Thu, 15 Feb 2018 16:18:55 +0100 Subject: refactor(#18): Handle process launch using a kernel process This change will make the kernel handle the launch of processes using a kernel process that is launched at the start of the simulation and launches processes when it receives `Launch` messages. --- .../com/atlarge/opendc/omega/MessageContainer.kt | 48 ------- .../kotlin/com/atlarge/opendc/omega/Messages.kt | 30 +++++ .../com/atlarge/opendc/omega/OmegaSimulation.kt | 142 ++++++++++++++------- .../main/kotlin/com/atlarge/opendc/omega/Resume.kt | 39 ------ .../kotlin/com/atlarge/opendc/omega/Timeout.kt | 35 ----- 5 files changed, 129 insertions(+), 165 deletions(-) delete mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt create mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Messages.kt delete mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt delete mode 100644 opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt deleted file mode 100644 index 32f27111..00000000 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/MessageContainer.kt +++ /dev/null @@ -1,48 +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 com.atlarge.opendc.omega - -import com.atlarge.opendc.simulator.Entity -import com.atlarge.opendc.simulator.Envelope -import com.atlarge.opendc.simulator.Instant - -/** - * 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 { - /** - * A flag to indicate the message has been canceled. - */ - internal var canceled: Boolean = false -} 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..73c3676f --- /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(val process: Process<*, M>) 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 index 80ac4600..71b20e34 100644 --- 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 @@ -46,7 +46,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot private val logger = KotlinLogging.logger {} /** - * The registry of the simulation kernels used in the experiment. + * The registry of the processes used in the simulation. */ private val registry: MutableMap, OmegaContext<*>> = HashMap() @@ -56,9 +56,29 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) /** - * The processes to be spawned. + * The kernel process instance that handles internal operations during the simulation. */ - private val spawnings: Queue> = ArrayDeque() + private val process = object : Process { + override val initialState = Unit + + override suspend fun Context.run() { + while(true) { + val msg = receive() + when (msg) { + is Launch<*> -> + @Suppress("UNCHECKED_CAST") + launch((msg as Launch).process) + } + } + } + } + + /** + * The context associated with an [Entity]. + */ + @Suppress("UNCHECKED_CAST") + private val , S, M> E.context: OmegaContext? + get() = registry[this] as? OmegaContext /** * The simulation time. @@ -68,25 +88,30 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot /** * The model of simulation. */ - override val model: M = bootstrap.apply(this) + // 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 , S> E.state: S get() = context?.state ?: initialState /** - * The context associated with an [Entity]. + * Initialise the simulation instance. */ - @Suppress("UNCHECKED_CAST") - private val , S, M> E.context: OmegaContext? - get() = registry[this] as? OmegaContext + 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 } - val process = entity as Process<*, M> - spawnings.add(process) + schedule(Launch(entity as Process<*, M>), process) return true } @@ -99,19 +124,9 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot override fun schedule(message: Any, destination: Entity<*, *>, sender: Entity<*, *>?, delay: Duration) = schedule(prepare(message, destination, sender, delay)) + // Simulation implementation override fun step() { while (true) { - // Initialise all spawned processes - while (spawnings.isNotEmpty()) { - val process = spawnings.poll() - val context = OmegaContext(process).also { registry[process] = it } - - // Bootstrap the process coroutine - val block: suspend () -> Unit = { context.start() } - block.startCoroutine(context) - - } - val envelope = queue.peek() ?: return val delivery = envelope.time @@ -144,9 +159,8 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot } } - override fun run() { - while (queue.isNotEmpty() || spawnings.isNotEmpty()) { + while (queue.isNotEmpty()) { step() } } @@ -158,7 +172,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot return } - while (time < until && (queue.isNotEmpty() || spawnings.isNotEmpty())) { + while (time < until && queue.isNotEmpty()) { step() } @@ -170,10 +184,42 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot } } + /** + * 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) + */ + private data class MessageContainer(override val message: Any, + val time: Instant, + override val sender: Entity<*, *>?, + override val destination: Entity<*, *>) : Envelope { + /** + * 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: MessageContainer) { 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): MessageContainer { require(delay >= 0) { "The amount of time to delay the message must be a positive number" } @@ -181,19 +227,22 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot } /** - * This internal class provides the default implementation for the [Context] interface for this simulator. + * Launch the given [Process]. + * + * @param process The process to launch. */ - private inner class OmegaContext(val process: Process) : Context, Continuation { - /** - * The continuation to resume the execution of the process. - */ - lateinit var continuation: Continuation> + private fun launch(process: Process<*, M>) { + val context = OmegaContext(process).also { registry[process] = it } - /** - * The last point in time the process has done some work. - */ - var last: Instant = -1 + // 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(val process: Process) : Context, Continuation { /** * The model in which the process exists. */ @@ -230,19 +279,14 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot get() = context?.state ?: initialState /** - * Start the process associated with this context. + * The continuation to resume the execution of the process. */ - internal suspend fun start() = process.run { - run() - } + lateinit var continuation: Continuation> /** - * 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. + * The last point in time the process has done some work. */ - suspend fun receiveEnvelope(): Envelope<*> = suspendCoroutine { continuation = it } + var last: Instant = -1 override suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T { val envelope = receiveEnvelope() @@ -304,6 +348,18 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot } } + /** + * 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(): Envelope<*> = suspendCoroutine { continuation = it } // Completion continuation implementation /** diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt deleted file mode 100644 index d4bd8536..00000000 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Resume.kt +++ /dev/null @@ -1,39 +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 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 diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt deleted file mode 100644 index c205f6b5..00000000 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/Timeout.kt +++ /dev/null @@ -1,35 +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 com.atlarge.opendc.omega - -import com.atlarge.opendc.simulator.Process - -/** - * 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 -- cgit v1.2.3 From 2fa0134773a99394aae0efc167af6767e2828c71 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 16 Feb 2018 14:32:16 +0100 Subject: refactor(#18): Fix broken receive() timeout This change fixes the broken implementation of the `receive()` method with a timeout due to an invalid condition. --- .../src/main/kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 71b20e34..9c6d4ab3 100644 --- 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 @@ -300,7 +300,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot try { val received = receiveEnvelope() - if (received.message == Timeout) { + if (received.message != Timeout) { send.canceled = true return transform(received, received.message) } -- cgit v1.2.3 From b84a995a05fecb9ef90c9184959f285f324e7411 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 16 Feb 2018 14:39:53 +0100 Subject: refactor(#18): Provide access to latest sender This change adds a `sender` property to the `Context` interface to provide processes access to the sender of the latest received message. Please note that methods like `hold()` and `interrupt()` may change the value of this property. --- .../kotlin/com/atlarge/opendc/simulator/Context.kt | 8 ++++++++ .../com/atlarge/opendc/omega/OmegaSimulation.kt | 22 ++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) 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 index c89bdb59..13170256 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt @@ -50,6 +50,14 @@ interface Context { */ val delta: Duration + /** + * 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. */ 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 index 9c6d4ab3..bd3f4529 100644 --- 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 @@ -249,11 +249,6 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot override val model: M get() = this@OmegaSimulation.model - /** - * The state of the entity. - */ - override var state: S = process.initialState - /** * The current point in simulation time. */ @@ -268,9 +263,9 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot get() = maxOf(time - last, 0) /** - * The [CoroutineContext] for a [Context]. + * The state of the entity. */ - override val context: CoroutineContext = EmptyCoroutineContext + override var state: S = process.initialState /** * The observable state of an [Entity] within the simulation is provided by the context of the simulation. @@ -278,6 +273,16 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot override val , 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 = EmptyCoroutineContext + /** * The continuation to resume the execution of the process. */ @@ -359,7 +364,8 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot * * @return The envelope containing the message. */ - suspend fun receiveEnvelope(): Envelope<*> = suspendCoroutine { continuation = it } + suspend fun receiveEnvelope() = suspendCoroutine> { continuation = it } + .also { sender = it.sender } // Completion continuation implementation /** -- cgit v1.2.3 From f8a4095d1824df095ea91253f914bc0512646684 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Fri, 16 Feb 2018 15:25:19 +0100 Subject: refactor(#18): Provide access to process context in nested calls This change provides a method in the standard library to access the process context in nested suspending function calls. --- .../kotlin/com/atlarge/opendc/simulator/Context.kt | 30 +++++++++++++-- .../kotlin/com/atlarge/opendc/simulator/Process.kt | 2 +- .../kotlin/com/atlarge/opendc/omega/Messages.kt | 2 +- .../com/atlarge/opendc/omega/OmegaSimulation.kt | 13 +++++-- .../kotlin/com/atlarge/opendc/simulator/Helpers.kt | 44 ++++++++++++++++++++++ 5 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 opendc-stdlib/src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt 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 index 13170256..24f87eff 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt @@ -25,6 +25,7 @@ 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 @@ -33,7 +34,7 @@ import java.util.* * * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -interface Context { +interface Context : CoroutineContext.Element { /** * The model of simulation in which the entity exists. */ @@ -50,6 +51,11 @@ interface Context { */ val delta: Duration + /** + * The [Entity] associated with this context. + */ + val self: Entity + /** * The sender of the last received message or `null` in case the process has not received any messages yet. * @@ -68,6 +74,14 @@ interface Context { */ val , S> E.state: S + /** + * 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)) + /** * Interrupt an [Entity] process in simulation. * @@ -75,8 +89,10 @@ interface Context { * 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() + suspend fun Entity<*, *>.interrupt(interrupt: Interrupt) /** * Suspend the [Context] of the [Entity] in simulation for the given duration of simulation time before resuming @@ -159,6 +175,11 @@ interface Context { * @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) + + /** + * This key provides users access to an untyped process context in case the coroutine runs inside a simulation. + */ + companion object Key : CoroutineContext.Key> } /** @@ -185,8 +206,9 @@ interface Envelope { } /** - * An [Interrupt] message is sent to a [Entity] process in order to interrupt its suspended state. + * 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) */ -object Interrupt : Throwable("The entity process has been interrupted by another entity") +open class Interrupt(reason: String) : Throwable(reason) 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 index e8b4d988..f2b8a52b 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Process.kt @@ -8,7 +8,7 @@ package com.atlarge.opendc.simulator * @param M The shape of the model in which the process exists. * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -interface Process : Entity { +interface Process : Entity { /** * This method is invoked to start the simulation a process. * 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 index 73c3676f..d63a53c8 100644 --- 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 @@ -27,4 +27,4 @@ object Timeout * * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ -data class Launch(val process: Process<*, M>) +data class Launch(val process: Process<*, M>) 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 index bd3f4529..22382ccd 100644 --- 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 @@ -242,7 +242,8 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot /** * This internal class provides the default implementation for the [Context] interface for this simulator. */ - private inner class OmegaContext(val process: Process) : Context, Continuation { + private inner class OmegaContext(val process: Process) : Context, Continuation, + AbstractCoroutineContextElement(Context) { /** * The model in which the process exists. */ @@ -255,6 +256,12 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot override val time: Instant get() = this@OmegaSimulation.time + /** + * The [Entity] associated with this context. + */ + override val self: Entity + 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. @@ -281,7 +288,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot /** * The [CoroutineContext] for a [Context]. */ - override val context: CoroutineContext = EmptyCoroutineContext + override val context: CoroutineContext = this /** * The continuation to resume the execution of the process. @@ -321,7 +328,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot override suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = schedule(prepare(msg, this, sender, delay)) - override suspend fun Entity<*, *>.interrupt() = send(Interrupt) + 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" } 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..acf3fe41 --- /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.* + +/** + * 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 contextOrNull(): Context? = 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 context(): Context = + 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() + +/** + * 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() -- cgit v1.2.3 From 0f84a74536e404f707c4f4e370efbaad8d12b89a Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sat, 17 Feb 2018 11:18:07 +0100 Subject: refactor(#18): Optimize imports --- .../src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt | 2 +- opendc-model-odc/jpa/src/main/resources/jpa/schema.xml | 6 +++--- .../src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt index e0d70eed..c0ab9fb4 100644 --- a/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt +++ b/opendc-kernel-omega/src/main/kotlin/com/atlarge/opendc/omega/OmegaKernel.kt @@ -25,8 +25,8 @@ package com.atlarge.opendc.omega import com.atlarge.opendc.simulator.Bootstrap -import com.atlarge.opendc.simulator.kernel.Simulation 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. diff --git a/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml b/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml index 142c3ee8..887cc8ab 100644 --- a/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml +++ b/opendc-model-odc/jpa/src/main/resources/jpa/schema.xml @@ -22,9 +22,9 @@ ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ~ SOFTWARE. --> - com.atlarge.opendc.model.odc.integration.jpa.schema 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 index acf3fe41..0f6392ed 100644 --- a/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt +++ b/opendc-stdlib/src/main/kotlin/com/atlarge/opendc/simulator/Helpers.kt @@ -1,6 +1,6 @@ package com.atlarge.opendc.simulator -import kotlin.coroutines.experimental.intrinsics.* +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 -- cgit v1.2.3 From ac0a8505ceb817e33011ff80f8585b199896b9c4 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 19 Feb 2018 14:15:55 +0100 Subject: bug: Make message priority queue stable This change fixes the bug where the insertion order into the message queue was not guaranteed for messages arriving at the same time, causing some non-deterministic behaviour. --- .../kotlin/com/atlarge/opendc/omega/OmegaSimulation.kt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) 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 index 22382ccd..8c1497c8 100644 --- 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 @@ -53,7 +53,9 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot /** * The message queue. */ - private val queue: Queue = PriorityQueue(Comparator.comparingLong(MessageContainer::time)) + private val queue: Queue = PriorityQueue(Comparator + .comparingLong(MessageContainer::time) + .thenComparingLong(MessageContainer::id)) /** * The kernel process instance that handles internal operations during the simulation. @@ -184,16 +186,23 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot } } + /** + * 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. * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) */ - private data class MessageContainer(override val message: Any, + private data class MessageContainer(val id: Long, + override val message: Any, val time: Instant, override val sender: Entity<*, *>?, override val destination: Entity<*, *>) : Envelope { @@ -223,7 +232,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, delay: Duration): MessageContainer { require(delay >= 0) { "The amount of time to delay the message must be a positive number" } - return MessageContainer(message, time + delay, sender, destination) + return MessageContainer(nextId++, message, time + delay, sender, destination) } /** -- cgit v1.2.3 From 59247a4f7a2dc948b3a63ff185c64922eb4334ea Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 19 Feb 2018 15:09:19 +0100 Subject: refactor(#18): Refactor unused transformation receive methods This change removes the unused transformation receive methods from the `Context` class as this functionality can now be easily implemented in the standard library using the newly introduced `sender` property. --- .../kotlin/com/atlarge/opendc/simulator/Context.kt | 50 +--------------------- .../com/atlarge/opendc/omega/OmegaSimulation.kt | 37 +++++++--------- .../kotlin/com/atlarge/opendc/omega/SmokeTest.kt | 5 +-- 3 files changed, 20 insertions(+), 72 deletions(-) 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 index 24f87eff..b1d635fd 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt @@ -117,36 +117,13 @@ interface Context : CoroutineContext.Element { */ suspend fun hold(duration: Duration, queue: Queue) - /** - * 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 after which the message [Envelope] is - * transformed through `transform` to return the transformed result. - * - * @param transform The block to transform the message with in an envelope context, providing access to the sender - * of the message. - * @return The transformed message. - */ - suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T - - /** - * 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 after which the message - * [Envelope] is transformed through `transform` to return the transformed result or the timeout has been reached. - * - * @param timeout The duration to wait before resuming execution. - * @param transform The block to transform the message with in an envelope context, providing access to the sender - * of the message. - * @return The processed message or `null` if the timeout was reached. - */ - suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? - /** * 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 = receive { it } + suspend fun receive(): Any /** * Retrieve and remove a single message from the instance's mailbox, suspending the function if the mailbox is @@ -155,7 +132,7 @@ interface Context : CoroutineContext.Element { * * @return The received message or `null` if the timeout was reached. */ - suspend fun receive(timeout: Duration): Any? = receive(timeout) { it } + suspend fun receive(timeout: Duration): Any? /** * Send the given message to the specified entity, without providing any guarantees about the actual delivery of @@ -182,29 +159,6 @@ interface Context : CoroutineContext.Element { companion object Key : CoroutineContext.Key> } -/** - * The message envelope that is sent to an [Entity], also containing the metadata of the message. - * - * @param T The shape of the message inside the envelope. - * @author Fabian Mastenbroek (f.s.mastenbroek@student.tudelft.nl) - */ -interface Envelope { - /** - * The message in this envelope. - */ - val message: T - - /** - * The sender of the message. - */ - val sender: Entity<*, *>? - - /** - * The destination of the message. - */ - val destination: Entity<*, *> -} - /** * An [Interrupt] message is sent to an [Entity] process in order to interrupt its suspended state. * 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 index 8c1497c8..4d94bf9e 100644 --- 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 @@ -53,9 +53,9 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot /** * The message queue. */ - private val queue: Queue = PriorityQueue(Comparator - .comparingLong(MessageContainer::time) - .thenComparingLong(MessageContainer::id)) + private val queue: Queue = PriorityQueue(Comparator + .comparingLong(Envelope::time) + .thenComparingLong(Envelope::id)) /** * The kernel process instance that handles internal operations during the simulation. @@ -199,13 +199,12 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot * @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) */ - private data class MessageContainer(val id: Long, - override val message: Any, - val time: Instant, - override val sender: Entity<*, *>?, - override val destination: Entity<*, *>) : Envelope { + 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. */ @@ -217,7 +216,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot * * @param envelope The envelope containing the message to schedule. */ - private fun schedule(envelope: MessageContainer) { + private fun schedule(envelope: Envelope) { queue.add(envelope) } @@ -230,9 +229,9 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot * @param delay The time to delay the message. */ private fun prepare(message: Any, destination: Entity<*, *>, sender: Entity<*, *>? = null, - delay: Duration): MessageContainer { + delay: Duration): Envelope { require(delay >= 0) { "The amount of time to delay the message must be a positive number" } - return MessageContainer(nextId++, message, time + delay, sender, destination) + return Envelope(nextId++, message, time + delay, sender, destination) } /** @@ -302,20 +301,16 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot /** * The continuation to resume the execution of the process. */ - lateinit var continuation: Continuation> + lateinit var continuation: Continuation /** * The last point in time the process has done some work. */ var last: Instant = -1 - override suspend fun receive(transform: suspend Envelope<*>.(Any) -> T): T { - val envelope = receiveEnvelope() - return transform(envelope, envelope.message) - } - + override suspend fun receive(): Any = receiveEnvelope().message - override suspend fun receive(timeout: Duration, transform: suspend Envelope<*>.(Any) -> T): T? { + override suspend fun receive(timeout: Duration): Any? { val send = prepare(Timeout, process, process, timeout).also { schedule(it) } try { @@ -323,7 +318,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot if (received.message != Timeout) { send.canceled = true - return transform(received, received.message) + return received.message } return null @@ -380,7 +375,7 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot * * @return The envelope containing the message. */ - suspend fun receiveEnvelope() = suspendCoroutine> { continuation = it } + suspend fun receiveEnvelope() = suspendCoroutine { continuation = it } .also { sender = it.sender } // Completion continuation implementation 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 index 74fa686b..c47f9a26 100644 --- 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 @@ -41,9 +41,8 @@ internal class SmokeTest { override val initialState = Unit override suspend fun Context.run() { while (true) { - receive { - sender?.send(message) - } + val msg = receive() + sender?.send(msg) } } } -- cgit v1.2.3 From 86dc826db4cd91b5a6875d9ecdd64c9238d7b95c Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Mon, 19 Feb 2018 15:12:16 +0100 Subject: refactor(#18): Simplify Context interface This change simplifies the `Context` interface to reduce the amount of methods required to implement by implementors. --- .../kotlin/com/atlarge/opendc/simulator/Context.kt | 22 +++++++++++----------- .../com/atlarge/opendc/omega/OmegaSimulation.kt | 2 -- 2 files changed, 11 insertions(+), 13 deletions(-) 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 index b1d635fd..23d10e8f 100644 --- a/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt +++ b/opendc-core/src/main/kotlin/com/atlarge/opendc/simulator/Context.kt @@ -74,14 +74,6 @@ interface Context : CoroutineContext.Element { */ val , S> E.state: S - /** - * 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)) - /** * Interrupt an [Entity] process in simulation. * @@ -94,6 +86,14 @@ interface Context : CoroutineContext.Element { */ 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. @@ -139,19 +139,19 @@ interface Context : CoroutineContext.Element { * 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, delay: Duration = 0) + 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 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) + 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. 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 index 4d94bf9e..532a033a 100644 --- 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 @@ -327,8 +327,6 @@ internal class OmegaSimulation(bootstrap: Bootstrap) : Simulation, Boot } } - override suspend fun Entity<*, *>.send(msg: Any, delay: Duration) = send(msg, process, delay) - override suspend fun Entity<*, *>.send(msg: Any, sender: Entity<*, *>, delay: Duration) = schedule(prepare(msg, this, sender, delay)) -- cgit v1.2.3