diff options
Diffstat (limited to 'opendc-common/src/main/kotlin/org/opendc')
8 files changed, 320 insertions, 0 deletions
diff --git a/opendc-common/src/main/kotlin/org/opendc/common/annotations/Endpoint.kt b/opendc-common/src/main/kotlin/org/opendc/common/annotations/Endpoint.kt new file mode 100644 index 00000000..4ef08a71 --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/annotations/Endpoint.kt @@ -0,0 +1,6 @@ +package org.opendc.common.annotations + +@RequiresOptIn(message = "This is a registered API endpoint.") +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR) +public annotation class Endpoint(val method: String, val name : String)
\ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/api/AssetsController.kt b/opendc-common/src/main/kotlin/org/opendc/common/api/AssetsController.kt new file mode 100644 index 00000000..c6f34d19 --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/api/AssetsController.kt @@ -0,0 +1,72 @@ +package org.opendc.common.api + +import org.opendc.common.annotations.Endpoint +import io.javalin.http.Handler + +/** + * This class represents the `/assets` endpoint. + * + * @author Mateusz Kwiatkowski + * + * */ + + +//TODO: fix -> this is all wrong. +// Sending the experiment file is completely useless. +// You need to send tasks.parquet +public class AssetsController { + /** + * Returns a concatenated JSON string of all assets. + */ + @Endpoint("GET","/assets") + public fun getAssets() : Handler { + return Handler { ctx -> ctx.status(200) + println(ctx.body()) + } + } + + /** + * Returns an asset with `id` as a JSON string. + */ + @Endpoint("GET", "/assets/{id}") + public fun getAssetsId(): Handler { + return Handler { ctx -> ctx.status(200) } + } + + /** + * Saves the asset specified in the HTTP body. + * Returns the asset `id`. + */ + @Endpoint("POST", "/assets") + public fun postAsset() : Handler { + return Handler { ctx -> ctx.status(200) + println(ctx.body()) + } + } + + /** + * Modifies the specified asset. + * Deletes all results from experiments with this asset. + */ + @Endpoint("PUT", "/assets/{id}") + public fun putAssetId() : Handler { + return Handler { ctx -> ctx.status(200) } + } + + /** + * Deletes an asset with `id`. + * Deletes all results from experiments with this asset. + */ + @Endpoint("DELETE", "/assets/{id}") + public fun deleteAssetId() : Handler { + return Handler { ctx -> ctx.status(200) } + } + + /** + * Deletes all assets + */ + @Endpoint("DELETE", "/assets") + public fun deleteAsset() : Handler { + return Handler { ctx -> ctx.status(200) } + } +}
\ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/api/ResourceController.kt b/opendc-common/src/main/kotlin/org/opendc/common/api/ResourceController.kt new file mode 100644 index 00000000..cf1d3cac --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/api/ResourceController.kt @@ -0,0 +1,30 @@ +package org.opendc.common.api + +import org.opendc.common.annotations.Endpoint + +/** + * This class represents the `/resources` endpoint. + * + * @author Mateusz Kwiatkowski + * + * */ + +public class ResourceController { + + /** + * Returns all data analytics for all experiments. + */ + @Endpoint("GET", "/resources") + public fun getResources() { + return + } + + /** + * Returns data analytics for experiment with `id`. + * + * */ + @Endpoint("GET", "/resources") + public fun getResourcesId() { + return + } +}
\ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/HTTPClient.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/HTTPClient.kt new file mode 100644 index 00000000..fc5bc57b --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/HTTPClient.kt @@ -0,0 +1,46 @@ +package org.opendc.common.utils + +import java.io.File +import java.io.InputStreamReader +import java.net.URI +import java.net.http.* +import java.net.http.HttpResponse.BodyHandlers.ofString + +/** + * Singleton class representing the real datacenter client. + * The client is asynchronous and initiates the connection first. + * + * @author Mateusz Kwiatkowski + */ + +public class HTTPClient private constructor() { + public companion object { + private var instance: HTTPClient? = null + private var client = HttpClient.newBuilder().build() + + public fun getInstance(): HTTPClient? { + if (instance == null) { + instance = HTTPClient() + } + return instance + } + } + + // TODO: this class must send the experiment JSON file to the digital twin + public fun sendExperiment(experiment: File) { + val input = experiment.inputStream() + val charArray = CharArray(experiment.length().toInt()) + val isr = InputStreamReader(input) + + isr.read(charArray) + + val request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/assets")) + .header("Content-type", "application/json") + // TODO: this is obviously wrong, find an efficient way to send JSON over network + .POST(HttpRequest.BodyPublishers.ofString(String(charArray))) + .build() + val response = client?.send(request, ofString()) + check(response?.statusCode() == 200) + } +}
\ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/JavalinRunner.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/JavalinRunner.kt new file mode 100644 index 00000000..23baac27 --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/JavalinRunner.kt @@ -0,0 +1,33 @@ +package org.opendc.common.utils + +import io.javalin.Javalin +import org.opendc.common.annotations.Endpoint +import org.opendc.common.api.AssetsController + +/** + * Represents the digital twin monitoring server. + * For endpoint documentation see `AssetsController`. + * @author Mateusz Kwiatkowski + * @see <a href=https://javalin.io/documentation>https://javalin.io/documentation</a> + * @see org.opendc.common.api.AssetsController + */ + +@OptIn(Endpoint::class) +public class JavalinRunner { + private val assetsController : AssetsController = AssetsController() + + init { + val app = Javalin.create().start() + app.get("/assets", assetsController.getAssets()) + + app.get("/assets/{id}", assetsController.getAssetsId()) + + app.post("/assets", assetsController.postAsset()) + + app.put("/assets/{id}", assetsController.putAssetId()) + + app.delete("/assets/{id}", assetsController.deleteAssetId()) + + app.delete("/assets", assetsController.deleteAsset()) + } +}
\ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/Kafka.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/Kafka.kt new file mode 100644 index 00000000..81eb6752 --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/Kafka.kt @@ -0,0 +1,38 @@ +package org.opendc.common.utils + +import com.fasterxml.jackson.dataformat.toml.TomlMapper +import org.apache.kafka.clients.producer.KafkaProducer +import org.apache.kafka.clients.producer.ProducerRecord +import org.opendc.common.ProtobufMetrics +import java.util.* +/** + * Represents the Kafka interface. + * @constructor `topic` the Kafka topic + * @author Mateusz Kwiatkowski + * @see <a href=https://kafka.apache.org/23/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html> + * https://kafka.apache.org/23/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html</a> + * @see <a href=https://kafka.apache.org/23/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html> + * https://kafka.apache.org/23/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html</a> + */ + +@Suppress("DEPRECATION") +public class Kafka(private val topic: String) { + private var properties : Properties + + init { + check(!topic.contains("-")) + properties = TomlMapper().readerFor(Properties().javaClass) + .readValue(Kafka::class.java.getResource("/producer.toml")) + } + + public fun getSend() : (ProtobufMetrics.ProtoExport) -> Unit { + val producer = KafkaProducer<String, ProtobufMetrics.ProtoExport>(properties) + return fun (value : ProtobufMetrics.ProtoExport) { + try { + producer.send(ProducerRecord(this.topic, value)) + } catch (e: Exception) { + println("${e.message}") + } + } + } +}
\ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/PostgresqlDB.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/PostgresqlDB.kt new file mode 100644 index 00000000..35d03feb --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/PostgresqlDB.kt @@ -0,0 +1,52 @@ +package org.opendc.common.utils + +import com.fasterxml.jackson.dataformat.toml.TomlMapper +import java.sql.Connection +import java.sql.DriverManager +import java.sql.SQLException +import java.util.Properties +/** + * Represents the Postgresql database. + * On setup cleans the entire database. + * + * @author Mateusz Kwiatkowski + * + * @see <a href=https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/DriverManager.html> + * https://docs.oracle.com/en/java/javase/21/docs/api/java.sql/java/sql/DriverManager.html</a> + */ +@Suppress("DEPRECATION") +public class PostgresqlDB { + private var properties = Properties() + private var connection : Connection? = null + + init { + try { + properties = TomlMapper().readerFor(Properties().javaClass) + .readValue(PostgresqlDB::class.java.getResource("/database.toml")) + connection = DriverManager.getConnection( + properties.getProperty("address").asJdbc(properties.getProperty("database")), + properties.getProperty("user"), + properties.getProperty("password")) + clear() + } catch (e: SQLException) { + print("${e.message}") + } + } + public fun clear(){ + val DELETE_ALL_TABLES = """ + DROP SCHEMA public CASCADE; + CREATE SCHEMA public; + """.trimIndent() + try { + val st = connection?.createStatement() + st?.executeQuery(DELETE_ALL_TABLES) + } catch (e: SQLException){ + println("${e.message}") + } + } + + private fun String.asJdbc(database : String) : String { + return "jdbc:postgresql://$this/$database" + } + +}
\ No newline at end of file diff --git a/opendc-common/src/main/kotlin/org/opendc/common/utils/Redis.kt b/opendc-common/src/main/kotlin/org/opendc/common/utils/Redis.kt new file mode 100644 index 00000000..b659d40a --- /dev/null +++ b/opendc-common/src/main/kotlin/org/opendc/common/utils/Redis.kt @@ -0,0 +1,43 @@ +package org.opendc.common.utils + +import com.fasterxml.jackson.dataformat.toml.TomlMapper +import redis.clients.jedis.RedisClient +import redis.clients.jedis.StreamEntryID +import redis.clients.jedis.params.XReadParams +import java.util.Properties + +/** + * This class represents the Redis server instance. + * @author Mateusz Kwiatkowski + * @see <a href=https://redis.io/docs/latest/>https://redis.io/docs/latest/</a> + * + * @see <a href=https://redis.io/docs/latest/develop/data-types/streams/>https://redis.io/docs/latest/develop/data-types/streams/</a> + */ + +@Suppress("DEPRECATION") +public class Redis { + private var properties : Properties + + init { + properties = TomlMapper().readerFor(Properties().javaClass) + .readValue(Kafka::class.java.getResource("/producer.toml")) + } + + public fun run() { + val jedis : RedisClient = RedisClient.create("redis://localhost:6379") + + val res5 = jedis.xread( + XReadParams.xReadParams().block(300).count(100), + object : HashMap<String?, StreamEntryID?>() { + init { + put("${properties.getProperty("table")}", StreamEntryID()) + } + }) + + // in Redis you can subscribe to updates to a stream. + // you should base your application off this. + // you can listen for new items with XREAD + println(res5) + jedis.close() + } +}
\ No newline at end of file |
