From 7b55c6d193f2b0b093a61d851810d9dd616b75a3 Mon Sep 17 00:00:00 2001
From: lorenz <stu203404@mail.uni-kiel.de>
Date: Sat, 6 Feb 2021 02:12:29 +0100
Subject: [PATCH] Applied Code Reviews for TopicManager and
 WorkloadGeneratorStateCleaner

---
 .../theodolite/execution/BenchmarkExecutor.kt |   4 +-
 .../kotlin/theodolite/k8s/TopicManager.kt     |  23 +-
 .../kotlin/theodolite/k8s/UC1Benchmark.kt     |   6 +-
 .../k8s/WorkloadGeneratorStateCleaner.kt      |  49 ++--
 .../resources/META-INF/resources/index.html   | 242 ------------------
 5 files changed, 53 insertions(+), 271 deletions(-)
 delete mode 100644 theodolite-quarkus/src/main/resources/META-INF/resources/index.html

diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
index 751e2d322..2cc54a25c 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt
@@ -25,7 +25,7 @@ abstract class BenchmarkExecutor(val benchmark: Benchmark, val results: Results,
      * @param res resources to be tested.
      * @return True, if the number of resources are suitable for the given load, false otherwise.
      */
-    abstract fun runExperiment(load: LoadDimension, res: Resource): Boolean;
+    abstract fun runExperiment(load: LoadDimension, res: Resource): Boolean
 
     /**
      * Wait while the benchmark is running and log the number of minutes executed every 1 minute.
@@ -37,4 +37,4 @@ abstract class BenchmarkExecutor(val benchmark: Benchmark, val results: Results,
             logger.info { "Executed: $i minutes" }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt
index 4f75298f3..fe1f4f89c 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/TopicManager.kt
@@ -8,6 +8,10 @@ import org.apache.kafka.clients.admin.NewTopic
 
 private val logger = KotlinLogging.logger {}
 
+/**
+ * Manages the topics related tasks
+ * @param bootstrapServers Ip of the kafka server
+ */
 class TopicManager(bootstrapServers: String) {
     private val props = hashMapOf<String, Any>(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG to bootstrapServers)
     lateinit var kafkaAdmin: AdminClient
@@ -16,10 +20,15 @@ class TopicManager(bootstrapServers: String) {
         try {
             kafkaAdmin = AdminClient.create(props)
         } catch (e: Exception) {
-            logger.error {e.toString()}
+            logger.error { e.toString() }
         }
     }
 
+    /**
+     * Creates topics.
+     * @param topics Map that holds a numPartition for each topic it should create
+     * @param replicationFactor
+     */
     fun createTopics(topics: Map<String, Int>, replicationFactor: Short) {
 
         val newTopics = mutableSetOf<NewTopic>()
@@ -28,7 +37,7 @@ class TopicManager(bootstrapServers: String) {
             newTopics.add(tops)
         }
         kafkaAdmin.createTopics(newTopics)
-        logger.info {"Topics created"}
+        logger.info { "Topics created" }
     }
 
     fun createTopics(topics: List<String>, numPartitions: Int, replicationFactor: Short) {
@@ -39,9 +48,13 @@ class TopicManager(bootstrapServers: String) {
             newTopics.add(tops)
         }
         kafkaAdmin.createTopics(newTopics)
-        logger.info {"Creation of $topics started"}
+        logger.info { "Creation of $topics started" }
     }
 
+    /**
+     * Deletes topics.
+     * @param topics
+     */
     fun deleteTopics(topics: List<String>) {
 
         val result = kafkaAdmin.deleteTopics(topics)
@@ -49,9 +62,9 @@ class TopicManager(bootstrapServers: String) {
         try {
             result.all().get()
         } catch (ex: Exception) {
-            logger.error {ex.toString()}
+            logger.error { ex.toString() }
         }
-        logger.info {"Topics deleted"}
+        logger.info { "Topics deleted" }
     }
 
     fun getTopics(): ListTopicsResult? {
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt
index 7e1347973..c8766c2fa 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/UC1Benchmark.kt
@@ -27,9 +27,9 @@ class UC1Benchmark(config: UC1BenchmarkConfig) : Benchmark(config) {
     private var wgDeployment: Deployment
     private var configMap: ConfigMap
 
-
     init {
-        this.workloadGeneratorStateCleaner = WorkloadGeneratorStateCleaner(this.config.zookeeperConnectionString)
+        this.workloadGeneratorStateCleaner =
+            WorkloadGeneratorStateCleaner(this.config.zookeeperConnectionString, path = "/workload-generation")
         this.topicManager = TopicManager(this.config.kafkaIPConnectionString)
         this.kubernetesClient = DefaultKubernetesClient().inNamespace("default")
         this.yamlLoader = YamlLoader(this.kubernetesClient)
@@ -83,7 +83,7 @@ class UC1Benchmark(config: UC1BenchmarkConfig) : Benchmark(config) {
 
 
         // TODO ("calculate number of required instances")
-        val requiredInstances: Int = 1
+        val requiredInstances = 1
         val environmentVariables: MutableMap<String, String> = mutableMapOf()
         //environmentVariables.put("KAFKA_BOOTSTRAP_SERVERS", this.config.kafkaIPConnectionString)
         //environmentVariables.put("ZK_HOST", this.config.zookeeperConnectionString.split(":")[0])
diff --git a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt
index 98c11167a..e1e2c5d3e 100644
--- a/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt
+++ b/theodolite-quarkus/src/main/kotlin/theodolite/k8s/WorkloadGeneratorStateCleaner.kt
@@ -5,58 +5,69 @@ import org.apache.zookeeper.KeeperException
 import org.apache.zookeeper.WatchedEvent
 import org.apache.zookeeper.Watcher
 import org.apache.zookeeper.ZooKeeper
+import java.time.Duration
 
 private val logger = KotlinLogging.logger {}
 
-
-class WorkloadGeneratorStateCleaner(ip: String) {
-    private val path = "/workload-generation"
-    private val sessionTimeout = 60
-    private val retryTime = 3000L
+/**
+ * Resets the workloadgenerator states in zookeper (and potetially watches for Zookeper events)
+ *
+ * @param ip of zookeeper
+ * @param path path of the zookeeper node
+ */
+class WorkloadGeneratorStateCleaner(ip: String, val path: String) {
+    private val timeout: Duration = Duration.ofMillis(500)
+    private val retryAfter: Duration = Duration.ofSeconds(5)
     lateinit var zookeeperClient: ZooKeeper
 
     init {
         try {
-            val watcher: Watcher = ZookeeperWatcher()  // defined below
-            zookeeperClient = ZooKeeper(ip, sessionTimeout, watcher)
+            val watcher: Watcher = ZookeeperWatcher() // defined below
+            zookeeperClient = ZooKeeper(ip, timeout.toMillis().toInt(), watcher)
         } catch (e: Exception) {
-            logger.error {e.toString()}
+            logger.error { e.toString() }
         }
     }
 
+    /**
+     * Deletes all Zookeeper nodes with the corresponding path.
+     */
     fun deleteAll() {
         var deleted = false
         while (!deleted) {
-
-            //
             try {
-                zookeeperClient.delete(path, -1)
+                zookeeperClient.delete(this.path, -1)
             } catch (ex: Exception) {
-                logger.error {ex.toString()}
+                logger.error { ex.toString() }
             }
 
             try {
-                val clients = zookeeperClient.getChildren(path, true)
+                // get list of all nodes of the given path
+                val clients = zookeeperClient.getChildren(this.path, true)
                 if (clients.isEmpty()) {
-                    break;
+                    deleted = true
+                    break
                 }
             } catch (ex: Exception) {
                 when (ex) {
+                    // indicates that there are no nodes to delete left
                     is KeeperException -> {
                         deleted = true
                     }
                     is InterruptedException -> {
-                        logger.error {ex.toString()}
+                        logger.error { ex.toString() }
                     }
                 }
             }
-            Thread.sleep(retryTime)
-            logger.info {"ZooKeeper reset was not successful. Retrying in 5s"}
+            Thread.sleep(retryAfter.toMillis())
+            logger.info { "ZooKeeper reset was not successful. Retrying in 5s" }
         }
-
-        logger.info {"ZooKeeper reset was successful"}
+        logger.info { "ZooKeeper reset was successful" }
     }
 
+    /**
+     * Currently empty, could be used to watch(and react) on certain zookeeper events
+     */
     private class ZookeeperWatcher : Watcher {
 
         override fun process(event: WatchedEvent) {}
diff --git a/theodolite-quarkus/src/main/resources/META-INF/resources/index.html b/theodolite-quarkus/src/main/resources/META-INF/resources/index.html
deleted file mode 100644
index 1a04c85cd..000000000
--- a/theodolite-quarkus/src/main/resources/META-INF/resources/index.html
+++ /dev/null
@@ -1,242 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>theodolite-quarkus - 1.0.0-SNAPSHOT</title>
-    <style>
-        h1, h2, h3, h4, h5, h6 {
-            margin-bottom: 0.5rem;
-            font-weight: 400;
-            line-height: 1.5;
-        }
-
-        h1 {
-            font-size: 2.5rem;
-        }
-
-        h2 {
-            font-size: 2rem
-        }
-
-        h3 {
-            font-size: 1.75rem
-        }
-
-        h4 {
-            font-size: 1.5rem
-        }
-
-        h5 {
-            font-size: 1.25rem
-        }
-
-        h6 {
-            font-size: 1rem
-        }
-
-        .lead {
-            font-weight: 300;
-            font-size: 2rem;
-        }
-
-        .banner {
-            font-size: 2.7rem;
-            margin: 0;
-            padding: 2rem 1rem;
-            background-color: #0d1c2c;
-            color: white;
-        }
-
-        body {
-            margin: 0;
-            font-family: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
-        }
-
-        code {
-            font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
-            font-size: 87.5%;
-            color: #e83e8c;
-            word-break: break-word;
-        }
-
-        .left-column {
-            padding: .75rem;
-            max-width: 75%;
-            min-width: 55%;
-        }
-
-        .right-column {
-            padding: .75rem;
-            max-width: 25%;
-        }
-
-        .container {
-            display: flex;
-            width: 100%;
-        }
-
-        li {
-            margin: 0.75rem;
-        }
-
-        .right-section {
-            margin-left: 1rem;
-            padding-left: 0.5rem;
-        }
-
-        .right-section h3 {
-            padding-top: 0;
-            font-weight: 200;
-        }
-
-        .right-section ul {
-            border-left: 0.3rem solid #71aeef;
-            list-style-type: none;
-            padding-left: 0;
-        }
-
-        .examples {
-            display: flex;
-            flex-wrap: wrap;
-            margin: 20px 0 20px -40px;
-        }
-
-        .example {
-            display: flex;
-            margin-left: 20px;
-            margin-bottom: 20px;
-            flex-direction: column;
-            width: 350px;
-            background-color: #205894;
-            color: white;
-        }
-
-        .example code {
-            color: lightgrey;
-        }
-
-        .example-header {
-            padding: 20px;
-            display: flex;
-            position: relative;
-        }
-
-        .example-header h4 {
-            margin: 0;
-            font-size: 1.4rem;
-            flex-grow: 1;
-            line-height: 1.5;
-        }
-
-        .example-description {
-            padding: 0 20px;
-            flex-grow: 1;
-        }
-
-        .example-paths {
-            display: flex;
-            flex-direction: column;
-        }
-
-        .example-paths a {
-            display: block;
-            background-color: transparent;
-            font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
-            color: white;
-            padding: 10px;
-            text-decoration: none;
-        }
-
-        .example-paths a:before {
-            content: '⇨';
-            font-weight: bold;
-            font-size: 1.5rem;
-            margin: 20px;
-        }
-
-        .example-paths a:hover {
-            background-color: #0d1c2c;
-        }
-
-        .guide-link {
-            background-color: #71aeef;
-            position: absolute;
-            color: white;
-            text-decoration: none;
-            top: 0;
-            right: 0;
-            padding: 7px;
-            font-weight: bold;
-        }
-
-        .guide-link:hover {
-            background-color: #0d1c2c;
-        }
-    </style>
-</head>
-<body>
-
-<div class="banner lead">
-    Your new Cloud-Native application is ready!
-</div>
-
-<div class="container">
-    <div class="left-column">
-        <p class="lead"> Congratulations, you have created a new Quarkus cloud application.</p>
-
-        <h2>Why do you see this?</h2>
-
-        <p>This page is served by Quarkus. The source is in
-            <code>src/main/resources/META-INF/resources/index.html</code>.</p>
-
-        <h2>What can I do from here?</h2>
-
-        <p>If not already done, run the application in <em>dev mode</em> using: <code>./gradlew quarkusDev</code>.
-        </p>
-        <ul>
-            <li>Play with your example code in <code>src/main/kotlin</code>:
-                <div class="examples">
-<div class="example">
-    <div class="example-header">
-        <h4>RESTEasy JAX-RS</h4>
-        <a href="https://quarkus.io/guides/rest-json" target="_blank" class="guide-link">Guide</a>
-    </div>
-    <div class="example-description">
-        <p>A Hello World RESTEasy resource</p>
-
-    </div>
-    <div class="example-paths">
-        <a href="/hello-resteasy" class="path-link" target="_blank">GET /hello-resteasy</a>
-    </div>
-</div>
-
-                </div>
-            </li>
-            <li>Your static assets are located in <code>src/main/resources/META-INF/resources</code>.</li>
-            <li>Configure your application in <code>src/main/resources/application.properties</code>.</li>
-        </ul>
-        <h2>Do you like Quarkus?</h2>
-        <p>Go give it a star on <a href="https://github.com/quarkusio/quarkus">GitHub</a>.</p>
-    </div>
-    <div class="right-column">
-        <div class="right-section">
-            <h3>Application</h3>
-            <ul>
-                <li>GroupId: theodolite</li>
-                <li>ArtifactId: theodolite-quarkus</li>
-                <li>Version: 1.0.0-SNAPSHOT</li>
-                <li>Quarkus Version: 1.10.3.Final</li>
-            </ul>
-        </div>
-        <div class="right-section">
-            <h3>Next steps</h3>
-            <ul>
-                <li><a href="https://quarkus.io/guides/gradle-tooling" target="_blank">Setup your IDE</a></li>
-                <li><a href="https://quarkus.io/guides/getting-started.html" target="_blank">Getting started</a></li>
-                <li><a href="https://quarkus.io" target="_blank">Quarkus Web Site</a></li>
-            </ul>
-        </div>
-    </div>
-</div>
-</body>
-</html>
\ No newline at end of file
-- 
GitLab