summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java20
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/host/SimHost.kt37
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt22
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMetricReader.kt29
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMonitor.kt14
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ComputeExportConfig.kt33
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt114
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt20
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltPowerSourceExportColumns.kt25
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltServiceExportColumns.kt2
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt16
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ParquetComputeMonitor.kt23
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryInfo.kt30
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt73
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt131
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostInfo.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostInfo.kt)4
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReader.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostTableReader.kt)4
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReaderImpl.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostTableReaderImpl.kt)16
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceInfo.kt30
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceTableReader.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/PowerSourceTableReader.kt)4
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceTableReaderImpl.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/PowerSourceTableReaderImpl.kt)12
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceData.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceData.kt)2
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceTableReader.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceTableReader.kt)2
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceTableReaderImpl.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceTableReaderImpl.kt)2
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskInfo.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskInfo.kt)4
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReader.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskTableReader.kt)5
-rw-r--r--opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReaderImpl.kt (renamed from opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskTableReaderImpl.kt)9
-rw-r--r--opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt98
-rw-r--r--opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt4
-rw-r--r--opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/HostSpec.kt6
-rw-r--r--opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/PowerSourceSpec.kt3
-rw-r--r--opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt15
-rw-r--r--opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt3
-rw-r--r--opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/BatteryTest.kt2
-rw-r--r--opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt10
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/SimPowerSource.java24
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/BatteryState.java6
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java106
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java14
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java64
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java12
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt7
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt10
43 files changed, 775 insertions, 292 deletions
diff --git a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java
index 6fa6af60..aa2c13b9 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java
+++ b/opendc-compute/opendc-compute-simulator/src/main/java/org/opendc/compute/simulator/service/ComputeService.java
@@ -56,6 +56,7 @@ import org.opendc.compute.simulator.scheduler.SchedulingResultType;
import org.opendc.compute.simulator.telemetry.ComputeMetricReader;
import org.opendc.compute.simulator.telemetry.SchedulerStats;
import org.opendc.simulator.compute.power.SimPowerSource;
+import org.opendc.simulator.compute.power.batteries.SimBattery;
import org.opendc.simulator.compute.workload.Workload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -109,6 +110,11 @@ public final class ComputeService implements AutoCloseable {
private final Set<SimPowerSource> powerSources = new HashSet<>();
/**
+ * The available powerSources
+ */
+ private final Set<SimBattery> batteries = new HashSet<>();
+
+ /**
* The tasks that should be launched by the service.
*/
private final Deque<SchedulingRequest> taskQueue = new ArrayDeque<>();
@@ -307,6 +313,15 @@ public final class ComputeService implements AutoCloseable {
powerSources.add(simPowerSource);
}
+ public void addBattery(SimBattery simBattery) {
+ // Check if host is already known
+ if (batteries.contains(simBattery)) {
+ return;
+ }
+
+ batteries.add(simBattery);
+ }
+
/**
* Remove a {@link SimHost} from the scheduling pool of the compute service.
*/
@@ -341,6 +356,10 @@ public final class ComputeService implements AutoCloseable {
return Collections.unmodifiableSet(this.powerSources);
}
+ public Set<SimBattery> getBatteries() {
+ return Collections.unmodifiableSet(this.batteries);
+ }
+
public void setMetricReader(ComputeMetricReader metricReader) {
this.metricReader = metricReader;
}
@@ -445,6 +464,7 @@ public final class ComputeService implements AutoCloseable {
final HostView hv = result.getHost();
final SchedulingRequest req = result.getReq();
final ServiceTask task = req.getTask();
+
final ServiceFlavor flavor = task.getFlavor();
if (task.getNumFailures() >= maxNumFailures) {
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/host/SimHost.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/host/SimHost.kt
index cc4ac2d8..132ad227 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/host/SimHost.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/host/SimHost.kt
@@ -40,24 +40,21 @@ import org.opendc.simulator.engine.graph.FlowGraph
import java.time.Duration
import java.time.Instant
import java.time.InstantSource
-import java.util.UUID
/**
- * A [Host] implementation that simulates virtual machines on a physical machine.
+ * A [SimHost] implementation that simulates virtual machines on a physical machine.
*
- * @param uid The unique identifier of the host.
* @param name The name of the host.
- * @param meta The metadata of the host.
* @param clock The (virtual) clock used to track time.
* @param graph The Flow Graph that the Host is part of
* @param machineModel The static model of the host
- * @param powerModel The static powerModel of the CPU TODO: can this be combined with machinemodel?
+ * @param cpuPowerModel The power model of the host
+ * @param powerDistributor The power distributor to which the host is connected
* @constructor Create empty Sim host
*/
public class SimHost(
- private val uid: UUID,
private val name: String,
- private val meta: Map<String, Any>,
+ private val clusterName: String,
private val clock: InstantSource,
private val graph: FlowGraph,
private val machineModel: MachineModel,
@@ -170,20 +167,16 @@ public class SimHost(
hostState = state
}
- public fun getUid(): UUID {
- return uid
- }
-
public fun getName(): String {
return name
}
- public fun getModel(): HostModel {
- return model
+ public fun getClusterName(): String {
+ return clusterName
}
- public fun getMeta(): Map<String, *> {
- return meta
+ public fun getModel(): HostModel {
+ return model
}
public fun getState(): HostState {
@@ -236,12 +229,12 @@ public class SimHost(
}
public fun start(task: ServiceTask) {
- val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.uid} at host $uid" }
+ val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.name} at host $name" }
guest.start()
}
public fun stop(task: ServiceTask) {
- val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.uid} at host $uid" }
+ val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.name} at host $name" }
guest.stop()
}
@@ -308,7 +301,7 @@ public class SimHost(
}
public fun getSystemStats(task: ServiceTask): GuestSystemStats {
- val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.uid} at host $uid" }
+ val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.name} at host $name" }
return guest.getSystemStats()
}
@@ -330,17 +323,17 @@ public class SimHost(
}
public fun getCpuStats(task: ServiceTask): GuestCpuStats {
- val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.uid} at host $uid" }
+ val guest = requireNotNull(taskToGuestMap[task]) { "Unknown task ${task.name} at host $name" }
return guest.getCpuStats()
}
- override fun hashCode(): Int = uid.hashCode()
+ override fun hashCode(): Int = name.hashCode()
override fun equals(other: Any?): Boolean {
- return other is SimHost && uid == other.uid
+ return other is SimHost && name == other.name
}
- override fun toString(): String = "SimHost[uid=$uid,name=$name,model=$model]"
+ override fun toString(): String = "SimHost[uid=$name,name=$name,model=$model]"
/**
* Convert flavor to machine model.
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt
index 572335e1..fcfa1b7b 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/provisioner/HostsProvisioningStep.kt
@@ -39,8 +39,8 @@ import org.opendc.simulator.engine.graph.FlowDistributor
* A [ProvisioningStep] that provisions a list of hosts for a [ComputeService].
*
* @param serviceDomain The domain name under which the compute service is registered.
- * @param specs A list of [HostSpec] objects describing the simulated hosts to provision.
- * @param optimize A flag to indicate that the CPU resources of the host should be merged into a single CPU resource.
+ * @param clusterSpecs A list of [HostSpec] objects describing the simulated hosts to provision.
+ * @param startTime The absolute start time of the simulation. Used to determine the carbon trace offset.
*/
public class HostsProvisioningStep internal constructor(
private val serviceDomain: String,
@@ -62,7 +62,7 @@ public class HostsProvisioningStep internal constructor(
// Create the Power Source to which hosts are connected
// Create Power Source
- val simPowerSource = SimPowerSource(graph, cluster.powerSource.totalPower.toDouble())
+ val simPowerSource = SimPowerSource(graph, cluster.powerSource.totalPower.toDouble(), cluster.powerSource.name, cluster.name)
simPowerSources.add(simPowerSource)
service.addPowerSource(simPowerSource)
@@ -84,7 +84,14 @@ public class HostsProvisioningStep internal constructor(
// Create Battery
val battery =
- SimBattery(graph, cluster.battery!!.capacity, cluster.battery!!.chargingSpeed, cluster.battery!!.initialCharge)
+ SimBattery(
+ graph,
+ cluster.battery!!.capacity,
+ cluster.battery!!.chargingSpeed,
+ cluster.battery!!.initialCharge,
+ cluster.battery!!.name,
+ cluster.name,
+ )
graph.addEdge(battery, batteryDistributor)
// Create Aggregator
@@ -102,6 +109,8 @@ public class HostsProvisioningStep internal constructor(
carbonModel?.addReceiver(batteryPolicy)
graph.addEdge(hostDistributor, batteryAggregator)
+
+ service.addBattery(battery)
} else {
graph.addEdge(hostDistributor, simPowerSource)
}
@@ -110,9 +119,8 @@ public class HostsProvisioningStep internal constructor(
for (hostSpec in cluster.hostSpecs) {
val simHost =
SimHost(
- hostSpec.uid,
hostSpec.name,
- hostSpec.meta,
+ cluster.name,
ctx.dispatcher.timeSource,
graph,
hostSpec.model,
@@ -120,7 +128,7 @@ public class HostsProvisioningStep internal constructor(
hostDistributor,
)
- require(simHosts.add(simHost)) { "Host with uid ${hostSpec.uid} already exists" }
+ require(simHosts.add(simHost)) { "Host with name ${hostSpec.name} already exists" }
service.addHost(simHost)
}
}
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMetricReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMetricReader.kt
index d5720649..10bc889b 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMetricReader.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMetricReader.kt
@@ -32,11 +32,13 @@ import org.opendc.common.asCoroutineDispatcher
import org.opendc.compute.simulator.host.SimHost
import org.opendc.compute.simulator.service.ComputeService
import org.opendc.compute.simulator.service.ServiceTask
-import org.opendc.compute.simulator.telemetry.table.HostTableReaderImpl
-import org.opendc.compute.simulator.telemetry.table.PowerSourceTableReaderImpl
-import org.opendc.compute.simulator.telemetry.table.ServiceTableReaderImpl
-import org.opendc.compute.simulator.telemetry.table.TaskTableReaderImpl
+import org.opendc.compute.simulator.telemetry.table.battery.BatteryTableReaderImpl
+import org.opendc.compute.simulator.telemetry.table.host.HostTableReaderImpl
+import org.opendc.compute.simulator.telemetry.table.powerSource.PowerSourceTableReaderImpl
+import org.opendc.compute.simulator.telemetry.table.service.ServiceTableReaderImpl
+import org.opendc.compute.simulator.telemetry.table.task.TaskTableReaderImpl
import org.opendc.simulator.compute.power.SimPowerSource
+import org.opendc.simulator.compute.power.batteries.SimBattery
import java.time.Duration
/**
@@ -86,6 +88,11 @@ public class ComputeMetricReader(
private val powerSourceTableReaders = mutableMapOf<SimPowerSource, PowerSourceTableReaderImpl>()
/**
+ * Mapping from [SimPowerSource] instances to [PowerSourceTableReaderImpl]
+ */
+ private val batteryTableReaders = mutableMapOf<SimBattery, BatteryTableReaderImpl>()
+
+ /**
* The background job that is responsible for collecting the metrics every cycle.
*/
private val job =
@@ -155,6 +162,20 @@ public class ComputeMetricReader(
reader.reset()
}
+ for (simBattery in this.service.batteries) {
+ val reader =
+ this.batteryTableReaders.computeIfAbsent(simBattery) {
+ BatteryTableReaderImpl(
+ it,
+ startTime,
+ )
+ }
+
+ reader.record(now)
+ this.monitor.record(reader.copy())
+ reader.reset()
+ }
+
this.serviceTableReader.record(now)
monitor.record(this.serviceTableReader.copy())
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMonitor.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMonitor.kt
index 5e1fe2c9..0c10e7a2 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMonitor.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/ComputeMonitor.kt
@@ -22,10 +22,11 @@
package org.opendc.compute.simulator.telemetry
-import org.opendc.compute.simulator.telemetry.table.HostTableReader
-import org.opendc.compute.simulator.telemetry.table.PowerSourceTableReader
-import org.opendc.compute.simulator.telemetry.table.ServiceTableReader
-import org.opendc.compute.simulator.telemetry.table.TaskTableReader
+import org.opendc.compute.simulator.telemetry.table.battery.BatteryTableReader
+import org.opendc.compute.simulator.telemetry.table.host.HostTableReader
+import org.opendc.compute.simulator.telemetry.table.powerSource.PowerSourceTableReader
+import org.opendc.compute.simulator.telemetry.table.service.ServiceTableReader
+import org.opendc.compute.simulator.telemetry.table.task.TaskTableReader
/**
* A monitor that tracks the metrics and events of the OpenDC Compute service.
@@ -49,5 +50,10 @@ public interface ComputeMonitor {
/**
* Record an entry with the specified [reader].
*/
+ public fun record(reader: BatteryTableReader) {}
+
+ /**
+ * Record an entry with the specified [reader].
+ */
public fun record(reader: ServiceTableReader) {}
}
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ComputeExportConfig.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ComputeExportConfig.kt
index 691d01c1..7c753ebf 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ComputeExportConfig.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ComputeExportConfig.kt
@@ -35,10 +35,11 @@ import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonObject
import org.opendc.common.logger.logger
-import org.opendc.compute.simulator.telemetry.table.HostTableReader
-import org.opendc.compute.simulator.telemetry.table.PowerSourceTableReader
-import org.opendc.compute.simulator.telemetry.table.ServiceTableReader
-import org.opendc.compute.simulator.telemetry.table.TaskTableReader
+import org.opendc.compute.simulator.telemetry.table.battery.BatteryTableReader
+import org.opendc.compute.simulator.telemetry.table.host.HostTableReader
+import org.opendc.compute.simulator.telemetry.table.powerSource.PowerSourceTableReader
+import org.opendc.compute.simulator.telemetry.table.service.ServiceTableReader
+import org.opendc.compute.simulator.telemetry.table.task.TaskTableReader
import org.opendc.trace.util.parquet.exporter.ColListSerializer
import org.opendc.trace.util.parquet.exporter.ExportColumn
import org.opendc.trace.util.parquet.exporter.Exportable
@@ -58,17 +59,20 @@ public data class ComputeExportConfig(
public val hostExportColumns: Set<ExportColumn<HostTableReader>>,
public val taskExportColumns: Set<ExportColumn<TaskTableReader>>,
public val powerSourceExportColumns: Set<ExportColumn<PowerSourceTableReader>>,
+ public val batteryExportColumns: Set<ExportColumn<BatteryTableReader>>,
public val serviceExportColumns: Set<ExportColumn<ServiceTableReader>>,
) {
public constructor(
hostExportColumns: Collection<ExportColumn<HostTableReader>>,
taskExportColumns: Collection<ExportColumn<TaskTableReader>>,
powerSourceExportColumns: Collection<ExportColumn<PowerSourceTableReader>>,
+ batteryExportColumns: Collection<ExportColumn<BatteryTableReader>>,
serviceExportColumns: Collection<ExportColumn<ServiceTableReader>>,
) : this(
hostExportColumns.toSet() + DfltHostExportColumns.BASE_EXPORT_COLUMNS,
taskExportColumns.toSet() + DfltTaskExportColumns.BASE_EXPORT_COLUMNS,
powerSourceExportColumns.toSet() + DfltPowerSourceExportColumns.BASE_EXPORT_COLUMNS,
+ batteryExportColumns.toSet() + DfltBatteryExportColumns.BASE_EXPORT_COLUMNS,
serviceExportColumns.toSet() + DfltServiceExportColumns.BASE_EXPORT_COLUMNS,
)
@@ -81,6 +85,7 @@ public data class ComputeExportConfig(
| Host columns : ${hostExportColumns.map { it.name }.toString().trim('[', ']')}
| Task columns : ${taskExportColumns.map { it.name }.toString().trim('[', ']')}
| Power Source columns : ${powerSourceExportColumns.map { it.name }.toString().trim('[', ']')}
+ | Power Source columns : ${batteryExportColumns.map { it.name }.toString().trim('[', ']')}
| Service columns : ${serviceExportColumns.map { it.name }.toString().trim('[', ']')}
""".trimIndent()
@@ -95,12 +100,13 @@ public data class ComputeExportConfig(
DfltHostExportColumns
DfltTaskExportColumns
DfltPowerSourceExportColumns
+ DfltBatteryExportColumns
DfltServiceExportColumns
}
/**
* Config that includes all columns defined in [DfltHostExportColumns], [DfltTaskExportColumns],
- * [DfltPowerSourceExportColumns], [DfltServiceExportColumns] among all other loaded
+ * [DfltPowerSourceExportColumns], [batteryExportColumns], [DfltServiceExportColumns] among all other loaded
* columns for [HostTableReader], [TaskTableReader] and [ServiceTableReader].
*/
public val ALL_COLUMNS: ComputeExportConfig by lazy {
@@ -109,6 +115,7 @@ public data class ComputeExportConfig(
hostExportColumns = ExportColumn.getAllLoadedColumns(),
taskExportColumns = ExportColumn.getAllLoadedColumns(),
powerSourceExportColumns = ExportColumn.getAllLoadedColumns(),
+ batteryExportColumns = ExportColumn.getAllLoadedColumns(),
serviceExportColumns = ExportColumn.getAllLoadedColumns(),
)
}
@@ -131,7 +138,11 @@ public data class ComputeExportConfig(
)
element(
"powerSourceExportColumns",
- ListSerializer(columnSerializer<ServiceTableReader>()).descriptor,
+ ListSerializer(columnSerializer<PowerSourceTableReader>()).descriptor,
+ )
+ element(
+ "batteryExportColumns",
+ ListSerializer(columnSerializer<BatteryTableReader>()).descriptor,
)
element(
"serviceExportColumns",
@@ -153,12 +164,14 @@ public data class ComputeExportConfig(
val hostFields: List<ExportColumn<HostTableReader>> = elem["hostExportColumns"].toFieldList()
val taskFields: List<ExportColumn<TaskTableReader>> = elem["taskExportColumns"].toFieldList()
val powerSourceFields: List<ExportColumn<PowerSourceTableReader>> = elem["powerSourceExportColumns"].toFieldList()
+ val batteryFields: List<ExportColumn<BatteryTableReader>> = elem["batteryExportColumns"].toFieldList()
val serviceFields: List<ExportColumn<ServiceTableReader>> = elem["serviceExportColumns"].toFieldList()
return ComputeExportConfig(
hostExportColumns = hostFields,
taskExportColumns = taskFields,
powerSourceExportColumns = powerSourceFields,
+ batteryExportColumns = batteryFields,
serviceExportColumns = serviceFields,
)
}
@@ -189,6 +202,12 @@ public data class ComputeExportConfig(
encodeSerializableElement(
descriptor,
3,
+ ColListSerializer(columnSerializer<BatteryTableReader>()),
+ value.batteryExportColumns.toList(),
+ )
+ encodeSerializableElement(
+ descriptor,
+ 4,
ColListSerializer(columnSerializer<ServiceTableReader>()),
value.serviceExportColumns.toList(),
)
@@ -204,7 +223,7 @@ private inline fun <reified T : Exportable> JsonElement?.toFieldList(): List<Exp
this?.let {
json.decodeFromJsonElement(ColListSerializer(columnSerializer<T>()), it)
}?.ifEmpty {
- ComputeExportConfig.Companion.LOG.warn(
+ ComputeExportConfig.LOG.warn(
"deserialized list of export columns for exportable ${T::class.simpleName} " +
"produced empty list, falling back to all loaded columns",
)
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt
new file mode 100644
index 00000000..274eceab
--- /dev/null
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltBatteryExportColumns.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2024 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.telemetry.parquet
+
+import org.apache.parquet.io.api.Binary
+import org.apache.parquet.schema.LogicalTypeAnnotation
+import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.BINARY
+import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.FLOAT
+import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT64
+import org.apache.parquet.schema.Types
+import org.opendc.compute.simulator.telemetry.table.battery.BatteryTableReader
+import org.opendc.trace.util.parquet.exporter.ExportColumn
+
+/**
+ * This object wraps the [ExportColumn]s to solves ambiguity for field
+ * names that are included in more than 1 exportable.
+ *
+ * Additionally, it allows to load all the fields at once by just its symbol,
+ * so that these columns can be deserialized. Additional fields can be added
+ * from anywhere, and they are deserializable as long as they are loaded by the jvm.
+ *
+ * ```kotlin
+ * ...
+ * // Loads the column
+ * DfltHostExportColumns
+ * ...
+ * ```
+ */
+public object DfltBatteryExportColumns {
+ public val TIMESTAMP: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field = Types.required(INT64).named("timestamp"),
+ ) { it.timestamp.toEpochMilli() }
+
+ public val TIMESTAMP_ABS: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field = Types.required(INT64).named("timestamp_absolute"),
+ ) { it.timestampAbsolute.toEpochMilli() }
+
+ public val NAME: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field =
+ Types.required(BINARY)
+ .`as`(LogicalTypeAnnotation.stringType())
+ .named("name"),
+ ) { Binary.fromString(it.batteryInfo.name) }
+
+ public val CLUSTER_NAME: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field =
+ Types.required(BINARY)
+ .`as`(LogicalTypeAnnotation.stringType())
+ .named("cluster_name"),
+ ) { Binary.fromString(it.batteryInfo.clusterName) }
+
+ public val POWER_DRAW: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field = Types.required(FLOAT).named("power_draw"),
+ ) { it.powerDraw }
+
+ public val ENERGY_USAGE: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field = Types.required(FLOAT).named("energy_usage"),
+ ) { it.energyUsage }
+
+ public val CHARGE: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field = Types.required(FLOAT).named("charge"),
+ ) { it.charge }
+
+ public val CAPACITY: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field = Types.required(FLOAT).named("capacity"),
+ ) { it.capacity }
+
+ public val BATTERY_STATE: ExportColumn<BatteryTableReader> =
+ ExportColumn(
+ field =
+ Types.optional(BINARY)
+ .`as`(LogicalTypeAnnotation.stringType())
+ .named("battery_state"),
+ ) { Binary.fromString(it.batteryState.name) }
+
+ /**
+ * The columns that are always included in the output file.
+ */
+ internal val BASE_EXPORT_COLUMNS =
+ setOf(
+ TIMESTAMP_ABS,
+ TIMESTAMP,
+ NAME,
+ CLUSTER_NAME,
+ )
+}
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt
index 805b224d..13304b47 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltHostExportColumns.kt
@@ -29,7 +29,7 @@ import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.FLOAT
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT32
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT64
import org.apache.parquet.schema.Types
-import org.opendc.compute.simulator.telemetry.table.HostTableReader
+import org.opendc.compute.simulator.telemetry.table.host.HostTableReader
import org.opendc.trace.util.parquet.exporter.ExportColumn
/**
@@ -58,31 +58,31 @@ public object DfltHostExportColumns {
field = Types.required(INT64).named("timestamp_absolute"),
) { it.timestampAbsolute.toEpochMilli() }
- public val HOST_ID: ExportColumn<HostTableReader> =
+ public val NAME: ExportColumn<HostTableReader> =
ExportColumn(
field =
Types.required(BINARY)
.`as`(LogicalTypeAnnotation.stringType())
- .named("host_id"),
- ) { Binary.fromString(it.host.id) }
+ .named("name"),
+ ) { Binary.fromString(it.hostInfo.name) }
- public val HOST_NAME: ExportColumn<HostTableReader> =
+ public val CLUSTER_NAME: ExportColumn<HostTableReader> =
ExportColumn(
field =
Types.required(BINARY)
.`as`(LogicalTypeAnnotation.stringType())
- .named("host_name"),
- ) { Binary.fromString(it.host.name) }
+ .named("cluster_name"),
+ ) { Binary.fromString(it.hostInfo.clusterName) }
public val CPU_COUNT: ExportColumn<HostTableReader> =
ExportColumn(
field = Types.required(INT32).named("core_count"),
- ) { it.host.coreCount }
+ ) { it.hostInfo.coreCount }
public val MEM_CAPACITY: ExportColumn<HostTableReader> =
ExportColumn(
field = Types.required(INT64).named("mem_capacity"),
- ) { it.host.memCapacity }
+ ) { it.hostInfo.memCapacity }
public val GUESTS_TERMINATED: ExportColumn<HostTableReader> =
ExportColumn(
@@ -181,5 +181,7 @@ public object DfltHostExportColumns {
setOf(
TIMESTAMP_ABS,
TIMESTAMP,
+ NAME,
+ CLUSTER_NAME,
)
}
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltPowerSourceExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltPowerSourceExportColumns.kt
index 95db55fe..192667b9 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltPowerSourceExportColumns.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltPowerSourceExportColumns.kt
@@ -22,11 +22,13 @@
package org.opendc.compute.simulator.telemetry.parquet
+import org.apache.parquet.io.api.Binary
+import org.apache.parquet.schema.LogicalTypeAnnotation
+import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.BINARY
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.FLOAT
-import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT32
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT64
import org.apache.parquet.schema.Types
-import org.opendc.compute.simulator.telemetry.table.PowerSourceTableReader
+import org.opendc.compute.simulator.telemetry.table.powerSource.PowerSourceTableReader
import org.opendc.trace.util.parquet.exporter.ExportColumn
/**
@@ -55,10 +57,21 @@ public object DfltPowerSourceExportColumns {
field = Types.required(INT64).named("timestamp_absolute"),
) { it.timestampAbsolute.toEpochMilli() }
- public val CPU_COUNT: ExportColumn<PowerSourceTableReader> =
+ public val NAME: ExportColumn<PowerSourceTableReader> =
ExportColumn(
- field = Types.required(INT32).named("hosts_connected"),
- ) { it.hostsConnected }
+ field =
+ Types.required(BINARY)
+ .`as`(LogicalTypeAnnotation.stringType())
+ .named("name"),
+ ) { Binary.fromString(it.powerSourceInfo.name) }
+
+ public val CLUSTER_NAME: ExportColumn<PowerSourceTableReader> =
+ ExportColumn(
+ field =
+ Types.required(BINARY)
+ .`as`(LogicalTypeAnnotation.stringType())
+ .named("cluster_name"),
+ ) { Binary.fromString(it.powerSourceInfo.clusterName) }
public val POWER_DRAW: ExportColumn<PowerSourceTableReader> =
ExportColumn(
@@ -87,5 +100,7 @@ public object DfltPowerSourceExportColumns {
setOf(
TIMESTAMP_ABS,
TIMESTAMP,
+ NAME,
+ CLUSTER_NAME,
)
}
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltServiceExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltServiceExportColumns.kt
index aa08e8ff..374b2d31 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltServiceExportColumns.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltServiceExportColumns.kt
@@ -25,7 +25,7 @@ package org.opendc.compute.simulator.telemetry.parquet
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT32
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT64
import org.apache.parquet.schema.Types
-import org.opendc.compute.simulator.telemetry.table.ServiceTableReader
+import org.opendc.compute.simulator.telemetry.table.service.ServiceTableReader
import org.opendc.trace.util.parquet.exporter.ExportColumn
/**
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt
index cf315947..52a84236 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/DfltTaskExportColumns.kt
@@ -29,7 +29,7 @@ import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.FLOAT
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT32
import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT64
import org.apache.parquet.schema.Types
-import org.opendc.compute.simulator.telemetry.table.TaskTableReader
+import org.opendc.compute.simulator.telemetry.table.task.TaskTableReader
import org.opendc.trace.util.parquet.exporter.ExportColumn
/**
@@ -66,13 +66,13 @@ public object DfltTaskExportColumns {
.named("task_id"),
) { Binary.fromString(it.taskInfo.id) }
- public val HOST_ID: ExportColumn<TaskTableReader> =
- ExportColumn(
- field =
- Types.optional(BINARY)
- .`as`(LogicalTypeAnnotation.stringType())
- .named("host_id"),
- ) { it.host?.id?.let { Binary.fromString(it) } }
+// public val HOST_ID: ExportColumn<TaskTableReader> =
+// ExportColumn(
+// field =
+// Types.optional(BINARY)
+// .`as`(LogicalTypeAnnotation.stringType())
+// .named("host_id"),
+// ) { it.host?.id?.let { Binary.fromString(it) } }
public val TASK_NAME: ExportColumn<TaskTableReader> =
ExportColumn(
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ParquetComputeMonitor.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ParquetComputeMonitor.kt
index b3150018..7d2b9363 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ParquetComputeMonitor.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/parquet/ParquetComputeMonitor.kt
@@ -23,10 +23,11 @@
package org.opendc.compute.simulator.telemetry.parquet
import org.opendc.compute.simulator.telemetry.ComputeMonitor
-import org.opendc.compute.simulator.telemetry.table.HostTableReader
-import org.opendc.compute.simulator.telemetry.table.PowerSourceTableReader
-import org.opendc.compute.simulator.telemetry.table.ServiceTableReader
-import org.opendc.compute.simulator.telemetry.table.TaskTableReader
+import org.opendc.compute.simulator.telemetry.table.battery.BatteryTableReader
+import org.opendc.compute.simulator.telemetry.table.host.HostTableReader
+import org.opendc.compute.simulator.telemetry.table.powerSource.PowerSourceTableReader
+import org.opendc.compute.simulator.telemetry.table.service.ServiceTableReader
+import org.opendc.compute.simulator.telemetry.table.task.TaskTableReader
import org.opendc.trace.util.parquet.exporter.ExportColumn
import org.opendc.trace.util.parquet.exporter.Exportable
import org.opendc.trace.util.parquet.exporter.Exporter
@@ -39,6 +40,7 @@ public class ParquetComputeMonitor(
private val hostExporter: Exporter<HostTableReader>,
private val taskExporter: Exporter<TaskTableReader>,
private val powerSourceExporter: Exporter<PowerSourceTableReader>,
+ private val batteryExporter: Exporter<BatteryTableReader>,
private val serviceExporter: Exporter<ServiceTableReader>,
) : ComputeMonitor, AutoCloseable {
override fun record(reader: HostTableReader) {
@@ -53,6 +55,10 @@ public class ParquetComputeMonitor(
powerSourceExporter.write(reader)
}
+ override fun record(reader: BatteryTableReader) {
+ batteryExporter.write(reader)
+ }
+
override fun record(reader: ServiceTableReader) {
serviceExporter.write(reader)
}
@@ -61,6 +67,7 @@ public class ParquetComputeMonitor(
hostExporter.close()
taskExporter.close()
powerSourceExporter.close()
+ batteryExporter.close()
serviceExporter.close()
}
@@ -85,6 +92,7 @@ public class ParquetComputeMonitor(
hostExportColumns = computeExportConfig.hostExportColumns,
taskExportColumns = computeExportConfig.taskExportColumns,
powerSourceExportColumns = computeExportConfig.powerSourceExportColumns,
+ batteryExportColumns = computeExportConfig.batteryExportColumns,
serviceExportColumns = computeExportConfig.serviceExportColumns,
)
@@ -104,6 +112,7 @@ public class ParquetComputeMonitor(
hostExportColumns: Collection<ExportColumn<HostTableReader>>? = null,
taskExportColumns: Collection<ExportColumn<TaskTableReader>>? = null,
powerSourceExportColumns: Collection<ExportColumn<PowerSourceTableReader>>? = null,
+ batteryExportColumns: Collection<ExportColumn<BatteryTableReader>>? = null,
serviceExportColumns: Collection<ExportColumn<ServiceTableReader>>? = null,
): ParquetComputeMonitor {
// Loads the fields in case they need to be retrieved if optional params are omitted.
@@ -128,6 +137,12 @@ public class ParquetComputeMonitor(
columns = powerSourceExportColumns ?: Exportable.getAllLoadedColumns(),
bufferSize = bufferSize,
),
+ batteryExporter =
+ Exporter(
+ outputFile = File(base, "$partition/battery.parquet").also { it.parentFile.mkdirs() },
+ columns = batteryExportColumns ?: Exportable.getAllLoadedColumns(),
+ bufferSize = bufferSize,
+ ),
serviceExporter =
Exporter(
outputFile = File(base, "$partition/service.parquet").also { it.parentFile.mkdirs() },
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryInfo.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryInfo.kt
new file mode 100644
index 00000000..7dac5920
--- /dev/null
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryInfo.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.telemetry.table.battery
+
+public data class BatteryInfo(
+ val name: String,
+ val clusterName: String,
+ val arch: String,
+ val capacity: Double,
+)
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt
new file mode 100644
index 00000000..6747d676
--- /dev/null
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReader.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.telemetry.table.battery
+
+import org.opendc.simulator.compute.power.batteries.BatteryState
+import org.opendc.trace.util.parquet.exporter.Exportable
+import java.time.Instant
+
+/**
+ * An interface that is used to read a row of a host trace entry.
+ */
+public interface BatteryTableReader : Exportable {
+ public fun copy(): BatteryTableReader
+
+ public fun setValues(table: BatteryTableReader)
+
+ public fun record(now: Instant)
+
+ public fun reset()
+
+ public val batteryInfo: BatteryInfo
+
+ /**
+ * The timestamp of the current entry of the reader relative to the start of the workload.
+ */
+ public val timestamp: Instant
+
+ /**
+ * The timestamp of the current entry of the reader.
+ */
+ public val timestampAbsolute: Instant
+
+ /**
+ * The number of connected hosts
+ */
+ public val hostsConnected: Int
+
+ /**
+ * The current power draw of the host in W.
+ */
+ public val powerDraw: Double
+
+ /**
+ * The current power draw of the host in W.
+ */
+ public val energyUsage: Double
+
+ public val batteryState: BatteryState
+
+ public val charge: Double
+
+ public val capacity: Double
+}
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt
new file mode 100644
index 00000000..7b666c30
--- /dev/null
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/battery/BatteryTableReaderImpl.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2024 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.telemetry.table.battery
+
+import org.opendc.simulator.compute.power.batteries.BatteryState
+import org.opendc.simulator.compute.power.batteries.SimBattery
+import java.time.Duration
+import java.time.Instant
+
+/**
+ * An aggregator for task metrics before they are reported.
+ */
+public class BatteryTableReaderImpl(
+ private val battery: SimBattery,
+ private val startTime: Duration = Duration.ofMillis(0),
+) : BatteryTableReader {
+ override fun copy(): BatteryTableReader {
+ val newPowerSourceTable =
+ BatteryTableReaderImpl(
+ battery,
+ )
+ newPowerSourceTable.setValues(this)
+
+ return newPowerSourceTable
+ }
+
+ override fun setValues(table: BatteryTableReader) {
+ _timestamp = table.timestamp
+ _timestampAbsolute = table.timestampAbsolute
+
+ _hostsConnected = table.hostsConnected
+ _powerDraw = table.powerDraw
+ _energyUsage = table.energyUsage
+ _charge = table.charge
+ _capacity = table.capacity
+ _batteryState = table.batteryState
+ }
+
+ public override val batteryInfo: BatteryInfo =
+ BatteryInfo(
+ battery.name,
+ battery.clusterName,
+ "XXX",
+ battery.capacity,
+ )
+
+ private var _timestamp = Instant.MIN
+ override val timestamp: Instant
+ get() = _timestamp
+
+ private var _timestampAbsolute = Instant.MIN
+ override val timestampAbsolute: Instant
+ get() = _timestampAbsolute
+
+ override val hostsConnected: Int
+ get() = _hostsConnected
+ private var _hostsConnected: Int = 0
+
+ override val powerDraw: Double
+ get() = _powerDraw
+ private var _powerDraw = 0.0
+
+ override val energyUsage: Double
+ get() = _energyUsage - previousEnergyUsage
+ private var _energyUsage = 0.0
+ private var previousEnergyUsage = 0.0
+
+ override val charge: Double
+ get() = _charge
+ private var _charge = 0.0
+
+ override val capacity: Double
+ get() = _capacity
+ private var _capacity = 0.0
+
+ override val batteryState: BatteryState
+ get() = _batteryState
+ private var _batteryState = BatteryState.IDLE
+
+ /**
+ * Record the next cycle.
+ */
+ override fun record(now: Instant) {
+ _timestamp = now
+ _timestampAbsolute = now + startTime
+
+ _hostsConnected = 0
+
+ battery.updateCounters()
+ _powerDraw = battery.outgoingSupply
+ _energyUsage = battery.totalEnergyUsage
+
+ _charge = battery.charge
+ _capacity = battery.capacity
+ _batteryState = battery.batteryState
+ }
+
+ /**
+ * Finish the aggregation for this cycle.
+ */
+ override fun reset() {
+ previousEnergyUsage = _energyUsage
+
+ _hostsConnected = 0
+ _powerDraw = 0.0
+ _energyUsage = 0.0
+ _charge = 0.0
+ _capacity = 0.0
+ _batteryState = BatteryState.IDLE
+ }
+}
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostInfo.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostInfo.kt
index 0220971b..b3b4ede8 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostInfo.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostInfo.kt
@@ -20,14 +20,14 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.host
/**
* Information about a host exposed to the telemetry service.
*/
public data class HostInfo(
- val id: String,
val name: String,
+ val clusterName: String,
val arch: String,
val coreCount: Int,
val coreSpeed: Double,
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReader.kt
index 35565f82..1d3d46d9 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostTableReader.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReader.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.host
import org.opendc.trace.util.parquet.exporter.Exportable
import java.time.Instant
@@ -40,7 +40,7 @@ public interface HostTableReader : Exportable {
/**
* The [HostInfo] of the host to which the row belongs to.
*/
- public val host: HostInfo
+ public val hostInfo: HostInfo
/**
* The timestamp of the current entry of the reader relative to the start of the workload.
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReaderImpl.kt
index 90f091f2..5babb864 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/HostTableReaderImpl.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/host/HostTableReaderImpl.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.host
import org.opendc.compute.simulator.host.SimHost
import java.time.Duration
@@ -30,12 +30,12 @@ import java.time.Instant
* An aggregator for host metrics before they are reported.
*/
public class HostTableReaderImpl(
- host: SimHost,
+ private val host: SimHost,
private val startTime: Duration = Duration.ofMillis(0),
) : HostTableReader {
override fun copy(): HostTableReader {
val newHostTable =
- HostTableReaderImpl(_host)
+ HostTableReaderImpl(host)
newHostTable.setValues(this)
return newHostTable
@@ -65,12 +65,10 @@ public class HostTableReaderImpl(
_bootTimeAbsolute = table.bootTimeAbsolute
}
- private val _host = host
-
- override val host: HostInfo =
+ override val hostInfo: HostInfo =
HostInfo(
- host.getUid().toString(),
host.getName(),
+ host.getClusterName(),
"x86",
host.getModel().coreCount,
host.getModel().cpuCapacity,
@@ -168,8 +166,8 @@ public class HostTableReaderImpl(
* Record the next cycle.
*/
override fun record(now: Instant) {
- val hostCpuStats = _host.getCpuStats()
- val hostSysStats = _host.getSystemStats()
+ val hostCpuStats = host.getCpuStats()
+ val hostSysStats = host.getSystemStats()
_timestamp = now
_timestampAbsolute = now + startTime
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceInfo.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceInfo.kt
new file mode 100644
index 00000000..6b558b72
--- /dev/null
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceInfo.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 AtLarge Research
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.opendc.compute.simulator.telemetry.table.powerSource
+
+public data class PowerSourceInfo(
+ val name: String,
+ val clusterName: String,
+ val arch: String,
+ val capacity: Double,
+)
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/PowerSourceTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceTableReader.kt
index cd2b2d2c..ac69d8a5 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/PowerSourceTableReader.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceTableReader.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.powerSource
import org.opendc.trace.util.parquet.exporter.Exportable
import java.time.Instant
@@ -37,6 +37,8 @@ public interface PowerSourceTableReader : Exportable {
public fun reset()
+ public val powerSourceInfo: PowerSourceInfo
+
/**
* The timestamp of the current entry of the reader relative to the start of the workload.
*/
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/PowerSourceTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceTableReaderImpl.kt
index 6a44d1ea..9779f27a 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/PowerSourceTableReaderImpl.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/powerSource/PowerSourceTableReaderImpl.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.powerSource
import org.opendc.simulator.compute.power.SimPowerSource
import java.time.Duration
@@ -30,7 +30,7 @@ import java.time.Instant
* An aggregator for task metrics before they are reported.
*/
public class PowerSourceTableReaderImpl(
- powerSource: SimPowerSource,
+ private val powerSource: SimPowerSource,
private val startTime: Duration = Duration.ofMillis(0),
) : PowerSourceTableReader {
override fun copy(): PowerSourceTableReader {
@@ -54,7 +54,13 @@ public class PowerSourceTableReaderImpl(
_carbonEmission = table.carbonEmission
}
- private val powerSource = powerSource
+ public override val powerSourceInfo: PowerSourceInfo =
+ PowerSourceInfo(
+ powerSource.name,
+ powerSource.clusterName,
+ "XXX",
+ powerSource.capacity,
+ )
private var _timestamp = Instant.MIN
override val timestamp: Instant
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceData.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceData.kt
index 16c38297..970c9d38 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceData.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceData.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.service
import java.time.Instant
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceTableReader.kt
index c8cc765a..b84520a5 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceTableReader.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceTableReader.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.service
import org.opendc.trace.util.parquet.exporter.Exportable
import java.time.Instant
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceTableReaderImpl.kt
index 52a25021..daa04ba3 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/ServiceTableReaderImpl.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/service/ServiceTableReaderImpl.kt
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.service
import org.opendc.compute.simulator.service.ComputeService
import java.time.Duration
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskInfo.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskInfo.kt
index 6ff56541..e0b28379 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskInfo.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskInfo.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2025 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
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.task
/**
* Static information about a task exposed to the telemetry service.
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskTableReader.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReader.kt
index 0a752e75..97d8ca88 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskTableReader.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReader.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 AtLarge Research
+ * Copyright (c) 2025 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
@@ -20,10 +20,11 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.task
import org.opendc.compute.api.TaskState
import org.opendc.compute.simulator.telemetry.parquet.DfltTaskExportColumns
+import org.opendc.compute.simulator.telemetry.table.host.HostInfo
import org.opendc.trace.util.parquet.exporter.Exportable
import java.time.Instant
diff --git a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskTableReaderImpl.kt b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReaderImpl.kt
index edcc8b20..07462b14 100644
--- a/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/TaskTableReaderImpl.kt
+++ b/opendc-compute/opendc-compute-simulator/src/main/kotlin/org/opendc/compute/simulator/telemetry/table/task/TaskTableReaderImpl.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024 AtLarge Research
+ * Copyright (c) 2025 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
@@ -20,12 +20,13 @@
* SOFTWARE.
*/
-package org.opendc.compute.simulator.telemetry.table
+package org.opendc.compute.simulator.telemetry.table.task
import org.opendc.compute.api.TaskState
import org.opendc.compute.simulator.host.SimHost
import org.opendc.compute.simulator.service.ComputeService
import org.opendc.compute.simulator.service.ServiceTask
+import org.opendc.compute.simulator.telemetry.table.host.HostInfo
import java.time.Duration
import java.time.Instant
@@ -171,12 +172,12 @@ public class TaskTableReaderImpl(
*/
override fun record(now: Instant) {
val newHost = service.lookupHost(task)
- if (newHost != null && newHost.getUid() != _host?.getUid()) {
+ if (newHost != null && newHost.getName() != _host?.getName()) {
_host = newHost
host =
HostInfo(
- newHost.getUid().toString(),
newHost.getName(),
+ newHost.getClusterName(),
"x86",
newHost.getModel().coreCount,
newHost.getModel().cpuCapacity,
diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt
index 721119cd..a857f496 100644
--- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt
+++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/TopologyFactories.kt
@@ -37,76 +37,99 @@ import org.opendc.simulator.compute.models.MachineModel
import org.opendc.simulator.compute.models.MemoryUnit
import java.io.File
import java.io.InputStream
-import java.util.SplittableRandom
-import java.util.UUID
-import java.util.random.RandomGenerator
/**
* A [TopologyReader] that is used to read the cluster definition file.
*/
private val reader = TopologyReader()
+// Lists used to make sure all cluster, host, power source and battery have unique names
+private val clusterNames: ArrayList<String> = ArrayList()
+private val hostNames: ArrayList<String> = ArrayList()
+private val powerSourceNames: ArrayList<String> = ArrayList()
+private val batteryNames: ArrayList<String> = ArrayList()
+
+/**
+ * Create a unique name for the specified [name] that is not already in the [names] list.
+ *
+ * If [name] is already in [names], "-$i" is appended to the name until a unique name is found.
+ * In which "$i" is an increasing integer starting from 0.
+ */
+private fun createUniqueName(
+ name: String,
+ names: ArrayList<String>,
+): String {
+ if (name !in names) {
+ names.add(name)
+ return name
+ }
+
+ var i = 0
+ var newName = "$name-$i"
+ while (newName in names) {
+ newName = "$name-${++i}"
+ }
+
+ names.add(newName)
+ return newName
+}
+
/**
* Construct a topology from the specified [pathToFile].
*/
-public fun clusterTopology(
- pathToFile: String,
- random: RandomGenerator = SplittableRandom(0),
-): List<ClusterSpec> {
- return clusterTopology(File(pathToFile), random)
+public fun clusterTopology(pathToFile: String): List<ClusterSpec> {
+ return clusterTopology(File(pathToFile))
}
/**
* Construct a topology from the specified [file].
*/
-public fun clusterTopology(
- file: File,
- random: RandomGenerator = SplittableRandom(0),
-): List<ClusterSpec> {
+public fun clusterTopology(file: File): List<ClusterSpec> {
val topology = reader.read(file)
- return topology.toClusterSpec(random)
+ return topology.toClusterSpec()
}
/**
* Construct a topology from the specified [input].
*/
-public fun clusterTopology(
- input: InputStream,
- random: RandomGenerator = SplittableRandom(0),
-): List<ClusterSpec> {
+public fun clusterTopology(input: InputStream): List<ClusterSpec> {
val topology = reader.read(input)
- return topology.toClusterSpec(random)
+ return topology.toClusterSpec()
}
/**
* Helper method to convert a [TopologySpec] into a list of [HostSpec]s.
*/
-private fun TopologySpec.toClusterSpec(random: RandomGenerator): List<ClusterSpec> {
+private fun TopologySpec.toClusterSpec(): List<ClusterSpec> {
+ clusterNames.clear()
+ hostNames.clear()
+ powerSourceNames.clear()
+ batteryNames.clear()
+
return clusters.map { cluster ->
- cluster.toClusterSpec(random)
+ cluster.toClusterSpec()
}
}
/**
* Helper method to convert a [ClusterJSONSpec] into a list of [HostSpec]s.
*/
-private var clusterId = 0
+private fun ClusterJSONSpec.toClusterSpec(): ClusterSpec {
+ val clusterName = createUniqueName(this.name, clusterNames)
-private fun ClusterJSONSpec.toClusterSpec(random: RandomGenerator): ClusterSpec {
val hostSpecs =
hosts.flatMap { host ->
(
List(host.count) {
host.toHostSpec(
- clusterId,
- random,
+ clusterName,
)
}
)
}
val powerSourceSpec =
PowerSourceSpec(
- UUID(random.nextLong(), (clusterId).toLong()),
+ createUniqueName(this.powerSource.name, powerSourceNames),
totalPower = this.powerSource.totalPower,
carbonTracePath = this.powerSource.carbonTracePath,
)
@@ -115,7 +138,7 @@ private fun ClusterJSONSpec.toClusterSpec(random: RandomGenerator): ClusterSpec
if (this.battery != null) {
batterySpec =
BatterySpec(
- UUID(random.nextLong(), clusterId.toLong()),
+ createUniqueName(this.battery.name, batteryNames),
this.battery.capacity,
this.battery.chargingSpeed,
this.battery.batteryPolicy,
@@ -123,20 +146,15 @@ private fun ClusterJSONSpec.toClusterSpec(random: RandomGenerator): ClusterSpec
)
}
- clusterId++
- return ClusterSpec(this.name, hostSpecs, powerSourceSpec, batterySpec)
+ return ClusterSpec(clusterName, hostSpecs, powerSourceSpec, batterySpec)
}
/**
* Helper method to convert a [HostJSONSpec] into a [HostSpec]s.
*/
-private var hostId = 0
private var globalCoreId = 0
-private fun HostJSONSpec.toHostSpec(
- clusterId: Int,
- random: RandomGenerator,
-): HostSpec {
+private fun HostJSONSpec.toHostSpec(clusterName: String): HostSpec {
val units =
List(cpu.count) {
CpuModel(
@@ -156,22 +174,12 @@ private fun HostJSONSpec.toHostSpec(
val powerModel =
getPowerModel(powerModel.modelType, powerModel.power.toWatts(), powerModel.maxPower.toWatts(), powerModel.idlePower.toWatts())
- var hostName: String
- if (name == null) {
- hostName = "Host-$hostId"
- } else {
- hostName = name
- }
-
val hostSpec =
HostSpec(
- UUID(random.nextLong(), (hostId).toLong()),
- hostName,
- mapOf("cluster" to clusterId),
+ createUniqueName(this.name, hostNames),
+ clusterName,
machineModel,
powerModel,
)
- hostId++
-
return hostSpec
}
diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt
index fd849b01..79a23a9e 100644
--- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt
+++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/BatterySpec.kt
@@ -22,10 +22,8 @@
package org.opendc.compute.topology.specs
-import java.util.UUID
-
public data class BatterySpec(
- val uid: UUID,
+ val name: String,
val capacity: Double,
val chargingSpeed: Double,
val batteryPolicy: BatteryPolicyJSONSpec,
diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/HostSpec.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/HostSpec.kt
index 0d0dd24d..0c614658 100644
--- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/HostSpec.kt
+++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/HostSpec.kt
@@ -24,21 +24,17 @@ package org.opendc.compute.topology.specs
import org.opendc.simulator.compute.cpu.CpuPowerModel
import org.opendc.simulator.compute.models.MachineModel
-import java.util.UUID
/**
* Description of a physical host that will be simulated by OpenDC and host the virtual machines.
*
- * @param uid Unique identifier of the host.
* @param name The name of the host.
- * @param meta The metadata of the host.
* @param model The physical model of the machine.
* @param cpuPowerModel The [cpuPowerModel] that determines the power draw based on cpu utilization
*/
public data class HostSpec(
- val uid: UUID,
val name: String,
- val meta: Map<String, Any>,
+ val clusterName: String,
val model: MachineModel,
val cpuPowerModel: CpuPowerModel,
)
diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/PowerSourceSpec.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/PowerSourceSpec.kt
index 179e8f9e..9028965f 100644
--- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/PowerSourceSpec.kt
+++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/PowerSourceSpec.kt
@@ -22,11 +22,8 @@
package org.opendc.compute.topology.specs
-import java.util.UUID
-
// TODO: add name to class
public data class PowerSourceSpec(
- val uid: UUID,
val name: String = "unknown",
val meta: Map<String, Any> = emptyMap(),
val totalPower: Long = Long.MAX_VALUE,
diff --git a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt
index 3ccb4e59..0f7694c1 100644
--- a/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt
+++ b/opendc-compute/opendc-compute-topology/src/main/kotlin/org/opendc/compute/topology/specs/TopologySpecs.kt
@@ -66,7 +66,7 @@ public data class ClusterJSONSpec(
*/
@Serializable
public data class HostJSONSpec(
- val name: String? = null,
+ val name: String = "Host",
val cpu: CPUJSONSpec,
val memory: MemoryJSONSpec,
val powerModel: PowerModelSpec = PowerModelSpec.DFLT,
@@ -143,6 +143,7 @@ public data class PowerModelSpec(
*/
@Serializable
public data class PowerSourceJSONSpec(
+ val name: String = "PowerSource",
val vendor: String = "unknown",
val modelName: String = "unknown",
val arch: String = "unknown",
@@ -158,15 +159,17 @@ public data class PowerSourceJSONSpec(
}
/**
- * Definition of a power source used for JSON input.
+ * Definition of a battery used for JSON input.
*
- * @property vendor
- * @property modelName
- * @property arch
- * @property totalPower
+ * @property name The name of the battery
+ * @property capacity The capacity of the battery in kWh
+ * @property chargingSpeed The charging speed of the battery in J
+ * @property batteryPolicy The policy used to decide when the battery charges and discharges
+ * @property initialCharge The initial charge in the battery
*/
@Serializable
public data class BatteryJSONSpec(
+ val name: String = "Battery",
var capacity: Double,
val chargingSpeed: Double,
val batteryPolicy: BatteryPolicyJSONSpec,
diff --git a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt
index 56278bf2..7cbce23a 100644
--- a/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt
+++ b/opendc-experiments/opendc-experiments-base/src/main/kotlin/org/opendc/experiments/base/runner/ScenarioRunner.kt
@@ -98,7 +98,7 @@ public fun runScenario(
val startTimeLong = workload.minOf { it.submissionTime }.toEpochMilli()
val startTime = Duration.ofMillis(startTimeLong)
- val topology = clusterTopology(scenario.topologySpec.pathToFile, Random(seed))
+ val topology = clusterTopology(scenario.topologySpec.pathToFile)
provisioner.runSteps(
setupComputeService(
serviceDomain,
@@ -131,7 +131,6 @@ public fun runScenario(
* @param scenario The scenario being run.
* @param seed The seed of the current run
* @param startTime The start time of the simulation given by the workload trace.
- * @param carbonTrace The carbon trace used to determine carbon emissions.
*/
public fun addExportModel(
provisioner: Provisioner,
diff --git a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/BatteryTest.kt b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/BatteryTest.kt
index 3161a9a1..a85c84f3 100644
--- a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/BatteryTest.kt
+++ b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/BatteryTest.kt
@@ -271,6 +271,8 @@ class BatteryTest {
val topology = createTopology("batteries/experiment1.json")
val monitor = runTest(topology, workload, failureModelSpec = failureModelSpec)
+ println(monitor.hostEnergyUsages["H01"])
+
assertAll(
{ assertEquals((960 * 1000) + 5000, monitor.maxTimestamp) { "Total runtime incorrect" } },
{
diff --git a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt
index df45f374..408e1496 100644
--- a/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt
+++ b/opendc-experiments/opendc-experiments-base/src/test/kotlin/org/opendc/experiments/base/TestingUtils.kt
@@ -34,10 +34,10 @@ import org.opendc.compute.simulator.scheduler.filters.VCpuFilter
import org.opendc.compute.simulator.scheduler.weights.CoreRamWeigher
import org.opendc.compute.simulator.service.ComputeService
import org.opendc.compute.simulator.telemetry.ComputeMonitor
-import org.opendc.compute.simulator.telemetry.table.HostTableReader
-import org.opendc.compute.simulator.telemetry.table.PowerSourceTableReader
-import org.opendc.compute.simulator.telemetry.table.ServiceTableReader
-import org.opendc.compute.simulator.telemetry.table.TaskTableReader
+import org.opendc.compute.simulator.telemetry.table.host.HostTableReader
+import org.opendc.compute.simulator.telemetry.table.powerSource.PowerSourceTableReader
+import org.opendc.compute.simulator.telemetry.table.service.ServiceTableReader
+import org.opendc.compute.simulator.telemetry.table.task.TaskTableReader
import org.opendc.compute.topology.clusterTopology
import org.opendc.compute.topology.specs.ClusterSpec
import org.opendc.compute.workload.Task
@@ -182,7 +182,7 @@ class TestComputeMonitor : ComputeMonitor {
var hostEnergyUsages = mutableMapOf<String, ArrayList<Double>>()
override fun record(reader: HostTableReader) {
- val hostName: String = reader.host.name
+ val hostName: String = reader.hostInfo.name
if (!(hostName in hostCpuDemands)) {
hostIdleTimes[hostName] = ArrayList()
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/SimPowerSource.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/SimPowerSource.java
index 3bc5ba70..718bc22a 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/SimPowerSource.java
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/SimPowerSource.java
@@ -43,10 +43,13 @@ public final class SimPowerSource extends FlowNode implements FlowSupplier, Carb
private FlowEdge distributorEdge;
- private double capacity;
+ private final double capacity;
private CarbonModel carbonModel = null;
+ private final String name;
+ private final String clusterName;
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Basic Getters and Setters
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -96,16 +99,27 @@ public final class SimPowerSource extends FlowNode implements FlowSupplier, Carb
return this.capacity;
}
+ public String getName() {
+ return name;
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constructors
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- public SimPowerSource(FlowGraph graph, double max_capacity) {
+ public SimPowerSource(FlowGraph graph, double max_capacity, String name, String clusterName) {
super(graph);
this.capacity = max_capacity;
lastUpdate = this.clock.millis();
+
+ this.name = name;
+ this.clusterName = clusterName;
}
public void close() {
@@ -136,9 +150,9 @@ public final class SimPowerSource extends FlowNode implements FlowSupplier, Carb
long lastUpdate = this.lastUpdate;
this.lastUpdate = now;
- long duration = now - lastUpdate;
- if (duration > 0) {
- double energyUsage = (this.powerSupplied * duration * 0.001);
+ long passedTime = now - lastUpdate;
+ if (passedTime > 0) {
+ double energyUsage = (this.powerSupplied * passedTime * 0.001);
// Compute the energy usage of the machine
this.totalEnergyUsage += energyUsage;
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/BatteryState.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/BatteryState.java
index 0f010864..ae87902d 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/BatteryState.java
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/BatteryState.java
@@ -23,7 +23,7 @@
package org.opendc.simulator.compute.power.batteries;
public enum BatteryState {
- Charging,
- Idle,
- Discharging
+ CHARGING,
+ IDLE,
+ DISCHARGING
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java
index ad7e09e3..d229d4b5 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/SimBattery.java
@@ -32,22 +32,50 @@ import org.opendc.simulator.engine.graph.FlowSupplier;
public class SimBattery extends FlowNode implements FlowConsumer, FlowSupplier {
private final double capacity;
- private double chargingSpeed;
+ private final double chargingSpeed;
private FlowEdge distributorEdge;
private FlowEdge aggregatorEdge;
- private BatteryState batteryState = BatteryState.Idle;
+ private BatteryState batteryState = BatteryState.IDLE;
private double charge;
private long lastUpdate;
private double incomingSupply;
private double incomingDemand;
-
private double outgoingDemand;
private double outgoingSupply;
+ private final String name;
+ private final String clusterName;
+
+ public String getName() {
+ return name;
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
+ public double getTotalEnergyUsage() {
+ return totalEnergyUsage;
+ }
+
+ public void setTotalEnergyUsage(double totalEnergyUsage) {
+ this.totalEnergyUsage = totalEnergyUsage;
+ }
+
+ public double getOutgoingSupply() {
+ return outgoingSupply;
+ }
+
+ public void setOutgoingSupply(double outgoingSupply) {
+ this.outgoingSupply = outgoingSupply;
+ }
+
+ private double totalEnergyUsage = 0.0f;
+
public BatteryPolicy getBatteryPolicy() {
return batteryPolicy;
}
@@ -78,24 +106,31 @@ public class SimBattery extends FlowNode implements FlowConsumer, FlowSupplier {
public boolean isFull() {
return (this.charge >= this.capacity);
}
- ;
public boolean isEmpty() {
return (this.charge <= 0.0);
}
- ;
/**
* Construct a new {@link FlowNode} instance.
*
* @param parentGraph The {@link FlowGraph} this stage belongs to.
*/
- public SimBattery(FlowGraph parentGraph, double capacity, double chargingSpeed, double initialCharge) {
+ public SimBattery(
+ FlowGraph parentGraph,
+ double capacity,
+ double chargingSpeed,
+ double initialCharge,
+ String name,
+ String clusterName) {
+
super(parentGraph);
this.capacity = capacity;
this.chargingSpeed = chargingSpeed;
this.charge = initialCharge;
+ this.name = name;
+ this.clusterName = clusterName;
}
public void close() {
@@ -112,17 +147,15 @@ public class SimBattery extends FlowNode implements FlowConsumer, FlowSupplier {
@Override
public long onUpdate(long now) {
- long passedTime = now - lastUpdate;
- this.lastUpdate = now;
+ this.updateCounters(now);
- if (this.batteryState == BatteryState.Idle) {
+ if (this.batteryState == BatteryState.IDLE) {
return Long.MAX_VALUE;
}
- this.updateCharge(passedTime);
long remainingTime = 0L;
- if (this.batteryState == BatteryState.Charging) {
+ if (this.batteryState == BatteryState.CHARGING) {
if (this.isFull()) {
this.batteryPolicy.invalidate();
return Long.MAX_VALUE;
@@ -131,7 +164,7 @@ public class SimBattery extends FlowNode implements FlowConsumer, FlowSupplier {
remainingTime = this.calculateRemainingTime();
}
- if (this.batteryState == BatteryState.Discharging) {
+ if (this.batteryState == BatteryState.DISCHARGING) {
if (this.isEmpty()) {
this.batteryPolicy.invalidate();
return Long.MAX_VALUE;
@@ -149,54 +182,69 @@ public class SimBattery extends FlowNode implements FlowConsumer, FlowSupplier {
return nextUpdate;
}
- private long calculateRemainingTime() {
- if ((this.batteryState == BatteryState.Charging) && (this.incomingSupply > 0.0)) {
- double remainingCharge = this.capacity - this.charge;
- return (long) Math.ceil((remainingCharge / this.incomingSupply) * 1000);
- }
+ public void updateCounters(long now) {
+ long lastUpdate = this.lastUpdate;
+ this.lastUpdate = now;
- if ((this.batteryState == BatteryState.Discharging) && (this.outgoingSupply > 0.0)) {
- return (long) Math.ceil((this.charge / this.outgoingSupply) * 1000);
+ long passedTime = now - lastUpdate;
+
+ this.updateCharge(passedTime);
+ if (passedTime > 0) {
+ double energyUsage = (this.outgoingSupply * passedTime * 0.001);
+
+ this.totalEnergyUsage += energyUsage;
}
+ }
- return Long.MAX_VALUE;
+ public void updateCounters() {
+ updateCounters(clock.millis());
}
private void updateCharge(long passedTime) {
- if (this.batteryState == BatteryState.Charging) {
+ if (this.batteryState == BatteryState.CHARGING) {
this.charge += this.incomingSupply * (passedTime / 1000.0);
}
- if (this.batteryState == BatteryState.Discharging) {
+ if (this.batteryState == BatteryState.DISCHARGING) {
this.charge -= this.outgoingSupply * (passedTime / 1000.0);
}
}
+ private long calculateRemainingTime() {
+ if ((this.batteryState == BatteryState.CHARGING) && (this.incomingSupply > 0.0)) {
+ double remainingCharge = this.capacity - this.charge;
+ return (long) Math.ceil((remainingCharge / this.incomingSupply) * 1000);
+ }
+
+ if ((this.batteryState == BatteryState.DISCHARGING) && (this.outgoingSupply > 0.0)) {
+ return (long) Math.ceil((this.charge / this.outgoingSupply) * 1000);
+ }
+
+ return Long.MAX_VALUE;
+ }
+
public void setBatteryState(BatteryState newBatteryState) {
if (newBatteryState == this.batteryState) {
return;
}
long now = this.clock.millis();
- long passedTime = now - lastUpdate;
- updateCharge(passedTime);
-
- this.lastUpdate = now;
+ updateCounters(now);
this.batteryState = newBatteryState;
- if (this.batteryState == BatteryState.Idle) {
+ if (this.batteryState == BatteryState.IDLE) {
this.pushOutgoingDemand(this.distributorEdge, 0.0f);
this.pushOutgoingSupply(this.distributorEdge, 0.0f);
}
- if (this.batteryState == BatteryState.Charging) {
+ if (this.batteryState == BatteryState.CHARGING) {
this.pushOutgoingDemand(this.distributorEdge, this.chargingSpeed);
this.pushOutgoingSupply(this.aggregatorEdge, 0.0f);
}
- if (this.batteryState == BatteryState.Discharging) {
+ if (this.batteryState == BatteryState.DISCHARGING) {
this.pushOutgoingDemand(this.distributorEdge, 0.0f);
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java
index be2f49e0..5abbe861 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/BatteryPolicy.java
@@ -38,7 +38,7 @@ public abstract class BatteryPolicy extends FlowNode implements CarbonReceiver {
protected double carbonIntensity;
- protected BatteryState batteryState = BatteryState.Idle;
+ protected BatteryState batteryState = BatteryState.IDLE;
/**
* Construct a new {@link FlowNode} instance.
@@ -68,20 +68,20 @@ public abstract class BatteryPolicy extends FlowNode implements CarbonReceiver {
this.batteryState = newBatteryState;
- if (newBatteryState == BatteryState.Charging) {
- this.battery.setBatteryState(BatteryState.Charging);
+ if (newBatteryState == BatteryState.CHARGING) {
+ this.battery.setBatteryState(BatteryState.CHARGING);
this.aggregator.setPowerSourceType(PowerSourceType.PowerSource);
return;
}
- if (newBatteryState == BatteryState.Idle) {
- this.battery.setBatteryState(BatteryState.Idle);
+ if (newBatteryState == BatteryState.IDLE) {
+ this.battery.setBatteryState(BatteryState.IDLE);
this.aggregator.setPowerSourceType(PowerSourceType.PowerSource);
return;
}
- if (newBatteryState == BatteryState.Discharging) {
- this.battery.setBatteryState(BatteryState.Discharging);
+ if (newBatteryState == BatteryState.DISCHARGING) {
+ this.battery.setBatteryState(BatteryState.DISCHARGING);
this.aggregator.setPowerSourceType(PowerSourceType.Battery);
}
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java
deleted file mode 100644
index 18da75d0..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/DoubleThresholdBatteryPolicy.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2025 AtLarge Research
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package org.opendc.simulator.compute.power.batteries.policy;
-
-import org.opendc.simulator.compute.power.batteries.BatteryAggregator;
-import org.opendc.simulator.compute.power.batteries.BatteryState;
-import org.opendc.simulator.compute.power.batteries.SimBattery;
-import org.opendc.simulator.engine.graph.FlowGraph;
-
-public class DoubleThresholdBatteryPolicy extends BatteryPolicy {
-
- private final double carbonThreshold;
-
- /**
- *
- * @param parentGraph The {@link FlowGraph} this stage belongs to.
- * @param battery
- * @param aggregator
- * @param carbonThreshold
- */
- public DoubleThresholdBatteryPolicy(
- FlowGraph parentGraph, SimBattery battery, BatteryAggregator aggregator, double carbonThreshold) {
- super(parentGraph, battery, aggregator);
-
- this.carbonThreshold = carbonThreshold;
- }
-
- @Override
- public long onUpdate(long now) {
-
- if (this.carbonIntensity >= this.carbonThreshold & !this.battery.isEmpty()) {
- this.setBatteryState(BatteryState.Discharging);
- return Long.MAX_VALUE;
- }
-
- if (this.carbonIntensity < this.carbonThreshold & !this.battery.isFull()) {
- this.setBatteryState(BatteryState.Charging);
- return Long.MAX_VALUE;
- }
-
- this.setBatteryState(BatteryState.Idle);
- return Long.MAX_VALUE;
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java
index 4d71c096..e917a26f 100644
--- a/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java
+++ b/opendc-simulator/opendc-simulator-compute/src/main/java/org/opendc/simulator/compute/power/batteries/policy/SingleThresholdBatteryPolicy.java
@@ -33,9 +33,9 @@ public class SingleThresholdBatteryPolicy extends BatteryPolicy {
/**
*
* @param parentGraph The {@link FlowGraph} this stage belongs to.
- * @param battery
- * @param aggregator
- * @param carbonThreshold
+ * @param battery The {@link SimBattery} to control.
+ * @param aggregator The {@link BatteryAggregator} to use.
+ * @param carbonThreshold The carbon intensity threshold to trigger charging or discharging.
*/
public SingleThresholdBatteryPolicy(
FlowGraph parentGraph, SimBattery battery, BatteryAggregator aggregator, double carbonThreshold) {
@@ -48,16 +48,16 @@ public class SingleThresholdBatteryPolicy extends BatteryPolicy {
public long onUpdate(long now) {
if (this.carbonIntensity >= this.carbonThreshold & !this.battery.isEmpty()) {
- this.setBatteryState(BatteryState.Discharging);
+ this.setBatteryState(BatteryState.DISCHARGING);
return Long.MAX_VALUE;
}
if (this.carbonIntensity < this.carbonThreshold & !this.battery.isFull()) {
- this.setBatteryState(BatteryState.Charging);
+ this.setBatteryState(BatteryState.CHARGING);
return Long.MAX_VALUE;
}
- this.setBatteryState(BatteryState.Idle);
+ this.setBatteryState(BatteryState.IDLE);
return Long.MAX_VALUE;
}
}
diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
index 196d6a93..2f23d33b 100644
--- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
+++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
@@ -50,7 +50,6 @@ import java.time.Duration
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.Random
-import java.util.UUID
import java.util.concurrent.Executors
import java.util.concurrent.ForkJoinPool
import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory
@@ -228,7 +227,7 @@ public class OpenDCRunner(
*
* @param scenario The scenario to simulate.
* @param repeat The repeat number used to seed the simulation.
- * @param topology The topology to simulate.
+ * @param topologyHosts The topology to simulate.
*/
private inner class SimulationTask(
private val scenario: Scenario,
@@ -264,7 +263,6 @@ public class OpenDCRunner(
val powerSourceSpec =
PowerSourceSpec(
- UUID(0, 0),
totalPower = Long.MAX_VALUE,
)
val topology = listOf(ClusterSpec("cluster", topologyHosts, powerSourceSpec))
@@ -359,9 +357,8 @@ public class OpenDCRunner(
val spec =
HostSpec(
- UUID(random.nextLong(), random.nextLong()),
"node-$clusterId-$position",
- mapOf("cluster" to clusterId),
+ clusterId,
MachineModel(processors, memoryUnits[0]),
powerModel,
)
diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt
index 7e09e9e9..fbb33593 100644
--- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt
+++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt
@@ -23,10 +23,10 @@
package org.opendc.web.runner.internal
import org.opendc.compute.simulator.telemetry.ComputeMonitor
-import org.opendc.compute.simulator.telemetry.table.HostTableReader
-import org.opendc.compute.simulator.telemetry.table.ServiceData
-import org.opendc.compute.simulator.telemetry.table.ServiceTableReader
-import org.opendc.compute.simulator.telemetry.table.toServiceData
+import org.opendc.compute.simulator.telemetry.table.host.HostTableReader
+import org.opendc.compute.simulator.telemetry.table.service.ServiceData
+import org.opendc.compute.simulator.telemetry.table.service.ServiceTableReader
+import org.opendc.compute.simulator.telemetry.table.service.toServiceData
import kotlin.math.roundToLong
/**
@@ -47,7 +47,7 @@ internal class WebComputeMonitor : ComputeMonitor {
hostAggregateMetrics.totalFailureVmSlices + reader.guestsRunning * slices,
)
- hostMetrics.compute(reader.host.id) { _, prev ->
+ hostMetrics.compute(reader.hostInfo.name) { _, prev ->
HostMetrics(
reader.cpuUsage + (prev?.cpuUsage ?: 0.0),
reader.cpuDemand + (prev?.cpuDemand ?: 0.0),