/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. */ /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.thingml.loadbalancer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import org.thingml.testjar.Command; import org.thingml.testjar.TestHelper; import org.thingml.testjar.lang.TargetedLanguage; import org.thingml.testjar.lang.lArduino; import org.thingml.testjar.lang.lJava; import org.thingml.testjar.lang.lJavaScript; import org.thingml.testjar.lang.lPosix; import org.thingml.testjar.lang.lPosixMT; import org.thingml.testjar.lang.lSintefboard; /** * * @author sintef */ public class LoadBalancer { public static void main(String[] args) throws ExecutionException { //call this by //java -cp .:target/testJar-0.7.0-SNAPSHOT-jar-with-dependencies.jar org.thingml.loadbalancer.LoadBalancer //java -cp .:target/testJar-0.7.0-SNAPSHOT-jar-with-dependencies.jar org.thingml.loadbalancer.LoadBalancer compilers.jar //java -cp .:target/testJar-0.7.0-SNAPSHOT-jar-with-dependencies.jar org.thingml.loadbalancer.LoadBalancer config.properties loadBalancer.properties <load_balance_dest_dir> <job_postfix> <test_case_folder> final File workingDir = new File(System.getProperty("user.dir")); File tmpDir = new File(workingDir, "tmp"); final File testCfgDir = new File(tmpDir, "thingml"); final File codeDir = new File(tmpDir, "genCode"); final File logDir = new File(tmpDir, "log"); File ressourcesDir = new File(workingDir.getPath() + "/src/main/resources"); File compilerJar; System.out.println(args.length); if(args.length == 1) { compilerJar = new File(workingDir, args[0]); } else { compilerJar = new File(workingDir, "../compilers/registry/target/compilers.registry-0.7.0-SNAPSHOT-jar-with-dependencies.jar"); } File testJar = new File(workingDir, "target/testJar-0.7.0-SNAPSHOT-jar-with-dependencies.jar"); tmpDir.delete(); tmpDir = new File(workingDir, "tmp"); tmpDir.mkdir(); String testPattern = "test(.+)\\.thingml"; Set<Command> tasks = new HashSet<>(); List<Future<String>> results = new ArrayList<Future<String>>(); System.out.println("****************************************"); System.out.println("* Properties Reading *"); System.out.println("****************************************"); System.out.println(""); Properties prop = new Properties(); InputStream input = null; InputStream lbInput = null; String languageList = null, useBlackList = null, categoryUseBlackList = null, categoryList = null, testList = null; try { File testFolder; String destTestRootDir = null; String testDirPostfix = null; if(args.length == 5) { input = new FileInputStream(new File(args[0])); lbInput = new FileInputStream(new File(args[1])); destTestRootDir = args[2]; testDirPostfix = args[3]; testFolder = new File(args[4]); }else { input = new FileInputStream(new File(workingDir, "config.properties")); lbInput = new FileInputStream(new File(workingDir, "loadBalancer.properties")); testFolder = new File(workingDir.getPath() + "/src/main/resources/tests"); } System.out.println("****************************************"); System.out.println("* Load Balancing Begins *"); System.out.println("****************************************"); System.out.println(""); System.out.println("Working Directory = " + System.getProperty("user.dir")); System.out.println("Tmp Directory = " + tmpDir); System.out.println("Compiler = " + compilerJar); System.out.println(""); // load a properties file prop.load(input); // get the property value and print it out languageList = prop.getProperty("languageList"); useBlackList = prop.getProperty("useBlackList"); categoryUseBlackList = prop.getProperty("categoryUseBlackList"); categoryList = prop.getProperty("categoryList"); testList = prop.getProperty("testList"); System.out.println("languageList:" + languageList); System.out.println("useBlackList:" + useBlackList); System.out.println("testList:" + testList); Properties loadBalancerProp = new Properties(); String nodeList = null; int totalWeight = 0; // load a properties file loadBalancerProp.load(lbInput); // get the property value and print it out nodeList = loadBalancerProp.getProperty("nodeList"); destTestRootDir = (destTestRootDir != null) ? destTestRootDir.trim() : null; HashMap<String, CloudNode> nl = new HashMap<>(); if(testList != null) { for(String nstr : nodeList.split(",")) { String nodeName = nstr.trim(); testDirPostfix = (testDirPostfix != null) ? testDirPostfix.trim() : CloudNode.defaultDirPostfix; CloudNode n = new CloudNode(nodeName, testDirPostfix); n.ip = loadBalancerProp.getProperty(nodeName + "_ip"); n.weight = Integer.parseInt(loadBalancerProp.getProperty(nodeName + "_weight")); n.port = Integer.parseInt(loadBalancerProp.getProperty(nodeName + "_port")); n.httpPort = Integer.parseInt(loadBalancerProp.getProperty(nodeName + "_httpPort")); totalWeight += n.weight; System.out.println("nodeList item: (" + n.name + ", " + n.ip + ", " + n.port + ", " + n.weight + ")"); nl.put(nodeName, n); } } Set<String> tl = new HashSet<>(); if(testList != null) { for(String tstr : testList.split(",")) { System.out.println("testList item: (" + tstr.trim() + ")"); tl.add(tstr.trim()); } } Set<String> dl = new HashSet<>(); if(categoryList != null) { for(String tstr : categoryList.split(",")) { dl.add(tstr.trim()); } } boolean cbl = false, tbl = false; if(categoryUseBlackList != null) { if (categoryUseBlackList.compareToIgnoreCase("true") == 0) cbl = true; else if (categoryUseBlackList.compareToIgnoreCase("false") != 0) dl = null; } else { dl = null; } if(useBlackList != null) { if (useBlackList.compareToIgnoreCase("true") == 0) tbl = true; else if (useBlackList.compareToIgnoreCase("false") != 0) tl = null; } else { tl = null; } //Test Sources Selection Set<File> testFiles; testFiles = TestHelper.listTestFiles(testFolder, testPattern, dl, cbl, tl, tbl); /*Set<File> testFiles; if(useBlackList != null) { if(useBlackList.compareToIgnoreCase("false") == 0) { testFiles = TestHelper.whiteListFiles(testFolder, tl); } else if (useBlackList.compareToIgnoreCase("true") == 0) { testFiles = TestHelper.blackListFiles(testFolder, tl); } else { testFiles = TestHelper.listTestFiles(testFolder, testPattern); } } else { testFiles = TestHelper.listTestFiles(testFolder, testPattern); }*/ //Language Selection List<TargetedLanguage> langs = new LinkedList<>(); int spareThreads = 0; if(languageList != null) { for(String lstr :languageList.split(",")) { if(lstr.trim().compareTo("arduino") == 0) { langs.add(new lArduino()); } if(lstr.trim().compareTo("posix") == 0) { langs.add(new lPosix()); } if(lstr.trim().compareTo("java") == 0) { langs.add(new lJava()); } if(lstr.trim().compareTo("nodejs") == 0) { langs.add(new lJavaScript()); } if(lstr.trim().compareTo("sintefboard") == 0) { langs.add(new lSintefboard()); } if(lstr.trim().compareTo("posixmt") == 0) { langs.add(new lPosixMT()); } } } else { langs.add(new lPosix()); langs.add(new lJava()); langs.add(new lJavaScript()); langs.add(new lArduino()); langs.add(new lSintefboard()); langs.add(new lPosixMT()); } //Load balancing CloudNode worker[] = new CloudNode[totalWeight]; int index = 0; for (CloudNode n : nl.values()) { for(int i = 0; i < n.weight; i++) { worker[index] = n; index++; } } index = 0; for(File t : testFiles) { worker[index].tests.add(t); index = (index + 1) % totalWeight; } for (CloudNode n : nl.values()) { n.languages.add(languageList); if(destTestRootDir == null) { n.makeTestDir(workingDir, ressourcesDir, compilerJar, testJar, testFolder); } else { n.createBalancedConfig(new File(destTestRootDir)); } } System.out.println("Master Node IP: " + loadBalancerProp.getProperty("masternode_ip")); System.out.println("Master Node Port: " + loadBalancerProp.getProperty("masternode_port")); generateDispatchScript(workingDir, loadBalancerProp.getProperty("masternode_ip"), loadBalancerProp.getProperty("masternode_port"), nl.values()); File resultsHeaderFile = new File(tmpDir, "header.html"); File resultsFooterFile = new File(tmpDir, "footer.html"); try { PrintWriter w = new PrintWriter(resultsFooterFile); w.print(TestHelper.getTemplateByID("loadBalancer/htmlTemplates/footer.html")); w.close(); } catch (Exception ex) { System.err.println("Problem writing log"); ex.printStackTrace(); } try { PrintWriter w = new PrintWriter(resultsHeaderFile); String header = TestHelper.getTemplateByID("loadBalancer/htmlTemplates/header.html"); String htmlLangList = "\n"; for(TargetedLanguage lang : langs) { htmlLangList += " <th>" + lang.compilerID + "</th>\n"; } header = header.replace("<th>nodejs</th><th>java</th><th>posixmt</th>", htmlLangList); w.print(header); w.close(); } catch (Exception ex) { System.err.println("Problem writing log"); ex.printStackTrace(); } } catch (IOException ex) { ex.printStackTrace(); } } public static void generateDispatchScript(File workingDir, String masterIP, String masterPort, Collection<CloudNode> nodeList) { String dispatchScript = TestHelper.getTemplateByID("loadBalancer/dispachTest.sh"); dispatchScript = dispatchScript.replace("#IP_MASTER", "masterIp=\"" + masterIP + "\""); dispatchScript = dispatchScript.replace("#PORT_MASTER", "masterPort=\"" + masterPort + "\""); String tasks =""; String wait =""; for(CloudNode n : nodeList) { tasks += "(work " + n.name + " " + n.ip + " " + n.port + " > " + n.name + "_testDir/log)&\n"; wait += "wait_node " + n.name + "\n"; } dispatchScript = dispatchScript.replace("#DISPATCH", tasks); dispatchScript = dispatchScript.replace("#WAIT", wait); File dispatchScriptFile = new File(workingDir, "dispatch.sh"); try { PrintWriter w = new PrintWriter(dispatchScriptFile); w.print(dispatchScript); w.close(); } catch (Exception ex) { System.err.println("Problem writing log"); ex.printStackTrace(); } } }