├── .gitignore ├── LICENSE └── TestClient.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | 11 | # Packages # 12 | ############ 13 | # it's better to unpack these files and commit the raw source 14 | # git has its own built in compression methods 15 | *.7z 16 | *.dmg 17 | *.gz 18 | *.iso 19 | *.rar 20 | #*.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sqlite 27 | *.xml 28 | _windows/ 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | ehthumbs.db 34 | Icon 35 | Thumbs.db 36 | .tmtags 37 | .idea/ 38 | mydjangosite/.idea/ 39 | tags 40 | vendor.tags 41 | tmtagsHistory 42 | *.sublime-project 43 | *.sublime-workspace 44 | .bundle 45 | 46 | result/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Intelligent-distributed Cloud and Security Laboratory (ICNS Lab.) 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /TestClient.py: -------------------------------------------------------------------------------- 1 | # This file is part of Qualified Caching-as-a-Service. 2 | # BSD 3-Clause License 3 | # 4 | # Copyright (c) 2019, Intelligent-distributed Cloud and Security Laboratory (ICNS Lab.) 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright notice, this 11 | # list of conditions and the following disclaimer. 12 | # 13 | # * Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # * Neither the name of the copyright holder nor the names of its 18 | # contributors may be used to endorse or promote products derived from 19 | # this software without specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | # 32 | # title : TestClient.py 33 | # description : python SDCManager class 34 | # author : Yunkon(Alvin) Kim 35 | # date : 20190305 36 | # version : 0.1 37 | # python_version : 3.6 38 | # notes : This class is an implementation of a test client to consume data from Software-Defined Cache (SDC) 39 | # in the Python Programming Language. 40 | # ============================================================================== 41 | 42 | # import logging 43 | import csv 44 | import os 45 | import random 46 | import threading 47 | import time 48 | 49 | import paho.mqtt.client as mqtt 50 | from paho.mqtt import publish 51 | 52 | client_id = "Client_1" 53 | 54 | # MQTT_HOST_ON_EDGE = "192.168.0.58" 55 | # MQTT_PORT_ON_EDGE = 1883 56 | MQTT_HOST_ON_EDGE = "163.180.117.185" 57 | MQTT_PORT_ON_EDGE = 11883 58 | 59 | # ----------------------------------------Error calculation for PID controller---------------------------------------# 60 | TEST_TIME = 30 # sec 61 | 62 | is_finish = False 63 | is_running = False 64 | is_received = False 65 | 66 | condition = threading.Condition() 67 | 68 | cache_hits_list = [] 69 | 70 | cache_miss_delay = 0.03 71 | 72 | 73 | # -------------------------------------------------------MQTT--------------------------------------------------------# 74 | def on_local_connect(client, userdata, flags, rc): 75 | if rc == 0: 76 | print("Connected - Result code: " + str(rc)) 77 | client.subscribe("edge/client/" + client_id + "/data") 78 | client.subscribe("edge/client/" + client_id + "/start_caching") 79 | 80 | else: 81 | print("Bad connection returned code = ", rc) 82 | print("ERROR: Could not connect to MQTT") 83 | 84 | 85 | def on_local_message(client, userdata, msg): 86 | global is_running 87 | global condition 88 | global cache_hits_list 89 | global cache_miss_delay 90 | 91 | # print("Cart new message: " + msg.topic + " " + str(msg.payload)) 92 | message = msg.payload 93 | print("Arrived topic: %s" % msg.topic) 94 | # print("Arrived message: %s" % message) 95 | 96 | if msg.topic == "edge/client/" + client_id + "/data": 97 | with condition: 98 | # if message.decode("utf-8") == "False": 99 | # print("No data (Message: %s)" % message) 100 | # else: 101 | # print("Here") 102 | if message != "False".encode(): 103 | print("Data size: %s" % len(message)) 104 | cache_hits_list.append(1) 105 | cache_miss_delay = 0.03 106 | else: 107 | print("No data received(Message: %s)" % message) 108 | time.sleep(cache_miss_delay) 109 | cache_miss_delay += 0.03 110 | cache_hits_list.append(0) 111 | # print("Data size: %s" % message) 112 | condition.notify() 113 | # time.sleep(0.03) 114 | elif msg.topic == "edge/client/" + client_id + "/start_caching": 115 | scenario_no = int(message) 116 | # Starting threads 117 | print("Scenario number: % s" % scenario_no) 118 | if scenario_no == 1: 119 | # time.sleep(1) # cache preparation time,and then continuously request data on the following thread. 120 | test_thread.start() 121 | time.sleep(0.05) 122 | is_running = True 123 | else: 124 | print("Unknown - scenario number: %s" % scenario_no) 125 | 126 | else: 127 | print("Unknown - topic: " + msg.topic + ", message: " + message) 128 | 129 | 130 | def on_local_publish(client, userdata, mid): 131 | print("mid: " + str(mid)) 132 | 133 | 134 | def on_local_subscribe(client, userdata, mid, granted_qos): 135 | print("Subscribed: " + str(mid) + " " + str(granted_qos)) 136 | 137 | 138 | def on_local_log(client, userdata, level, string): 139 | print(string) 140 | 141 | 142 | # The below lines will be used to publish the topics 143 | # publish.single("elevator/starting_floor_number", "3", hostname=MQTT_HOST, port=MQTT_PORT) 144 | # publish.single("elevator/destination_floor_number", "2", hostname=MQTT_HOST, port=MQTT_PORT) 145 | # ------------------------------------------------------------------------------------------------------------------# 146 | 147 | 148 | def consume_data_scenario1(mqtt_obj): 149 | # A cloud service periodically consumes an equal amount of cached data. 150 | global condition 151 | 152 | start_time = time.time() 153 | read_size = (1 << 19) 154 | with condition: 155 | while True: 156 | # consume data 157 | # This section will be changed to apply the distributed messaging structure. 158 | # In other words, MQTT will be used. 159 | # print("Request data") 160 | mqtt_obj.publish("edge/client/" + client_id + "/data_req", read_size, qos=2) 161 | condition.wait() 162 | # print("Consuming data") 163 | running_time = time.time() - start_time 164 | if running_time > TEST_TIME: 165 | break 166 | time.sleep(0.03) 167 | 168 | 169 | def consume_data_scenario2(mqtt_obj): 170 | # A cloud service periodically consumes an equal amount of cached data. 171 | global condition 172 | 173 | start_time = time.time() 174 | with condition: 175 | while True: 176 | # consume data 177 | # This section will be changed to apply the distributed messaging structure. 178 | # In other words, MQTT will be used. 179 | # print("Request data") 180 | val = random.randint(1, 4) 181 | val2 = random.randint(17, 18) 182 | read_size = (val << val2) # 128KB ~ 1024KB(1MB) 183 | mqtt_obj.publish("edge/client/" + client_id + "/data_req", read_size, qos=2) 184 | condition.wait() 185 | # print("Consuming data") 186 | running_time = time.time() - start_time 187 | if running_time > TEST_TIME: 188 | break 189 | time.sleep(0.03) 190 | 191 | 192 | def consume_data_scenario3(mqtt_obj): 193 | # A cloud service periodically consumes an equal amount of cached data. 194 | global condition 195 | 196 | start_time = time.time() 197 | read_size = (1 << 19) 198 | with condition: 199 | while True: 200 | # consume data 201 | # This section will be changed to apply the distributed messaging structure. 202 | # In other words, MQTT will be used. 203 | # print("Request data") 204 | random_ms = random.randint(8, 80) / 1000.0 # about 120fps ~ 12fps 205 | mqtt_obj.publish("edge/client/" + client_id + "/data_req", read_size, qos=2) 206 | condition.wait() 207 | # print("Consuming data") 208 | running_time = time.time() - start_time 209 | if running_time > TEST_TIME: 210 | break 211 | time.sleep(random_ms) 212 | 213 | 214 | def consume_data_scenario4(mqtt_obj): 215 | # A cloud service periodically consumes an equal amount of cached data. 216 | global condition 217 | 218 | start_time = time.time() 219 | with condition: 220 | while True: 221 | # consume data 222 | # This section will be changed to apply the distributed messaging structure. 223 | # In other words, MQTT will be used. 224 | # print("Request data") 225 | val = random.randint(1, 4) 226 | val2 = random.randint(17, 18) 227 | read_size = (val << val2) # 128KB ~ 1024KB(1MB) 228 | random_ms = random.randint(8, 80) / 1000.0 # about 120fps ~ 12fps 229 | mqtt_obj.publish("edge/client/" + client_id + "/data_req", read_size, qos=2) 230 | condition.wait() 231 | # print("Consuming data") 232 | running_time = time.time() - start_time 233 | if running_time > TEST_TIME: 234 | break 235 | time.sleep(random_ms) 236 | 237 | 238 | if __name__ == '__main__': 239 | 240 | # MQTT connection 241 | message_local_client = mqtt.Client("Client") 242 | message_local_client.on_connect = on_local_connect 243 | message_local_client.on_message = on_local_message 244 | # message_local_client.on_publish = on_local_publish 245 | 246 | ################################################ 247 | # Scenario 1 248 | ################################################ 249 | loop_counter = 0 250 | loop_round = 9 251 | cache_hit_ratios = [] 252 | trimmed_cache_hit_ratios = [] 253 | 254 | scenario_number = 1 255 | 256 | while loop_counter < loop_round: 257 | 258 | message_local_client.connect(MQTT_HOST_ON_EDGE, MQTT_PORT_ON_EDGE, 60) 259 | message_local_client.loop_start() 260 | 261 | # message_local_client.publish("edge/client/" + client_id + "/data_req", 100) 262 | # publish.single("edge/client/" + client_id + "/data_req", 100, 263 | # hostname=MQTT_HOST_ON_EDGE, port=MQTT_PORT_ON_EDGE) 264 | 265 | # Creating threads 266 | test_thread = threading.Thread(target=consume_data_scenario1, args=[message_local_client]) 267 | 268 | while not is_running: 269 | time.sleep(0.005) 270 | 271 | # Wait until threads are completely executed 272 | test_thread.join() 273 | print("Test is done!") 274 | 275 | publish.single("edge/client/" + client_id + "/done_to_test", "done", hostname=MQTT_HOST_ON_EDGE, 276 | port=MQTT_PORT_ON_EDGE, qos=2) 277 | time.sleep(3) 278 | 279 | message_local_client.loop_stop() 280 | message_local_client.disconnect() 281 | 282 | trimmed_cache_hits_list = cache_hits_list[10:] 283 | 284 | cache_hit_ratio = float(cache_hits_list.count(1)) / len(cache_hits_list) * 100.0 285 | trimmed_cache_hit_ratio = float(trimmed_cache_hits_list.count(1)) / len(trimmed_cache_hits_list) * 100.0 286 | 287 | cache_hit_ratios.append(cache_hit_ratio) 288 | trimmed_cache_hit_ratios.append(trimmed_cache_hit_ratio) 289 | 290 | print("Cache hit ratio: %s" % cache_hit_ratio) 291 | print("Cache hit ratio(Trimmed): %s" % trimmed_cache_hit_ratio) 292 | 293 | # time_list = [i for i in range(1, len(trimmed_cache_hits_list)+1)] 294 | 295 | # time_sm = np.array(time_list) 296 | # time_smooth = np.linspace(time_sm.min(), time_sm.max(), 300) 297 | 298 | # feedback_smooth = spline(time_list, percentage_list, time_smooth) 299 | # Using make_interp_spline to create BSpline 300 | 301 | # Smooth graph 302 | # helper_x3 = make_interp_spline(time_list, percentage_feedback_list) 303 | # feedback_smooth = helper_x3(time_smooth) 304 | # 305 | # helper_x3 = make_interp_spline(time_list, percentage_output_list) 306 | # output_smooth = helper_x3(time_smooth) 307 | # 308 | # plt.plot(time_smooth, feedback_smooth, marker='o', markersize=3, linestyle='-') 309 | # plt.plot(time_smooth, output_smooth, marker='o', markersize=3, linestyle='-') 310 | # plt.plot(time_list, percentage_setpoint_list) 311 | 312 | # # Real value graph 313 | # plt.plot(time_list, trimmed_cache_hits_list, marker='o', markersize=3, linestyle='None') 314 | # 315 | # plt.xlim((1, len(trimmed_cache_hits_list)+1)) 316 | # # plt.ylim((min(percentage_list) - 0.5, max(percentage_list) + 0.5)) 317 | # # plt.ylim(0, 100) 318 | # plt.xlabel('Round no.') 319 | # plt.ylabel('Cache hit(Hit:1, Miss:0)') 320 | # plt.title('Cache hits') 321 | # 322 | # # plt.ylim((1 - 0.5, 1 + 0.5)) 323 | # 324 | # plt.grid(True) 325 | # plt.show() 326 | 327 | # start_time = time.time() 328 | # read_size = (2 << 19) 329 | # while True: 330 | # # consume data 331 | # # This section will be changed to apply the distributed messaging structure. 332 | # # In other words, MQTT will be used. 333 | # message_client.publish("core/edge/" + client_id + "/data_req", read_size) 334 | # # print("Consuming data") 335 | # running_time = time.time() - start_time 336 | # if running_time > TEST_TIME: 337 | # break 338 | # time.sleep(0.03) 339 | is_running = False 340 | loop_counter += 1 341 | 342 | print("A test is finished") 343 | file_name = str(scenario_number) + "-" + time.strftime("%Y%m%d%H%M%S") + ".csv" 344 | print(file_name) 345 | full_path = os.path.join(os.path.join(".", "result"), file_name) 346 | print(full_path) 347 | 348 | avg_cache_hit_ratio = sum(cache_hit_ratios) / len(cache_hit_ratios) 349 | avg_trimmed_cache_hit_ratio = sum(trimmed_cache_hit_ratios) / len(trimmed_cache_hit_ratios) 350 | 351 | with open(full_path, 'w', newline='') as csvfile: 352 | writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) 353 | # print running time 354 | writer.writerow([avg_cache_hit_ratio, avg_trimmed_cache_hit_ratio]) 355 | for idx in range(len(cache_hits_list)): 356 | writer.writerow([cache_hits_list[idx]]) 357 | 358 | csvfile.close() 359 | 360 | ################################################ 361 | # Scenario 2 362 | ################################################ 363 | loop_counter = 0 364 | loop_round = 9 365 | cache_hit_ratios = [] 366 | trimmed_cache_hit_ratios = [] 367 | 368 | scenario_number = 2 369 | 370 | while loop_counter < loop_round: 371 | 372 | message_local_client.connect(MQTT_HOST_ON_EDGE, MQTT_PORT_ON_EDGE, 60) 373 | message_local_client.loop_start() 374 | 375 | # message_local_client.publish("edge/client/" + client_id + "/data_req", 100) 376 | # publish.single("edge/client/" + client_id + "/data_req", 100, 377 | # hostname=MQTT_HOST_ON_EDGE, port=MQTT_PORT_ON_EDGE) 378 | 379 | # Creating threads 380 | test_thread = threading.Thread(target=consume_data_scenario2, args=[message_local_client]) 381 | 382 | while not is_running: 383 | time.sleep(0.005) 384 | 385 | # Wait until threads are completely executed 386 | test_thread.join() 387 | print("Test is done!") 388 | 389 | publish.single("edge/client/" + client_id + "/done_to_test", "done", hostname=MQTT_HOST_ON_EDGE, 390 | port=MQTT_PORT_ON_EDGE, qos=2) 391 | time.sleep(3) 392 | 393 | message_local_client.loop_stop() 394 | message_local_client.disconnect() 395 | 396 | trimmed_cache_hits_list = cache_hits_list[10:] 397 | 398 | cache_hit_ratio = float(cache_hits_list.count(1)) / len(cache_hits_list) * 100.0 399 | trimmed_cache_hit_ratio = float(trimmed_cache_hits_list.count(1)) / len(trimmed_cache_hits_list) * 100.0 400 | 401 | cache_hit_ratios.append(cache_hit_ratio) 402 | trimmed_cache_hit_ratios.append(trimmed_cache_hit_ratio) 403 | 404 | print("Cache hit ratio: %s" % cache_hit_ratio) 405 | print("Cache hit ratio(Trimmed): %s" % trimmed_cache_hit_ratio) 406 | 407 | is_running = False 408 | loop_counter += 1 409 | 410 | print("A test is finished") 411 | file_name = str(scenario_number) + "-" + time.strftime("%Y%m%d%H%M%S") + ".csv" 412 | print(file_name) 413 | full_path = os.path.join(os.path.join(".", "result"), file_name) 414 | print(full_path) 415 | 416 | avg_cache_hit_ratio = sum(cache_hit_ratios) / len(cache_hit_ratios) 417 | avg_trimmed_cache_hit_ratio = sum(trimmed_cache_hit_ratios) / len(trimmed_cache_hit_ratios) 418 | 419 | with open(full_path, 'w', newline='') as csvfile: 420 | writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) 421 | # print running time 422 | writer.writerow([avg_cache_hit_ratio, avg_trimmed_cache_hit_ratio]) 423 | for idx in range(len(cache_hits_list)): 424 | writer.writerow([cache_hits_list[idx]]) 425 | 426 | csvfile.close() 427 | 428 | ################################################ 429 | # Scenario 3 430 | ################################################ 431 | loop_counter = 0 432 | loop_round = 9 433 | cache_hit_ratios = [] 434 | trimmed_cache_hit_ratios = [] 435 | 436 | scenario_number = 3 437 | 438 | while loop_counter < loop_round: 439 | 440 | message_local_client.connect(MQTT_HOST_ON_EDGE, MQTT_PORT_ON_EDGE, 60) 441 | message_local_client.loop_start() 442 | 443 | # message_local_client.publish("edge/client/" + client_id + "/data_req", 100) 444 | # publish.single("edge/client/" + client_id + "/data_req", 100, 445 | # hostname=MQTT_HOST_ON_EDGE, port=MQTT_PORT_ON_EDGE) 446 | 447 | # Creating threads 448 | test_thread = threading.Thread(target=consume_data_scenario3, args=[message_local_client]) 449 | 450 | while not is_running: 451 | time.sleep(0.005) 452 | 453 | # Wait until threads are completely executed 454 | test_thread.join() 455 | print("Test is done!") 456 | 457 | publish.single("edge/client/" + client_id + "/done_to_test", "done", hostname=MQTT_HOST_ON_EDGE, 458 | port=MQTT_PORT_ON_EDGE, qos=2) 459 | time.sleep(3) 460 | 461 | message_local_client.loop_stop() 462 | message_local_client.disconnect() 463 | 464 | trimmed_cache_hits_list = cache_hits_list[10:] 465 | 466 | cache_hit_ratio = float(cache_hits_list.count(1)) / len(cache_hits_list) * 100.0 467 | trimmed_cache_hit_ratio = float(trimmed_cache_hits_list.count(1)) / len(trimmed_cache_hits_list) * 100.0 468 | 469 | cache_hit_ratios.append(cache_hit_ratio) 470 | trimmed_cache_hit_ratios.append(trimmed_cache_hit_ratio) 471 | 472 | print("Cache hit ratio: %s" % cache_hit_ratio) 473 | print("Cache hit ratio(Trimmed): %s" % trimmed_cache_hit_ratio) 474 | 475 | is_running = False 476 | loop_counter += 1 477 | 478 | print("A test is finished") 479 | file_name = str(scenario_number) + "-" + time.strftime("%Y%m%d%H%M%S") + ".csv" 480 | print(file_name) 481 | full_path = os.path.join(os.path.join(".", "result"), file_name) 482 | print(full_path) 483 | 484 | avg_cache_hit_ratio = sum(cache_hit_ratios) / len(cache_hit_ratios) 485 | avg_trimmed_cache_hit_ratio = sum(trimmed_cache_hit_ratios) / len(trimmed_cache_hit_ratios) 486 | 487 | with open(full_path, 'w', newline='') as csvfile: 488 | writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) 489 | # print running time 490 | writer.writerow([avg_cache_hit_ratio, avg_trimmed_cache_hit_ratio]) 491 | for idx in range(len(cache_hits_list)): 492 | writer.writerow([cache_hits_list[idx]]) 493 | 494 | csvfile.close() 495 | 496 | ################################################ 497 | # Scenario 4 498 | ################################################ 499 | loop_counter = 0 500 | loop_round = 9 501 | cache_hit_ratios = [] 502 | trimmed_cache_hit_ratios = [] 503 | 504 | scenario_number = 4 505 | 506 | while loop_counter < loop_round: 507 | 508 | message_local_client.connect(MQTT_HOST_ON_EDGE, MQTT_PORT_ON_EDGE, 60) 509 | message_local_client.loop_start() 510 | 511 | # message_local_client.publish("edge/client/" + client_id + "/data_req", 100) 512 | # publish.single("edge/client/" + client_id + "/data_req", 100, 513 | # hostname=MQTT_HOST_ON_EDGE, port=MQTT_PORT_ON_EDGE) 514 | 515 | # Creating threads 516 | test_thread = threading.Thread(target=consume_data_scenario4, args=[message_local_client]) 517 | 518 | while not is_running: 519 | time.sleep(0.005) 520 | 521 | # Wait until threads are completely executed 522 | test_thread.join() 523 | print("Test is done!") 524 | 525 | publish.single("edge/client/" + client_id + "/done_to_test", "done", hostname=MQTT_HOST_ON_EDGE, 526 | port=MQTT_PORT_ON_EDGE, qos=2) 527 | time.sleep(3) 528 | 529 | message_local_client.loop_stop() 530 | message_local_client.disconnect() 531 | 532 | trimmed_cache_hits_list = cache_hits_list[10:] 533 | 534 | cache_hit_ratio = float(cache_hits_list.count(1)) / len(cache_hits_list) * 100.0 535 | trimmed_cache_hit_ratio = float(trimmed_cache_hits_list.count(1)) / len(trimmed_cache_hits_list) * 100.0 536 | 537 | cache_hit_ratios.append(cache_hit_ratio) 538 | trimmed_cache_hit_ratios.append(trimmed_cache_hit_ratio) 539 | 540 | print("Cache hit ratio: %s" % cache_hit_ratio) 541 | print("Cache hit ratio(Trimmed): %s" % trimmed_cache_hit_ratio) 542 | 543 | is_running = False 544 | loop_counter += 1 545 | 546 | print("A test is finished") 547 | file_name = str(scenario_number) + "-" + time.strftime("%Y%m%d%H%M%S") + ".csv" 548 | print(file_name) 549 | full_path = os.path.join(os.path.join(".", "result"), file_name) 550 | print(full_path) 551 | 552 | avg_cache_hit_ratio = sum(cache_hit_ratios) / len(cache_hit_ratios) 553 | avg_trimmed_cache_hit_ratio = sum(trimmed_cache_hit_ratios) / len(trimmed_cache_hit_ratios) 554 | 555 | with open(full_path, 'w', newline='') as csvfile: 556 | writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) 557 | # print running time 558 | writer.writerow([avg_cache_hit_ratio, avg_trimmed_cache_hit_ratio]) 559 | for idx in range(len(cache_hits_list)): 560 | writer.writerow([cache_hits_list[idx]]) 561 | 562 | csvfile.close() 563 | --------------------------------------------------------------------------------