• No results found

Under arbetets gång har flertalet ändringar genomförts för arbetet. Den största ändrin-gen som ändrin-genomfördes var att försöka reducera aggregeringstiderna från pilotstudiens resultat genom att dela upp tabellerna i MySQL samt öka filstorleken i Apache Spark.

Detta gjordes i hopp om att kunna genomföra fler mätningar på större mängder data.

Denna ändring var dock ej lyckad då dessa ändringar skapade längre aggregeringstider samt diverse anomalier i både MySQL samt Apache Spark. Dessa anomalier bestod främst av låsningar och datorkrasher och innebar att föregående aggregeringskod fick återställas. Ytterligare ändringar som fick göras var ändringar gällande mängden data som aggregerades mot webbapplikationen i Apache Spark samt MySQL som fick minskas flertalet gånger då aggregeringarna av datan tog för lång tid på begränsad hårdvara.

Valet att minska antalet aggregeringar vid ökad aggregering av data är en aspekt av arbetet som troligtvis kan påverka arbetets resultat negativt då det finns en risk att en tillräcklig mängd datapunkter ej samlats in. Dock bör man kunna få en inblick av

prestandaskillnader för MySQL samt Apache Spark på begränsad hårdvara vid olika datamängder med ett mindre antal datapunkter då trenderna för MySQL samt Apache Spark var väldigt lika för de olika testfallen under mätningarnas gång. Trenderna var att MySQL har en mindre standardavvikelse vid aggregeringar av enkel grad och en signifikant ökning av standardavvikelse för sökningar av mer komplex grad. Apache Spark hade däremot en låg standardavvikelse för båda typer av aggregeringar, men presterade bättre vid mer komplexa aggregeringsfrågor. Detta kan tolkas som att Apache Spark har mer stabilitet i aggregeringstider än MySQL för JSONdata. En mer lämplig typ av mätning för utvärderingsmetoden för arbetet är troligtvis en tidsgräns för mätningarna istället för en iterationsgräns för antal mätningar då mätningarna speficikt tog väldigt lång tid vid de större datamängderna.

Ett problem i MySQL som var väldigt märkbart under experimentets gång och som även beskrivs i artikeln av Ongo och Kusuma (2018) är att relationsdatabaser blir mer långsamma ju större datamängd som lagras i dessa. Detta problem fanns uppkom även i Apache Spark vilket troligtvis beror på den begränsade hårdvaran som användes för arbetet.

Artefakten som togs fram i arbetet löser troligtvis inga verklighetsbaserade problem inom området energiförbrukningsdata från smarta elmätare då aggregeringstiderna för både MySQL samt Apache Spark ökade signifikant när datamängden som aggregerades blev större på begränsad hårdvara. Trots att den typ av data som genererades troligtvis faller definitionen av de 3V’en av Kaisler et al. (2013) då varje dataobjekt i JSON genererades med ett hypotetiskt insamlingsintervall på 30 minuter kan datamängden för testfallen i arbetet kritiseras då dessa datamängder som användes i arbetet normalt sett inte faller inom kategorin Big Data enligt Kaisler et al. (2013). Dock kan mätningarna för arbetet trots avsaknaden av mängder data som klassas som Big Data visa på begränsningarna för aggregering av stora datamängder i JSONformat på begränsad hårdvara då resultaten visade på långa aggregeringstider överlag när sökningarna gjordes på JSONdatan.

8.3 Etik och samhälle

De etiska aspekterna som berör detta arbete är inledningsvis möjligheten att kunna replikera arbetet eller använda delar av arbetet för kommande personer som har någon typ av intresse av det. Därför finns all kod tillgänglig i ett kodförvar på GitHub (2020) som är tillgängligt för alla. All kod finns även tillgänglig som flertalet ap-pendix i detta examensarbete. Arbetet omfattas även av en tre-klausuls-BSD licens.

Denna licens gör det möjligt för andra parter att använda samt sprida detta examen-sarbete i vinstdrivande samt privat syfte med eller utan modifikationer vilket kan ses öka samhällsnyttan för arbetet då en hög grad av frihet ges vidare för kommande arbeten.

Ytterligare aspekter av samhällsnytta som detta arbete kan fylla är att det kan vara användbart för människor att använda detta arbete för att undvika att göra ag-gregeringar på JSONdata i både MySQL samt Apache Spark vid miljontals JSONobjekt då aggregeringstiderna överlag var långa i experimentet.

8.4 Framtida arbete

JSON-data för att aggregera energiförbrukningsdata. Något som skulle vara intressant är att göra en slags normalisering av JSON-datan i MySQL och möjligen i Apache Spark för att undersöka hur det påverkar aggregeringstiden. Vid en potentiell ökning genom bättre datastrukturer för lagring av JSON-data kan troligen datamängden vid olika testfall ökas ytterligare. Det vore även intressant att använda detta arbete som inspiration eller grund för att implementera ett mindre kluster av datorer för att se hur det påverkar aggregeringstiderna för sökning av JSON-data.

Ur ett långsiktigt perspektiv för framtida arbeten kan arbetet vara relevant för nya versioner av den mjukvaran än den som använts för detta arbete som specificeras i Fig. 22. Kanske kan detta arbete implementeras för nyare versioner för mjukvaror och visa på bättre resultat vid aggregeringsfrågor mot lagrad JSONdata i antingen MySQL eller Apache Spark.

Referenslista

Anderson, D. och Hills, M. (2017), Query construction patterns in php, in ‘2017 IEEE 24th International Conference on Software Analysis, Evolution and Reengineering (SANER)’, IEEE, ss. 452–456.

Auer, S., Dietzold, S., Lehmann, J., Hellmann, S. och Aumueller, D. (2009), Triplify:

light-weight linked data publication from relational databases, in ‘Proceedings of the 18th international conference on World wide web’, ss. 621–630.

Bourhis, P., Reutter, J. L., Suárez, F. och Vrgoč, D. (2017), Json: data model, query languages and schema specification, in ‘Proceedings of the 36th ACM SIGMOD-SIGACT-SIGAI symposium on principles of database systems’, ss. 123–135.

Chambers, B. och Zahari, M. (2018), Spark: the definitive guide, OReilly.

Chasseur, C., Li, Y. och Patel, J. M. (2013), Enabling json document stores in relational systems., in ‘WebDB’, Vol. 13, ss. 14–15.

Chen, M., Mao, S. och Liu, Y. (2014), ‘Big data: A survey’, Mobile networks and appli-cations 19(2), 171–209.

Condie, T., Conway, N., Alvaro, P., Hellerstein, J. M., Elmeleegy, K. och Sears, R. (2010), Mapreduce online., Vol. 10, s. 20.

Curren, J. C. (2010), ‘Php speed vs other languages’.

https://stackoverflow.com/questions/2359718/php-speed-vs-other-languages Dahse, J. och Holz, T. (2014), Simulation of built-in php features for precise static code

analysis., Vol. 14, Citeseer, ss. 23–26.

Dean, J. och Ghemawat, S. (2008), ‘Mapreduce: simplified data processing on large clus-ters’, Communications of the ACM 51(1), 107–113.

Faraon, M. (2011), Webbutveckling med PHP och MySQL, Studentlitteratur.

Fuad, A., Erwin, A. och Ipung, H. P. (2014), Processing performance on apache pig, apache hive and mysql cluster, in ‘Proceedings of International Conference on Information, Communication Technology and System (ICTS) 2014’, IEEE, ss. 297–302.

GitHub (2020), ‘a17robda/examensarbete’.

https://github.com/a17robda/Examensarbete

Groff, J. R. och Weinberg, P. N. (2002), SQL: the complete reference, McGraw-Hill/Osborne.

Hardin, D. S. (2001), Real-time objects on the bare metal: an efficient hardware realization of the java/sup tm/virtual machine, in ‘Fourth IEEE International Symposium on Object-Oriented Real-Time Distributed Computing. ISORC 2001’, IEEE, ss. 53–59.

Hellerstein, J. M., Haas, P. J. och Wang, H. J. (1997), Online aggregation, in ‘Proceedings of the 1997 ACM SIGMOD international conference on Management of data’, ss. 171–

Honarvar, A. R. och Sami, A. (2016), ‘Extracting usage patterns from power usage data of homes’ appliances in smart home using big data platform’, International Journal of Information Technology and Web Engineering (IJITWE) 11(2), 39–50.

Jamison, D. C. (2003), ‘Structured query language (sql) fundamentals’, Current protocols in bioinformatics (1), 9–2.

JavaScript Object Notation (2020-03-20).

https://www.php.net/manual/en/book.json.php

Jazayeri, M. (2007), Some trends in web application development, in ‘Future of Software Engineering (FOSE’07)’, IEEE, ss. 199–213.

Kaisler, S., Armour, F., Espinosa, J. A. och Money, W. (2013), Big data: Issues and challenges moving forward, in ‘2013 46th Hawaii International Conference on System Sciences’, IEEE, ss. 995–1004.

Kaur, K. och Rani, R. (2013), Modeling and querying data in nosql databases, in ‘2013 IEEE International Conference on Big Data’, IEEE, ss. 1–7.

Loghin, D., Tudor, B. M., Zhang, H., Ooi, B. C. och Teo, Y. M. (2015), ‘A performance study of big data on small nodes’, Proceedings of the VLDB Endowment 8(7), 762–

773.

Lu, X., Rahman, M. W. U., Islam, N., Shankar, D. och Panda, D. K. (2014), Accelerating spark with rdma for big data processing: Early experiences, in ‘2014 IEEE 22nd Annual Symposium on High-Performance Interconnects’, IEEE, ss. 9–16. Piscataway, New Jersey, US.

Meng, X., Bradley, J., Yavuz, B., Sparks, E., Venkataraman, S., Liu, D., Freeman, J., Tsai, D., Amde, M., Owen, S. et al. (2016), ‘Mllib: Machine learning in apache spark’, The Journal of Machine Learning Research 17(1), 1235–1241.

Moher, T. och Schneider, G. M. (1981), Methods for improving controlled experimenta-tion in software engineering, in ‘Proceedings of the 5th internaexperimenta-tional conference on Software engineering’, IEEE Press, ss. 224–233.

Odersky, M., Altherr, P., Cremet, V., Emir, B., Maneth, S., Micheloud, S., Mihaylov, N., Schinz, M., Stenman, E. och Zenger, M. (2004), An overview of the scala program-ming language, Technical report.

Ongo, G. och Kusuma, G. P. (2018), Hybrid database system of mysql and mongodb in web application development, in ‘2018 International Conference on Information Management and Technology (ICIMTech)’, IEEE, ss. 256–260.

Pargas, R. P., Harrold, M. J. och Peck, R. R. (1999), ‘Test-data generation using genetic algorithms’, Software testing, verification and reliability 9(4), 263–282.

Pérez-Chacón, R., Luna-Romera, J. M., Troncoso, A., Martínez-Álvarez, F. och Riquelme, J. C. (2018), ‘Big data analytics for discovering electricity consumption patterns in smart cities’, Energies 11(3), 683.

Sagiroglu, S. och Sinanc, D. (2013), Big data: A review, in ‘2013 International Conference on Collaboration Technologies and Systems (CTS)’, IEEE, ss. 42–47. Piscataway, New Jersey, US.

Spark Overview (2020-04-10).

https://spark.apache.org/docs/2.4.5/

Taivalsaari, A., Mikkonen, T., Ingalls, D. och Palacz, K. (2008), Web browser as an application platform, in ‘2008 34th Euromicro Conference Software Engineering and Advanced Applications’, IEEE, ss. 293–302.

Wohlin, C., Runeson, P., Höst, M., Ohlsson, M. C. och Regnell, Björn, W. A. (2012), Experimentation in software engineering, Springer Science & Business Media.

Yang, C., Song, Y., Qian, J., Zhao, H., Jiang, W., Tang, H. och Wu, J. (2017), Apache spark based urban load data analysis and forecasting technology research, in ‘2017 IEEE Conference on Energy Internet and Energy System Integration (EI2)’, IEEE, ss. 1–6.

Zwitter, A. (2014), ‘Big data ethics’, Big Data & Society 1(2), 2053951714559253.

Öppna data och PSI (2020-02-21).

https://www.oppnadata.se/

Appendix A - Generate.php

echo "WELCOME TO SETUP! \n";

echo "Create a new preferences file? [y/n]\n";

$s = readline();

if(yesNo($s)) {

echo "Folder name: \n";

$folder = readline();

if(!file_exists($folder)) { mkdir($folder);

}$separator = checkOS();

echo "File name \n";

$fileName = readline();

$f = fopen("preferences.json", "w");

$jsonArr = array('folderName' => $folder, 'separator' =>

$separator, 'fileName' => $fileName);

echo "No preferences are set, aborting!";

exit();

return false;

echo "It seems like there is no preference file present. Please set up one. \n";

echo "File size goal(Mb): \n";

$inp = readline();

$inp = str_replace(' ', '', $inp);

try {

$inp = (int)$inp;

} catch(Exception $e) { echo $e."\n";

}

if(is_int($inp) && $inp !=0) { echo $inp."Is valid\n";

confirmGenerate($inp);

echo "Integer cannot be 0\n";

echo "This will generate a file of ".$inp." Megabytes. Continue?

[y/n]\n";

,→

echo "Continue?: ", $s = readline();

if (yesNo($s)) {

$pretty;

echo "Would you like to pretty-print?\n", $s = readline();

if(yesNo($s)) {

$pretty = true; } else {

$pretty = false;

}

echo "\nGenerating data\n", generate($inp * 1000, $pretty);

} else if(!yesNo($s)) {

echo "\nAborting...\n", hello();

} }

// Return preferences created from setup function function returnPreferences() {

$preferences = file_get_contents("preferences.json");

$decoded = json_decode($preferences, true);

return $decoded;

}

// IMPLEMENT FILE SPLITTING AND CREATION

function createFile(&$folderName, &$separator, &$fileName, &$fileSplit) {

// Checks the operating system structure function checkOS() {

// Check OS

if (DIRECTORY_SEPARATOR === '/') { // Running under Linux

return "/";

} else if (DIRECTORY_SEPARATOR === '\\') { // Running under Windows

return "\\";

} }

// Generate a pseudorandom array

function randArray(&$keycode, &$year, &$day, &$month, &$hour, &$minute) {

,→

// Timestamp

if((int)$year > 2020) {

$year = 1977;

if((int)$minute > 59) {

$minute = 0;

$hour++;

}

$rndValue = rand(3704, 112292);

// Fixes apparant bug with rand();

if($rndValue > 112292) {

$rndValue = 112292;

}

$randArr = array('tkeycode' => $keycode, 'tstamp' =>

gmdate('c',mktime($hour,$minute,0,$month,$day,$year)), 'tunit'

=> 'kwh', 'tvalue' => $rndValue);

,→

// Generate arrays and split files accordingly function generate($kbGoal, $pretty) {

// File size

$kbCount = 0;

$splitMbLimit = 10;

// File name as String

$fullFileName =

$dateNOW = date('Y-m-d h:i:sa', $timeNOW);

$separator;

$f = createFile($folderName, $separator, $fileName, $fileSplit);

while(reachedGoal($kbCount, $targetKb) == false) {

$theArray = randArray($keycode, $year, $day, $month, $hour,

$minute);

,→

$iter = $iter + 1;

$tmpStr = "Number: ".$iter." Kb: ".round($kbCount)." File size:

".filesize($folderName.$separator.$fileName."_"

,→

.$fileSplit.".json")."\n";

echo $tmpStr;

kbSize($theArray, $kbCount, $kbTemp);

fwrite($f, json_encode($theArray));

if(reachedGoal($kbCount, $targetKb) == false && (round($kbTemp)

% ($mbSplit * 1000) != 0) || round($kbTemp) == 0) {

if(round($kbTemp) % ($mbSplit * 1000) == 0 && round($kbTemp) !=

0) {

,→

$kbTemp = 0;

echo "Splitting file!\n";

fwrite($f, "\n]");

fclose($f);

$fileSplit++;

$f = createFile($folderName, $separator, $fileName,

$fileSplit);

,→

}

}finalize($f, $timeNOW, $dateNOW, $keycode);

}

// Bytes to kilobytes count

function kbSize(&$inp, &$kbCount, &$kbTemp) { foreach ($inp as $k => $v) {

$kbCount += strlen($k) * 0.001;

$kbCount += strlen($v) * 0.001;

$kbTemp += strlen($k) * 0.001;

$kbTemp += strlen($v) * 0.001;

} }

// The kilobyte goal from megabytes function kbGoal($mb) {

return $mb * 1000;

}

// Check if we have reached the total file goal function reachedGoal($kbCount, $targetKb) {

$timeDONE = time();

$dateDONE = date('Y-m-d h:i:sa', $timeDONE);

echo "Generation started: ".$dateNOW."\n";

echo "Generation complete: ".$dateDONE."\n";

$secondsElapsed = $timeDONE - $timeNOW;

$minutesElapsed = round($secondsElapsed / 60, 1);

echo "Seconds elapsed: ".$secondsElapsed." seconds.\n";

echo "Minutes elapsed: ".$minutesElapsed." minutes.\n";

fwrite($f, "\n]");

fclose($f);

mkdir(returnPreferences()['folderName']."/max");

$maxIdFile =

fopen(returnPreferences()['folderName']."/max/maxId.txt", "w+");

,→

fwrite($maxIdFile, $maxId -1);

fclose($maxIdFile);

clearstatcache();

}

Appendix B - Router.php

<?php

// Simple routing for application returns class Router

{

protected $routes = [

"" => "controllers/index.controller.php",

"query" => "controllers/query.controller.php"

];

public function route($uri) { switch($uri) {

case "":

return $this->routes[""];

break;

case "query":

return $this->routes["query"];

break;

default:

return "controllers/404.controller.php";

break;

} } }

?>

Appendix C - index.php

<?php

require "Router.php";

$uri = $_SERVER["REQUEST_URI"];

$uri = trim($uri, "/");

$router = new Router();

require $router->route($uri);

Appendix D - query.view.php

$qstr = query("mysql", $iter, $complexity, $dbSize);

try {

} catch (PDOException $e) { echo $e;

} break;

foreach (glob("/home/robin/Documents/Examensarbete/

// Randomizes a date for the complex MySQL queries function randomizeDate($maxrand) {

// Builds the queries accordingly

function query($platform, &$iter, $complexity, $dbSize) { if($platform == "mysql") {

$maxval =

file_get_contents("/home/robin/Documents/Examensarbete/

,→

generate_datasets/outputJSON{$dbSize}/max/maxId.txt");

srand($iter);

$maxrand = rand(0, $maxval);

switch($complexity) { case "simple":

return 'SELECT * FROM jsontable_1 where jsonrow->>"$.tkeycode" = '.$maxrand;

MAX(CAST(jsonrow->>"$.tvalue" AS UNSIGNED)) AS maximum, MIN(CAST(jsonrow->>"$.tvalue" AS UNSIGNED)) AS minimum, STD(CAST(jsonrow->>"$.tvalue" AS UNSIGNED)) AS std_dev,

VARIANCE(CAST(jsonrow->>"$.tvalue" AS UNSIGNED)) AS variance FROM jsontable_1 where jsonrow->>"$.tstamp" BETWEEN

"1976-12-31%" AND '.'"'.randomizeDate($maxrand).'%"';

,→

,→

break; } }

if ($platform == "spark") { switch($complexity) {

// Render table and data accordingly

function render($data, $platform, $complexity) {

$table = "<table id='outTable'>";

foreach($data as $arr) {

<td>{$arr['maximum']}</td>

<td>{$arr['minimum']}</td>

<td>{$arr['average']}</td>

<td>{$arr['sum_energy']}</td>

<td>{$arr['std_dev']}</td>

<td>{$arr['variance']}</td>

</tr>

";

}

foreach($arr as $k => $v) {

$js = json_decode($v, true);

if($complexity != "complex") {

$table.= "

<tr>

<td>{$js['tkeycode']}</td>

<td>{$js['tstamp']}</td>

<td>{$js['tunit']}</td>

<td>{$js['tvalue']}</td>

</tr>

";

} } } }

if($platform == "spark") { while(!feof($data)) {

$result = fgets($data);

$js = json_decode($result, true);

if($complexity == "complex") {

$table.= "

<tr>

<td>{$js['maximum']}</td>

<td>{$js['minimum']}</td>

<td>{$js['average']}</td>

<td>{$js['sum_energy']}</td>

<td>{$js['std_dev']}</td>

<td>{$js['variance']}</td>

</tr>";

}

if($complexity != "complex") {

$table.=

"<tr>

<td>{$js['tkeycode']}</td>

<td>{$js['tstamp']}</td>

<td>{$js['tunit']}</td>

<td>{$js['tvalue']}</td>

</tr>

";

} }

fclose($data);

}$table.="</table>";

echo $table;

}

?>

Appendix E - index.view.php

<input type="radio" id="mysql" name="aggregation" value="mysql">

<label for="mysql">MySQL</label><br>

<input type="radio" id="spark" name="aggregation" value="spark">

<label for="spark">Apache Spark</label><br>

<label>Data size:</label><br>

<input type="radio" id="one" name="dataSize" value="one">

<label for="one">~1.4 GB</label><br>

<input type="radio" id="five" name="dataSize" value="five">

<label for="ten">~6.7 GB</label><br>

<input type="radio" id="thirteen" name="dataSize" value="thirteen">

<label for="fifty">~13.5 GB</label><br>

<input id="submit" type="submit">

</form>

';}

?>

Appendix F - 404.view.php

<?php

echo "<h2>404</h2>";

echo "Page not found!";

Appendix G - main.php

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<link rel="stylesheet" href="css/style.css">

</head>

<body>

<?php

require $contentBlock;

?>

</body>

</html>

Appendix H - style.css

* {

margin: 0;

padding: 0;

} body {

background-color: rgb(70, 70, 70);

}

#aggForm, h1, #outTable { width: 50%;

margin: 0 auto; text-align: center; }

th {

font-size: 1.5em;

}

label, h1, th, td { color: white; }

Appendix I - query.controller.php

<?php

$contentBlock = "views/query.view.php";

require "templates/main.php";

Appendix J - index.controller.php

<?php

$contentBlock = "views/index.view.php";

require "templates/main.php";

Appendix K - 404.controller.php

<?php

$contentBlock = "views/404.view.php";

require "templates/main.php";

Appendix L - SparkApp.scala

// Import SparkSession

import org.apache.spark.sql.SparkSession

object SparkApp {

def main(args: Array[String]) {

val spark = SparkSession.builder.appName("Spark Application").getOrCreate()

,→

// Args

var testType : String = args(0) var iter : Int = args(1).toInt var dbSize : String = args(2);

// Import primitive datatypes

outputJSON" + dbSize + "/max/maxId.txt"

for (line <- Source.fromFile(filename).getLines) { maxId = line.toInt

}

// Create a query string

val queryString = queryBuilder(testType, maxId, iter) // Load JSON-file in a Data Frame

val jsonPath =

def queryBuilder(choice:String, maxId:Int, iter:Int) : String = { val maxRand = randomize(maxId, iter)

println("Max rand: " + maxRand) choice match {

case "0" =>

return "SELECT * FROM values WHERE tkeycode = " + maxRand

,→

case "1" =>

return "SELECT MAX(tvalue) AS maximum, MIN(tvalue) AS minimum, AVG(tvalue) AS average, SUM(tvalue) AS sum_energy, STD(tvalue) AS std_dev, VARIANCE(tvalue) AS variance FROM values WHERE tstamp BETWEEN

'1976-12-31%' AND " + "'" +

// Randomize a timestamp according to seed def randomizeTimestamp(seed:Int) : String = {

val rand = new scala.util.Random(seed)

var year : Int = rand.nextInt(2020 - 1977) + 1977 var month : Int = rand.nextInt((12 - 1) + 1) var day : Int = rand.nextInt((31 - 1) + 1) // String representation

var stringYear : String = year.toString var stringMonth : String = month.toString var stringDay : String = day.toString if(month < 10) {

stringMonth = "0" + stringMonth }if(day < 10) {

stringDay = "0" + stringDay }

return stringYear + "-" + stringMonth + "-" + stringDay }

def randomize(maxId:Int, iter:Int) : Int = {

// Creates a new random and seeds it according to iteration val rand = new scala.util.Random(iter)

val randInt = rand.nextInt(maxId) return randInt

} }

Appendix M - build.sbt

name := "SparkApp"

version := "1.0"

scalaVersion := "2.11.12"

libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.4.5"

Appendix N - launch.sh

#!/bin/bash

/usr/local/spark-2.4.5-bin-hadoop2.7/bin/spark-submit \ --class "SparkApp" \

--master spark://robin:7077 \

~/Documents/Examensarbete/spark/target/scala-2.11/sparkapp_2.11-1.0.jar

$1 $2 $3

,→

Appendix O - jsonMysql.php

$files = array_diff($files, array('.', '..', 'max'));

// Database-credentials

$dateNOW = date('Y-m-d h:i:sa', $timeNOW);

$conn = new PDO("mysql:host=$server;dbname=$database", $user,

$password);

,→

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

echo "Connected!";

$createDbSql = "CREATE TABLE {$tableName}( id int AUTO_INCREMENT,

// Iterate through all files in folder foreach($files as $f) {

$qmarks = "";

$valArr = array();

$js = file_get_contents($folderPath."/".$f);

$decoded = json_decode($js, true);

// Last array in file

$lastArr = end($decoded);

$insert.= '{"'.$k.'"'.':'.$v.",";

if($arr["tkeycode"] != $lastArr["tkeycode"]) {

$qmarks.= "(?),";

} else {

$qmarks.= "(?)";

}$insert = "";

}$sql = "INSERT INTO {$tableName} (jsonrow) VALUES {$qmarks}";

$stmt = $conn->prepare($sql);

$dateDONE = date('Y-m-d h:i:sa', $timeDONE);

echo "Insertion started: ".$dateNOW."\n";

echo "Insertion complete: ".$dateDONE."\n";

$secondsElapsed = $timeDONE - $timeNOW;

$minutesElapsed = round($secondsElapsed / 60, 1);

echo "Seconds elapsed: ".$secondsElapsed." seconds.\n";

echo "Minutes elapsed: ".$minutesElapsed." minutes.\n";

Appendix P - postRequest.js

window.onload = function() { addListeners();

}csv = localStorage.getItem("csv");

if(type == "mysql") {

mysqlSelect.checked = true; }

if(type == "spark") {

sparkSelect.checked = true; }

document.getElementById(dbSize).checked = true; console.log(timeNOW);

if(iter <= maxIter) {

console.log("Iterations: " + iter);

iter++;

saveVars();

post();

} else {

console.log("Completed!" + maxIter + " iterations!");

}

if(key == "r") { reset();

}); } }

// Menu functions function download() {

console.log("Downloading!");

var an = window.document.createElement('a');

an.setAttribute('href', 'data:text/csv; charset=utf-8,' + encodeURIComponent(csv));

,→

an.setAttribute('download', 'data.csv');

window.document.body.appendChild(an);

an.click();

}

function reset() {

console.log("Resetting!");

localStorage.clear();

location.reload();

}

Appendix Q - writeTime.js

// ==UserScript==

// @name writeTime // @version 1

// @grant none

// @include http://localhost:8888/query // ==/UserScript==

var timeTOTAL;

var timeNOW;

var data;

var csv;

window.onload = function() { saveTime();

redir();

}

function saveTime() {

csv = localStorage.getItem("csv");

timeNOW = localStorage.getItem("timeNOW");

timeTOTAL = Date.now() - timeNOW;

console.log("Time elapsed: " + timeTOTAL);

csv+= timeTOTAL+",";

localStorage.setItem("csv", csv);

}

function redir() {

window.location.href = "http://localhost:8888/";

}

Related documents