diff options
| author | Dante Niewenhuis <d.niewenhuis@hotmail.com> | 2025-07-22 15:47:44 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-22 15:47:44 +0200 |
| commit | e22c97dcca7478d6941b78bdf7cd873bc0d23cdc (patch) | |
| tree | f1859c16f4c7973d8b16ed693caad4c749d42331 /opendc-trace/opendc-trace-tools | |
| parent | 0c0cf25616771cd40a9e401edcba4a5e5016f76e (diff) | |
Updated workload schema (#360)
Diffstat (limited to 'opendc-trace/opendc-trace-tools')
5 files changed, 0 insertions, 813 deletions
diff --git a/opendc-trace/opendc-trace-tools/build.gradle.kts b/opendc-trace/opendc-trace-tools/build.gradle.kts deleted file mode 100644 index 654d37f7..00000000 --- a/opendc-trace/opendc-trace-tools/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -description = "Tools for working with workload traces" - -// Build configuration -plugins { - `kotlin-conventions` - application -} - -application { - mainClass.set("org.opendc.trace.tools.TraceTools") -} - -dependencies { - implementation(projects.opendcTrace.opendcTraceApi) - implementation(projects.opendcTrace.opendcTraceCalcite) - implementation(libs.kotlin.logging) - implementation(libs.clikt) - implementation(libs.jline) - - runtimeOnly(libs.log4j.core) - runtimeOnly(libs.log4j.slf4j) -} diff --git a/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/ConvertCommand.kt b/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/ConvertCommand.kt deleted file mode 100644 index aa7b09d5..00000000 --- a/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/ConvertCommand.kt +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.trace.tools - -import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.groups.OptionGroup -import com.github.ajalt.clikt.parameters.groups.cooccurring -import com.github.ajalt.clikt.parameters.groups.defaultByName -import com.github.ajalt.clikt.parameters.groups.groupChoice -import com.github.ajalt.clikt.parameters.options.default -import com.github.ajalt.clikt.parameters.options.defaultLazy -import com.github.ajalt.clikt.parameters.options.option -import com.github.ajalt.clikt.parameters.options.required -import com.github.ajalt.clikt.parameters.types.double -import com.github.ajalt.clikt.parameters.types.file -import com.github.ajalt.clikt.parameters.types.long -import com.github.ajalt.clikt.parameters.types.restrictTo -import mu.KotlinLogging -import org.opendc.trace.TableWriter -import org.opendc.trace.Trace -import org.opendc.trace.conv.TABLE_RESOURCES -import org.opendc.trace.conv.TABLE_RESOURCE_STATES -import org.opendc.trace.conv.resourceCpuCapacity -import org.opendc.trace.conv.resourceCpuCount -import org.opendc.trace.conv.resourceDuration -import org.opendc.trace.conv.resourceID -import org.opendc.trace.conv.resourceMemCapacity -import org.opendc.trace.conv.resourceStateCpuUsage -import org.opendc.trace.conv.resourceStateCpuUsagePct -import org.opendc.trace.conv.resourceStateDuration -import org.opendc.trace.conv.resourceStateMemUsage -import org.opendc.trace.conv.resourceStateTimestamp -import org.opendc.trace.conv.resourceSubmissionTime -import java.io.File -import java.time.Duration -import java.time.Instant -import java.util.Random -import kotlin.math.abs -import kotlin.math.max -import kotlin.math.min - -/** - * A [CliktCommand] that can convert between workload trace formats. - */ -internal class ConvertCommand : CliktCommand(name = "convert", help = "Convert between workload trace formats") { - /** - * The logger instance for the converter. - */ - private val logger = KotlinLogging.logger {} - - /** - * The directory where the trace should be stored. - */ - private val output by option("-O", "--output", help = "path to store the trace") - .file(canBeFile = false, mustExist = false) - .defaultLazy { File("output") } - - /** - * The directory where the input trace is located. - */ - private val input by argument("input", help = "path to the input trace") - .file(canBeFile = false) - - /** - * The input format of the trace. - */ - private val inputFormat by option("-f", "--input-format", help = "format of input trace") - .required() - - /** - * The format of the output trace. - */ - private val outputFormat by option("--output-format", help = "format of output trace") - .default("opendc-vm") - - /** - * The sampling options. - */ - private val samplingOptions by SamplingOptions().cooccurring() - - /** - * The converter strategy to use. - */ - private val converter by option("-c", "--converter", help = "converter strategy to use").groupChoice( - "default" to DefaultTraceConverter(), - "azure" to AzureTraceConverter(), - ).defaultByName("default") - - override fun run() { - val metaParquet = File(output, "meta.parquet") - val traceParquet = File(output, "trace.parquet") - - if (metaParquet.exists()) { - metaParquet.delete() - } - if (traceParquet.exists()) { - traceParquet.delete() - } - - val inputTrace = Trace.open(input, format = inputFormat) - val outputTrace = Trace.create(output, format = outputFormat) - - logger.info { "Building resources table" } - - val metaWriter = outputTrace.getTable(TABLE_RESOURCES)!!.newWriter() - - val selectedVms = metaWriter.use { converter.convertResources(inputTrace, it, samplingOptions) } - - if (selectedVms.isEmpty()) { - logger.warn { "No VMs selected" } - return - } - - logger.info { "Wrote ${selectedVms.size} rows" } - logger.info { "Building resource states table" } - - val writer = outputTrace.getTable(TABLE_RESOURCE_STATES)!!.newWriter() - - val statesCount = writer.use { converter.convertResourceStates(inputTrace, it, selectedVms) } - logger.info { "Wrote $statesCount rows" } - } - - /** - * Options for sampling the workload trace. - */ - private class SamplingOptions : OptionGroup() { - /** - * The fraction of VMs to sample - */ - val fraction by option("--sampling-fraction", help = "fraction of the workload to sample") - .double() - .restrictTo(0.0001, 1.0) - .required() - - /** - * The seed for sampling the trace. - */ - val seed by option("--sampling-seed", help = "seed for sampling the workload") - .long() - .default(0) - } - - /** - * A trace conversion strategy. - */ - private sealed class TraceConverter(name: String) : OptionGroup(name) { - /** - * Convert the resources table for the trace. - * - * @param trace The trace to convert. - * @param writer The table writer for the target format. - * @param samplingOptions The sampling options to use. - * @return The map of resources that have been selected. - */ - abstract fun convertResources( - trace: Trace, - writer: TableWriter, - samplingOptions: SamplingOptions?, - ): Map<String, Resource> - - /** - * Convert the resource states table for the trace. - * - * @param trace The trace to convert. - * @param writer The table writer for the target format. - * @param selected The set of virtual machines that have been selected. - * @return The number of rows written. - */ - abstract fun convertResourceStates( - trace: Trace, - writer: TableWriter, - selected: Map<String, Resource>, - ): Int - - /** - * A resource in the resource table. - */ - data class Resource( - val id: String, - val startTime: Instant, - val stopTime: Instant, - val cpuCount: Int, - val cpuCapacity: Double, - val memCapacity: Double, - ) - } - - /** - * Default implementation of [TraceConverter]. - */ - private class DefaultTraceConverter : TraceConverter("default") { - /** - * The logger instance for the converter. - */ - private val logger = KotlinLogging.logger {} - - /** - * The interval at which the samples where taken. - */ - private val sampleInterval = Duration.ofMinutes(5) - - /** - * The difference in CPU usage for the algorithm to cascade samples. - */ - private val sampleCascadeDiff = 0.1 - - override fun convertResources( - trace: Trace, - writer: TableWriter, - samplingOptions: SamplingOptions?, - ): Map<String, Resource> { - val random = samplingOptions?.let { Random(it.seed) } - val samplingFraction = samplingOptions?.fraction ?: 1.0 - val reader = checkNotNull(trace.getTable(TABLE_RESOURCE_STATES)).newReader() - - var hasNextRow = reader.nextRow() - val selectedVms = mutableMapOf<String, Resource>() - - val idCol = reader.resolve(resourceID) - val timestampCol = reader.resolve(resourceStateTimestamp) - val cpuCountCol = reader.resolve(resourceCpuCount) - val cpuCapacityCol = reader.resolve(resourceCpuCapacity) - val memCapacityCol = reader.resolve(resourceMemCapacity) - val memUsageCol = reader.resolve(resourceStateMemUsage) - - while (hasNextRow) { - var id: String - var cpuCount = 0 - var cpuCapacity = 0.0 - var memCapacity = 0.0 - var memUsage = 0.0 - var startTime = Long.MAX_VALUE - var stopTime = Long.MIN_VALUE - - do { - id = reader.getString(idCol)!! - - val timestamp = reader.getInstant(timestampCol)!!.toEpochMilli() - startTime = min(startTime, timestamp) - stopTime = max(stopTime, timestamp) - - cpuCount = max(cpuCount, reader.getInt(cpuCountCol)) - cpuCapacity = max(cpuCapacity, reader.getDouble(cpuCapacityCol)) - memCapacity = max(memCapacity, reader.getDouble(memCapacityCol)) - if (memUsageCol > 0) { - memUsage = max(memUsage, reader.getDouble(memUsageCol)) - } - - hasNextRow = reader.nextRow() - } while (hasNextRow && id == reader.getString(resourceID)) - - // Sample only a fraction of the VMs - if (random != null && random.nextDouble() > samplingFraction) { - continue - } - - logger.info { "Selecting VM $id" } - - val startInstant = Instant.ofEpochMilli(startTime) - sampleInterval // Offset by sample interval - val stopInstant = Instant.ofEpochMilli(stopTime) - - selectedVms.computeIfAbsent(id) { - Resource(it, startInstant, stopInstant, cpuCount, cpuCapacity, max(memCapacity, memUsage)) - } - - writer.startRow() - writer.setString(resourceID, id) - writer.setInstant(resourceSubmissionTime, startInstant) - writer.setInstant(resourceDuration, stopInstant) - writer.setInt(resourceCpuCount, cpuCount) - writer.setDouble(resourceCpuCapacity, cpuCapacity) - writer.setDouble(resourceMemCapacity, max(memCapacity, memUsage)) - writer.endRow() - } - - return selectedVms - } - - override fun convertResourceStates( - trace: Trace, - writer: TableWriter, - selected: Map<String, Resource>, - ): Int { - val reader = checkNotNull(trace.getTable(TABLE_RESOURCE_STATES)).newReader() - val sampleInterval = sampleInterval.toMillis() - - val idCol = reader.resolve(resourceID) - val timestampCol = reader.resolve(resourceStateTimestamp) - val cpuCountCol = reader.resolve(resourceCpuCount) - val cpuUsageCol = reader.resolve(resourceStateCpuUsage) - - var hasNextRow = reader.nextRow() - var count = 0 - - while (hasNextRow) { - val id = reader.getString(idCol)!! - val resource = selected[id] - if (resource == null) { - hasNextRow = reader.nextRow() - continue - } - - val cpuCount = reader.getInt(cpuCountCol) - val cpuUsage = reader.getDouble(cpuUsageCol) - - val startTimestamp = reader.getInstant(timestampCol)!!.toEpochMilli() - var timestamp: Long = startTimestamp - var duration: Long = sampleInterval - - // Attempt to cascade further samples into one if they share the same CPU usage - while (reader.nextRow().also { hasNextRow = it }) { - val shouldCascade = - id == reader.getString(idCol) && - abs(cpuUsage - reader.getDouble(cpuUsageCol)) < sampleCascadeDiff && - cpuCount == reader.getInt(cpuCountCol) - - // Check whether the next sample can be cascaded with the current sample: - // (1) The VM identifier of both samples matches - // (2) The CPU usage is almost identical (lower than `SAMPLE_CASCADE_DIFF` - // (3) The CPU count of both samples is identical - if (!shouldCascade) { - break - } - - val nextTimestamp = reader.getInstant(timestampCol)!!.toEpochMilli() - - // Check whether the interval between both samples is not higher than `SAMPLE_INTERVAL` - if ((nextTimestamp - timestamp) > sampleInterval) { - break - } - - duration += nextTimestamp - timestamp - timestamp = nextTimestamp - } - - writer.startRow() - writer.setString(resourceID, id) - writer.setInstant(resourceStateTimestamp, Instant.ofEpochMilli(timestamp)) - writer.setDuration(resourceStateDuration, Duration.ofMillis(duration)) - writer.setInt(resourceCpuCount, cpuCount) - writer.setDouble(resourceStateCpuUsage, cpuUsage) - writer.endRow() - - count++ - } - - return count - } - } - - /** - * Implementation of [TraceConverter] for the Azure trace format. - */ - private class AzureTraceConverter : TraceConverter("default") { - /** - * The logger instance for the converter. - */ - private val logger = KotlinLogging.logger {} - - /** - * CPU capacity of the machines used by Azure. - */ - private val cpuCapacity = 2500.0 - - /** - * The interval at which the samples where taken. - */ - private val sampleInterval = Duration.ofMinutes(5) - - /** - * The difference in CPU usage for the algorithm to cascade samples. - */ - private val sampleCascadeDiff = 0.1 - - override fun convertResources( - trace: Trace, - writer: TableWriter, - samplingOptions: SamplingOptions?, - ): Map<String, Resource> { - val random = samplingOptions?.let { Random(it.seed) } - val samplingFraction = samplingOptions?.fraction ?: 1.0 - val reader = checkNotNull(trace.getTable(TABLE_RESOURCES)).newReader() - - val idCol = reader.resolve(resourceID) - val startTimeCol = reader.resolve(resourceSubmissionTime) - val stopTimeCol = reader.resolve(resourceDuration) - val cpuCountCol = reader.resolve(resourceCpuCount) - val memCapacityCol = reader.resolve(resourceMemCapacity) - - val selectedVms = mutableMapOf<String, Resource>() - - while (reader.nextRow()) { - // Sample only a fraction of the VMs - if (random != null && random.nextDouble() > samplingFraction) { - continue - } - - val id = reader.getString(idCol)!! - val startTime = reader.getInstant(startTimeCol)!!.toEpochMilli() - val stopTime = reader.getInstant(stopTimeCol)!!.toEpochMilli() - val cpuCount = reader.getInt(cpuCountCol) - val memCapacity = reader.getDouble(memCapacityCol) - - logger.info { "Selecting VM $id" } - - val startInstant = Instant.ofEpochMilli(startTime) - val stopInstant = Instant.ofEpochMilli(stopTime) - val cpuCapacity = cpuCount * cpuCapacity - - selectedVms.computeIfAbsent(id) { - Resource(it, startInstant, stopInstant, cpuCount, cpuCapacity, memCapacity) - } - - writer.startRow() - writer.setString(resourceID, id) - writer.setInstant(resourceSubmissionTime, startInstant) - writer.setInstant(resourceDuration, stopInstant) - writer.setInt(resourceCpuCount, cpuCount) - writer.setDouble(resourceCpuCapacity, cpuCapacity) - writer.setDouble(resourceMemCapacity, memCapacity) - writer.endRow() - } - - return selectedVms - } - - override fun convertResourceStates( - trace: Trace, - writer: TableWriter, - selected: Map<String, Resource>, - ): Int { - val reader = checkNotNull(trace.getTable(TABLE_RESOURCE_STATES)).newReader() - val states = HashMap<String, State>() - val sampleInterval = sampleInterval.toMillis() - - val idCol = reader.resolve(resourceID) - val timestampCol = reader.resolve(resourceStateTimestamp) - val cpuUsageCol = reader.resolve(resourceStateCpuUsagePct) - - var count = 0 - - while (reader.nextRow()) { - val id = reader.getString(idCol)!! - val resource = selected[id] ?: continue - - val cpuUsage = reader.getDouble(cpuUsageCol) * resource.cpuCapacity // MHz - val state = states.computeIfAbsent(id) { State(resource, cpuUsage, sampleInterval) } - val timestamp = reader.getInstant(timestampCol)!!.toEpochMilli() - val delta = (timestamp - state.time) - - // Check whether the next sample can be cascaded with the current sample: - // (1) The CPU usage is almost identical (lower than `SAMPLE_CASCADE_DIFF`) - // (2) The interval between both samples is not higher than `SAMPLE_INTERVAL` - if (abs(cpuUsage - state.cpuUsage) <= sampleCascadeDiff && delta <= sampleInterval) { - state.time = timestamp - state.duration += delta - continue - } - - state.write(writer) - // Reset the state fields - state.time = timestamp - state.duration = sampleInterval - // Count write - count++ - } - - for ((_, state) in states) { - state.write(writer) - count++ - } - - return count - } - - private class State( - @JvmField val resource: Resource, - @JvmField var cpuUsage: Double, - @JvmField var duration: Long, - ) { - @JvmField var time: Long = resource.startTime.toEpochMilli() - private var lastWrite: Long = Long.MIN_VALUE - - fun write(writer: TableWriter) { - // Check whether this timestamp was already written - if (lastWrite == time) { - return - } - lastWrite = time - - writer.startRow() - writer.setString(resourceID, resource.id) - writer.setInstant(resourceStateTimestamp, Instant.ofEpochMilli(time)) - writer.setDuration(resourceStateDuration, Duration.ofMillis(duration)) - writer.setDouble(resourceStateCpuUsage, cpuUsage) - writer.setInt(resourceCpuCount, resource.cpuCount) - writer.endRow() - } - } - } -} diff --git a/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/QueryCommand.kt b/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/QueryCommand.kt deleted file mode 100644 index 7b7a2a64..00000000 --- a/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/QueryCommand.kt +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2022 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.trace.tools - -import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.parameters.arguments.argument -import com.github.ajalt.clikt.parameters.options.option -import com.github.ajalt.clikt.parameters.options.required -import com.github.ajalt.clikt.parameters.types.file -import org.apache.calcite.jdbc.CalciteConnection -import org.jline.builtins.Styles -import org.jline.console.Printer -import org.jline.console.impl.DefaultPrinter -import org.jline.terminal.Terminal -import org.jline.terminal.TerminalBuilder -import org.jline.utils.AttributedStringBuilder -import org.opendc.trace.Trace -import org.opendc.trace.calcite.TraceSchema -import java.nio.charset.StandardCharsets -import java.sql.DriverManager -import java.sql.ResultSet -import java.sql.ResultSetMetaData -import java.util.Properties - -/** - * A [CliktCommand] that allows users to query workload traces using SQL. - */ -internal class QueryCommand : CliktCommand(name = "query", help = "Query workload traces") { - /** - * The trace to open. - */ - private val input by option("-i", "--input") - .file(mustExist = true) - .required() - - /** - * The input format of the trace. - */ - private val inputFormat by option("-f", "--format", help = "format of the trace") - .required() - - /** - * The query to execute. - */ - private val query by argument() - - /** - * Access to the terminal. - */ - private val terminal = - TerminalBuilder.builder() - .system(false) - .streams(System.`in`, System.out) - .encoding(StandardCharsets.UTF_8) - .build() - - /** - * Helper class to print results to console. - */ - private val printer = QueryPrinter(terminal) - - override fun run() { - val inputTrace = Trace.open(input, format = inputFormat) - val info = Properties().apply { this["lex"] = "JAVA" } - val connection = DriverManager.getConnection("jdbc:calcite:", info).unwrap(CalciteConnection::class.java) - connection.rootSchema.add("trace", TraceSchema(inputTrace)) - connection.schema = "trace" - - val stmt = connection.createStatement() - stmt.executeQuery(query) - - val start = System.currentTimeMillis() - val hasResults = stmt.execute(query) - - try { - if (hasResults) { - do { - stmt.resultSet.use { rs -> - val count: Int = printResults(rs) - val duration = (System.currentTimeMillis() - start) / 1000.0 - printer.println("$count rows selected (${"%.3f".format(duration)} seconds)") - } - } while (stmt.moreResults) - } else { - val count: Int = stmt.updateCount - val duration = (System.currentTimeMillis() - start) / 1000.0 - - printer.println("$count rows affected (${"%0.3f".format(duration)} seconds)") - } - } finally { - stmt.close() - connection.close() - } - } - - /** - * Helper function to print the results to console. - */ - private fun printResults(rs: ResultSet): Int { - var count = 0 - val meta: ResultSetMetaData = rs.metaData - - val options = - mapOf( - Printer.COLUMNS to List(meta.columnCount) { meta.getColumnName(it + 1) }, - Printer.BORDER to "|", - ) - val data = mutableListOf<Map<String, Any>>() - - while (rs.next()) { - val row = mutableMapOf<String, Any>() - for (i in 1..meta.columnCount) { - row[meta.getColumnName(i)] = rs.getObject(i) - } - data.add(row) - - count++ - } - - printer.println(options, data) - - return count - } - - /** - * Helper class to print the results of the query. - */ - private class QueryPrinter(private val terminal: Terminal) : DefaultPrinter(null) { - override fun terminal(): Terminal = terminal - - override fun highlightAndPrint( - options: MutableMap<String, Any>, - exception: Throwable, - ) { - if (options.getOrDefault("exception", "stack") == "stack") { - exception.printStackTrace() - } else { - val asb = AttributedStringBuilder() - asb.append(exception.message, Styles.prntStyle().resolve(".em")) - asb.toAttributedString().println(terminal()) - } - } - } -} diff --git a/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/TraceTools.kt b/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/TraceTools.kt deleted file mode 100644 index 8f3dc60d..00000000 --- a/opendc-trace/opendc-trace-tools/src/main/kotlin/org/opendc/trace/tools/TraceTools.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2022 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. - */ - -@file:JvmName("TraceTools") - -package org.opendc.trace.tools - -import com.github.ajalt.clikt.core.CliktCommand -import com.github.ajalt.clikt.core.subcommands - -/** - * A script for querying and manipulating workload traces supported by OpenDC. - */ -fun main(args: Array<String>): Unit = TraceToolsCli().main(args) - -/** - * The primary [CliktCommand] for the trace tools offered by OpenDC. - */ -class TraceToolsCli : CliktCommand(name = "trace-tools") { - init { - subcommands(QueryCommand()) - subcommands(ConvertCommand()) - } - - override fun run() {} -} diff --git a/opendc-trace/opendc-trace-tools/src/main/resources/log4j2.xml b/opendc-trace/opendc-trace-tools/src/main/resources/log4j2.xml deleted file mode 100644 index 32d81416..00000000 --- a/opendc-trace/opendc-trace-tools/src/main/resources/log4j2.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ 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. - --> - -<Configuration status="WARN"> - <Appenders> - <Console name="Console" target="SYSTEM_OUT"> - <PatternLayout pattern="%d{HH:mm:ss.SSS} [%highlight{%-5level}] %logger{36} - %msg%n" disableAnsi="false"/> - </Console> - </Appenders> - <Loggers> - <Logger name="org.opendc" level="info" additivity="false"> - <AppenderRef ref="Console"/> - </Logger> - <Root level="error"> - <AppenderRef ref="Console"/> - </Root> - </Loggers> -</Configuration> |
