From ef2c595afe6cf74b79d9df6ead159ffc2252640c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=BCrgen=20Walter?= <juergen.walter@uni-wuerzburg.de>
Date: Fri, 20 Jan 2017 17:29:35 +0100
Subject: [PATCH] added number of CPU cores parameter

added to PMX CommandLine and passed it to LibReDE
---
 .../descartes/pmx/console/PMXCommandLine.java | 36 ++++++++++++++++++-
 .../tools/descartes/pmx/PMXController.java    | 24 +++++++++----
 .../PerformanceModelFilterAppender.java       | 11 ++++--
 .../resourcedemands/ResourceDemandFilter.java | 30 ++++++++++++----
 .../EstimationSpecificationFactory.java       | 19 +++++-----
 .../adapter/LibReDEAdapter.java               |  4 +--
 6 files changed, 96 insertions(+), 28 deletions(-)

diff --git a/tools.descartes.pmx.console/src/tools/descartes/pmx/console/PMXCommandLine.java b/tools.descartes.pmx.console/src/tools/descartes/pmx/console/PMXCommandLine.java
index 043ebe39..3cede646 100644
--- a/tools.descartes.pmx.console/src/tools/descartes/pmx/console/PMXCommandLine.java
+++ b/tools.descartes.pmx.console/src/tools/descartes/pmx/console/PMXCommandLine.java
@@ -28,6 +28,7 @@ package tools.descartes.pmx.console;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.HashMap;
 
 import org.apache.commons.cli.BasicParser;
 import org.apache.commons.cli.CommandLine;
@@ -65,6 +66,8 @@ public class PMXCommandLine {
 	private static final String CMD_LONG_OPT_INPUT_DIR = "trace-file";
 	private static final String CMD_LONG_OPT_CONFIG_FILE = "pmx-config";
 	private static final String CMD_LONG_OPT_OUTPUT_DIR = "output-dir";
+	private static final String CMD_OPT_NUM_CORE = "numCore";
+
 	private static final HelpFormatter commandLineFormatter = new HelpFormatter();
 	private static final String toolName = "Performance Model eXtractor(PMX)";
 	private static IModelBuilder modelBuilder;
@@ -118,6 +121,15 @@ public class PMXCommandLine {
 		OptionBuilder.withValueSeparator(' ');
 		Option ignoreAfterOption = OptionBuilder.create("a");
 		options.addOption(ignoreAfterOption);
+
+		OptionBuilder.withArgName("long");
+		OptionBuilder.hasArgs();
+		OptionBuilder.withLongOpt(PMXCommandLine.CMD_OPT_NUM_CORE);
+		OptionBuilder.isRequired(false);
+		OptionBuilder.withDescription("specifies number of cores for a host");
+		OptionBuilder.withValueSeparator(' ');
+		Option numCoresOption = OptionBuilder.create("cores");
+		options.addOption(numCoresOption);
 	}
 	
 	public static void main(String[] args) {
@@ -173,6 +185,8 @@ public class PMXCommandLine {
 				outputDir = inputDirs[0];
 				log.info("No output directory specified. Logging to input directory.");
 			}
+			
+			HashMap<String, Integer> numCores = getNumberOfCores();
 
 			initFileLogging(outputDir, "extraction.log", new SimpleLayout());
 			initFileLogging(outputDir, "extraction.log.html", new HTMLLayout());
@@ -180,7 +194,7 @@ public class PMXCommandLine {
 			PMXController controller = new PMXController(analysisController, outputDir,
 					commandLine.getOptionValue(TimestampFilter.CONFIG_PROPERTY_NAME_IGNORE_BEFORE_TIMESTAMP),
 					commandLine.getOptionValue(TimestampFilter.CONFIG_PROPERTY_NAME_IGNORE_AFTER_TIMESTAMP),
-					commandLine.hasOption("reduced"));
+					commandLine.hasOption("reduced"), numCores);
 			return controller;
 		} catch (NullPointerException e) {
 			//PMXCommandLine.printUsage();
@@ -194,6 +208,26 @@ public class PMXCommandLine {
 
 	}
 
+	private HashMap<String, Integer> getNumberOfCores() {
+		String coresCmd = commandLine.getOptionValue(CMD_OPT_NUM_CORE);
+		log.info(coresCmd + " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
+		String[] numCoresDescriptions;
+		if(coresCmd.contains(",")){
+			numCoresDescriptions = coresCmd.split(",");
+		}else if (coresCmd.contains("=")){
+			numCoresDescriptions = new String[]{coresCmd};
+		}else{
+			numCoresDescriptions = new String[0];
+		}
+		HashMap<String, Integer> numberOfCores = new HashMap<String, Integer>();
+		for(String ab: numCoresDescriptions){
+			numberOfCores.put(ab.split("=")[0], Integer.parseInt(ab.split("=")[1]));
+			log.info(ab.split("=")[0] + " = " + Integer.parseInt(ab.split("=")[1]));
+		}
+		
+		return numberOfCores;
+	}
+
 	private String[] getInputDirs() {
 		String inputDirCmd = commandLine.getOptionValue(CMD_LONG_OPT_INPUT_DIR);
 		String[] inputDirs = inputDirCmd.split(";");
diff --git a/tools.descartes.pmx/src/tools/descartes/pmx/PMXController.java b/tools.descartes.pmx/src/tools/descartes/pmx/PMXController.java
index bd813732..dad413ee 100644
--- a/tools.descartes.pmx/src/tools/descartes/pmx/PMXController.java
+++ b/tools.descartes.pmx/src/tools/descartes/pmx/PMXController.java
@@ -28,6 +28,7 @@ package tools.descartes.pmx;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.HashMap;
 
 import org.apache.log4j.Logger;
 
@@ -50,14 +51,17 @@ public class PMXController {
 	private long ignoreExecutionsBeforeTimestamp = Long.parseLong(TimestampFilter.CONFIG_PROPERTY_VALUE_MIN_TIMESTAMP);
 	private long ignoreExecutionsAfterTimestamp = Long.parseLong(TimestampFilter.CONFIG_PROPERTY_VALUE_MAX_TIMESTAMP);
 	private static IModelBuilder modelBuilder;
+	private HashMap<String, Integer> numCores;
 
-	public PMXController(IAnalysisController analysisController, String path, String ignoreExecutionsBeforeTimestamp, String ignoreExecutionsAfterTimestamp)
+	public PMXController(IAnalysisController analysisController, String path, String ignoreExecutionsBeforeTimestamp,
+			String ignoreExecutionsAfterTimestamp, HashMap<String, Integer> numCores)
 			throws IOException {
 		//this(analysisController, path, ignoreExecutionsBeforeTimestamp, ignoreExecutionsAfterTimestamp, false);
-		this(analysisController, path, ignoreExecutionsBeforeTimestamp, ignoreExecutionsAfterTimestamp, true);
+		this(analysisController, path, ignoreExecutionsBeforeTimestamp, ignoreExecutionsAfterTimestamp, true, numCores);
 	}
 
-	public PMXController(IAnalysisController analysisController, String path, String ignoreExecutionsBeforeTimestamp, String ignoreExecutionsAfterTimestamp, boolean isReduced)
+	public PMXController(IAnalysisController analysisController, String path, String ignoreExecutionsBeforeTimestamp,
+			String ignoreExecutionsAfterTimestamp, boolean isReduced, HashMap<String, Integer> numCores)
 			throws IOException {
 		this.analysisController = analysisController;
 		this.outputDir = path;
@@ -71,11 +75,13 @@ public class PMXController {
 		if(ignoreExecutionsBeforeTimestamp != null){
 			this.ignoreExecutionsAfterTimestamp = Long.parseLong(ignoreExecutionsAfterTimestamp);
 		}
+		this.numCores = numCores;
 	}
 	
 	public void run() throws AnalysisConfigurationException {
 		log.info("initializing filters... |||||||||||||||||||||||||||||||||||||||||||||||||");
-		initAndConnectKiekerFilters(analysisController, outputDir, ignoreExecutionsBeforeTimestamp, ignoreExecutionsAfterTimestamp, isReduced);
+		initAndConnectKiekerFilters(analysisController, outputDir, ignoreExecutionsBeforeTimestamp,
+				ignoreExecutionsAfterTimestamp, isReduced, numCores);
 		
 		log.info("running filters...  |||||||||||||||||||||||||||||||||||||||||||||||||");
 		analysisController.run(); 
@@ -83,8 +89,12 @@ public class PMXController {
 
 	/**
 	 * Connects the Kieker filters
+	 * 
+	 * @param numCores
 	 */
-	private static void initAndConnectKiekerFilters(IAnalysisController analysisController, String resultPath, long ignoreExecutionsBeforeTimestamp, long ignoreExecutionsAfterTimestamp, boolean isReduced){
+	private static void initAndConnectKiekerFilters(IAnalysisController analysisController, String resultPath,
+			long ignoreExecutionsBeforeTimestamp, long ignoreExecutionsAfterTimestamp, boolean isReduced,
+			HashMap<String, Integer> numCores) {
 		// initialize and register the system model repository
 		final SystemModelRepository systemModelRepository = new SystemModelRepository(
 				new Configuration(), analysisController);
@@ -97,7 +107,9 @@ public class PMXController {
 
 		// connect lots of filters to the connection point
 		try {
-			PerformanceModelFilterAppender.initAndConnectFilters(systemModelRepository, reader, port, analysisController, resultPath, ignoreExecutionsBeforeTimestamp, ignoreExecutionsAfterTimestamp, isReduced);
+			PerformanceModelFilterAppender.initAndConnectFilters(systemModelRepository, reader, port,
+					analysisController, resultPath, ignoreExecutionsBeforeTimestamp, ignoreExecutionsAfterTimestamp,
+					isReduced, numCores);
 		} catch (IllegalStateException e) {
 			log.info(e);
 		} catch (AnalysisConfigurationException e) {
diff --git a/tools.descartes.pmx/src/tools/descartes/pmx/filter/PerformanceModelFilterAppender.java b/tools.descartes.pmx/src/tools/descartes/pmx/filter/PerformanceModelFilterAppender.java
index b93bdba5..2461c09a 100644
--- a/tools.descartes.pmx/src/tools/descartes/pmx/filter/PerformanceModelFilterAppender.java
+++ b/tools.descartes.pmx/src/tools/descartes/pmx/filter/PerformanceModelFilterAppender.java
@@ -28,6 +28,7 @@ package tools.descartes.pmx.filter;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.log4j.Logger;
@@ -55,10 +56,10 @@ import kieker.tools.traceAnalysis.filter.visualization.dependencyGraph.Operation
 import kieker.tools.traceAnalysis.filter.visualization.dependencyGraph.ResponseTimeNodeDecorator;
 import kieker.tools.traceAnalysis.systemModel.repository.SystemModelRepository;
 import tools.descartes.pmx.filter.controlflow.CallNodeDecorator;
-import tools.descartes.pmx.filter.resourcedemands.AbstractResourceDemandFilter;
-import tools.descartes.pmx.filter.resourcedemands.CPUFilter;
 import tools.descartes.pmx.filter.resourcedemands.ResourceDemandFilter;
 import tools.descartes.pmx.filter.util.FilterPortTuple;
+import unused.AbstractResourceDemandFilter;
+import unused.CPUFilter;
 
 public class PerformanceModelFilterAppender {
 	private static final Logger log = Logger.getLogger(PerformanceModelFilterAppender.class);
@@ -76,7 +77,8 @@ public class PerformanceModelFilterAppender {
 	 */
 	public static void initAndConnectFilters(final SystemModelRepository systemModelRepository, AbstractPlugin reader,
 			String port, IAnalysisController analysisController, String resultPath,
-			long ignoreExecutionsBeforeTimestamp, long ignoreExecutionsAfterTimestamp, boolean isReduced)
+			long ignoreExecutionsBeforeTimestamp, long ignoreExecutionsAfterTimestamp, boolean isReduced,
+			HashMap<String, Integer> numCores)
 			throws AnalysisConfigurationException {
 
 		TraceReconstructionFilter mtReconstrFilter = null;
@@ -262,6 +264,9 @@ public class PerformanceModelFilterAppender {
 
 		ResourceDemandFilter resourceDemandFilter = new ResourceDemandFilter(resourceDemandFilterConfiguration,
 				analysisController);
+		for (String host : numCores.keySet()) {
+			resourceDemandFilter.addCPUCoreMumber(host, numCores.get(host));
+		}
 		analysisController.connect(reader, port, cpuFilter, CPUFilter.INPUT_PORT_NAME);
 		analysisController.connect(cpuFilter, CPUFilter.OUTPUT_PORT_NAME_UTILIZATION, resourceDemandFilter,
 				ResourceDemandFilter.INPUT_PORT_NAME_UTILIZATION);
diff --git a/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/ResourceDemandFilter.java b/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/ResourceDemandFilter.java
index b3a3e27d..185f0ed2 100644
--- a/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/ResourceDemandFilter.java
+++ b/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/ResourceDemandFilter.java
@@ -33,6 +33,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.log4j.Logger;
+
 import kieker.analysis.IProjectContext;
 import kieker.analysis.plugin.annotation.InputPort;
 import kieker.analysis.plugin.annotation.OutputPort;
@@ -44,9 +46,6 @@ import kieker.tools.traceAnalysis.systemModel.AbstractMessage;
 import kieker.tools.traceAnalysis.systemModel.AllocationComponent;
 import kieker.tools.traceAnalysis.systemModel.Execution;
 import kieker.tools.traceAnalysis.systemModel.MessageTrace;
-
-import org.apache.log4j.Logger;
-
 import tools.descartes.librede.LibredeResults;
 import tools.descartes.librede.ResultTable;
 import tools.descartes.librede.approach.IEstimationApproach;
@@ -63,7 +62,7 @@ import tools.descartes.pmx.filter.resourcedemands.adapter.LibReDEAdapter;
 @Plugin(name = "ResourceDemandFilter", 
 description = "Subtracts times for external calls from total time for resource demand estimation.",
 outputPorts = { 
-		@OutputPort(name = AbstractResourceDemandFilter.OUTPUT_PORT_NAME_DEMANDS,
+				@OutputPort(name = ResourceDemandFilter.OUTPUT_PORT_NAME_DEMANDS,
 				description = "Outputs resource demands", eventTypes = { HashMap.class })
 })
 public class ResourceDemandFilter extends AbstractMessageTraceProcessingFilter {
@@ -74,6 +73,14 @@ public class ResourceDemandFilter extends AbstractMessageTraceProcessingFilter {
 	private static TimeSeries networkTimeSeries;
 	private static Set<String> hosts = new HashSet<String>();
 	private final String outputPath;
+	private HashMap<String, Integer> numCores = new HashMap<String, Integer>();
+
+	public void addCPUCoreMumber(String host, Integer number) {
+		if (numCores == null) {
+			numCores = new HashMap<String, Integer>();
+		}
+		numCores.put(host, number);
+	}
 	
 	public static final String INPUT_PORT_NAME_MESSAGE_TRACE = "messageTrace";
 	public static final String INPUT_PORT_NAME_EXECUTION_TRACES = "executionTraces";
@@ -260,6 +267,7 @@ public class ResourceDemandFilter extends AbstractMessageTraceProcessingFilter {
 	 */
 	@Override
 	public void terminate(final boolean errorBeforeTermination) {
+		super.terminate(errorBeforeTermination);
 		if(serviceTimeSeriesMap.keySet().isEmpty()){
 			log.error("could not extract service times to estimate resource demands");	//No service execution logs could be found
 			return;
@@ -278,8 +286,18 @@ public class ResourceDemandFilter extends AbstractMessageTraceProcessingFilter {
 
 			/** Run LibReDE */
 			try{
+				Integer cores = null;
+				if (numCores.containsKey(host)) {
+					cores = numCores.get(host);
+				}
+				if (cores == null) {
+					log.warn("no value passed for numer of cores at " + host);
+					log.info("did set number of cores to " + 2);
+					cores = 2;
+				}
+
 				LibredeResults estimates = LibReDEAdapter.initAndRunLibrede(host, serviceTimeSeriesMap,
-						resourceTimeSeriesMap, outputPath);
+						resourceTimeSeriesMap, outputPath, cores);
 	
 				Set<Class<? extends IEstimationApproach>> approaches = estimates.getApproaches();
 				Class<? extends IEstimationApproach> approach;
@@ -323,7 +341,7 @@ public class ResourceDemandFilter extends AbstractMessageTraceProcessingFilter {
 			}
 			resourceDemandMap.put("Network", averageDelay);
 		}
-		super.deliver(AbstractResourceDemandFilter.OUTPUT_PORT_NAME_DEMANDS, resourceDemandMap);
+		super.deliver(ResourceDemandFilter.OUTPUT_PORT_NAME_DEMANDS, resourceDemandMap);
 		super.terminate(errorBeforeTermination);
 	}
 	
diff --git a/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/EstimationSpecificationFactory.java b/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/EstimationSpecificationFactory.java
index 93e4ada5..1151de5e 100644
--- a/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/EstimationSpecificationFactory.java
+++ b/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/EstimationSpecificationFactory.java
@@ -54,9 +54,7 @@ public class EstimationSpecificationFactory {
 
 	public static EstimationSpecification createEstimationSpecification(
 			InMemoryDataSource dataSource, WorkloadDescription workloadDescription, String host,
-			LibredeConfiguration configuration) {
-		
-		//WorkloadDescription workloadDescription = repository.getWorkload();
+			LibredeConfiguration configuration, int numCores) {
 		
 		EstimationSpecification estimationSpecification = ConfigurationFactory.eINSTANCE
 				.createEstimationSpecification();
@@ -76,7 +74,8 @@ public class EstimationSpecificationFactory {
 			}
 		}
 		
-		estimationSpecification.setStepSize(UnitsFactory.eINSTANCE.createQuantity(range.getValue() / 10, Time.SECONDS));
+		estimationSpecification
+				.setStepSize(UnitsFactory.eINSTANCE.createQuantity(range.getValue() / 10, Time.SECONDS));
 		estimationSpecification.setWindow(60);
 		
 		configuration.getEstimation().setStartTimestamp(UnitsFactory.eINSTANCE.createQuantity(range.getStart(), Time.SECONDS));
@@ -96,7 +95,7 @@ public class EstimationSpecificationFactory {
 //			}
 //		}
 
-		addEstimationSpecification(workloadDescription, configuration, host, estimationSpecification);
+		addEstimationSpecification(workloadDescription, configuration, host, estimationSpecification, numCores);
 		//addEstimationSpeci
 		// addServiceDemandLawToEstimationSpecification(estimationSpecification);
 		// EstimationAlgorithmConfiguration estimationAlgorithmConfiguration =
@@ -110,14 +109,14 @@ public class EstimationSpecificationFactory {
 	private static void addEstimationSpecification(
 			WorkloadDescription workloadDescription,
 			LibredeConfiguration libredeConfiguration, String host,
-			EstimationSpecification estimationSpecification) {
+			EstimationSpecification estimationSpecification, int numCores) {
 		if (workloadDescription.getResources().size() == 0) {
 			log.info("\tno resource utilization logs for this host");
 			//log.info("\tassumtion: one CPU with two cores");
 			log.info("\tcan only apply response time estimation approach");
 			Resource cpu = ConfigurationFactory.eINSTANCE.createResource();
 			cpu.setName("CPU@" + host);
-			cpu.setNumberOfServers(2);
+			cpu.setNumberOfServers(numCores);
 			workloadDescription.getResources().add(cpu);
 			LibReDEAdapter.mapServicesToResources(workloadDescription);
 
@@ -131,7 +130,7 @@ public class EstimationSpecificationFactory {
 		.addResponseTimeApproximationApproachToEstimationSpecification(estimationSpecification);
 	}
 
-	public static void addResponseTimeApproximationApproachToEstimationSpecification(
+	private static void addResponseTimeApproximationApproachToEstimationSpecification(
 			EstimationSpecification estimationSpecification) {
 		EstimationApproachConfiguration estimationApproachConfiguration = ConfigurationFactory.eINSTANCE
 				.createEstimationApproachConfiguration();
@@ -142,7 +141,7 @@ public class EstimationSpecificationFactory {
 				estimationApproachConfiguration);
 	}
 
-	public static void addZhangKalmannApproachToEstimationSpecification(
+	private static void addZhangKalmannApproachToEstimationSpecification(
 			EstimationSpecification estimationSpecification) {
 		EstimationApproachConfiguration estimationApproachConfiguration = ConfigurationFactory.eINSTANCE
 				.createEstimationApproachConfiguration();
@@ -157,7 +156,7 @@ public class EstimationSpecificationFactory {
 		
 	}
 
-	public static void addServiceDemandLawToEstimationSpecification(
+	private static void addServiceDemandLawToEstimationSpecification(
 			EstimationSpecification estimationSpecification) {
 		EstimationApproachConfiguration estimationApproachConfiguration = ConfigurationFactory.eINSTANCE
 				.createEstimationApproachConfiguration();
diff --git a/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/LibReDEAdapter.java b/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/LibReDEAdapter.java
index 0676a940..10c9c69e 100644
--- a/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/LibReDEAdapter.java
+++ b/tools.descartes.pmx/src/tools/descartes/pmx/filter/resourcedemands/adapter/LibReDEAdapter.java
@@ -66,7 +66,7 @@ public class LibReDEAdapter {
 
 	public static LibredeResults initAndRunLibrede(String host,
 			Map<String, TimeSeries> serviceToTimeSeriesMap,
-			Map<String, TimeSeries> resourceTimeSeriesMap, String outputPath) {
+			Map<String, TimeSeries> resourceTimeSeriesMap, String outputPath, int numCores) {
 		Librede.init();
 
 		WorkloadDescription workloadDescription = ConfigurationFactory.eINSTANCE
@@ -99,7 +99,7 @@ public class LibReDEAdapter {
 		configuration.getInput().getDataSources().add(dataSourceConfiguration);
 		
 		EstimationSpecificationFactory.createEstimationSpecification(
-				dataSource, workloadDescription, host, configuration);
+				dataSource, workloadDescription, host, configuration, numCores);
 
 		Map<String, IDataSource> x = new HashMap<String, IDataSource>();
 		x.put("key", dataSource);
-- 
GitLab