Skip to content

Commit c057a02

Browse files
committed
Separate UI physically from service layer (#118)
The UI transmits now a JobDescription when a diagnosis should be performed, so the server creates necessary configuration files for DS to run (identical to those locally configured on the client-side before) using this data. The results are only saved on the server side now. The configuration files and results are saved on a per job-id basis, so that (not implemented yet) the client can request the results later via DS service using the job id that was used to trigger the diagnosis run. Change-Id: I990cc93a2851726dead0d33e2f1a935ddd5c46ad Signed-off-by: Denis Knoepfle <denis.knoepfle@sap.com>
1 parent c5dc57f commit c057a02

File tree

7 files changed

+129
-24
lines changed

7 files changed

+129
-24
lines changed

org.spotter.client/src/org/spotter/client/SpotterServiceClient.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.lpe.common.config.ConfigParameterDescription;
2323
import org.lpe.common.util.web.LpeWebUtils;
2424
import org.spotter.shared.configuration.ConfigKeys;
25+
import org.spotter.shared.configuration.JobDescription;
2526
import org.spotter.shared.configuration.SpotterExtensionType;
2627
import org.spotter.shared.hierarchy.model.XPerformanceProblem;
2728
import org.spotter.shared.service.SpotterServiceResponse;
@@ -73,15 +74,15 @@ public void updateUrl(String host, String port) {
7374
/**
7475
* Executes diagnostics process.
7576
*
76-
* @param configurationFile
77-
* path to the configuration file
78-
* @return job id for the started diagnosis task,
77+
* @param jobDescription
78+
* the job description to use
79+
* @return job id for the started diagnosis task
7980
*/
80-
public long startDiagnosis(String configurationFile) {
81+
public long startDiagnosis(JobDescription jobDescription) {
8182
SpotterServiceResponse<Long> response = webResource.path(ConfigKeys.SPOTTER_REST_BASE)
8283
.path(ConfigKeys.SPOTTER_REST_START_DIAG).type(MediaType.APPLICATION_JSON)
8384
.accept(MediaType.APPLICATION_JSON).post(new GenericType<SpotterServiceResponse<Long>>() {
84-
}, configurationFile);
85+
}, jobDescription);
8586

8687
switch (response.getStatus()) {
8788
case INVALID_STATE:

org.spotter.eclipse.ui/src/org/spotter/eclipse/ui/ServiceClientWrapper.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.spotter.eclipse.ui.model.ExtensionMetaobject;
3232
import org.spotter.eclipse.ui.util.DialogUtils;
3333
import org.spotter.eclipse.ui.util.SpotterProjectSupport;
34+
import org.spotter.shared.configuration.JobDescription;
3435
import org.spotter.shared.configuration.SpotterExtensionType;
3536
import org.spotter.shared.hierarchy.model.RawHierarchyFactory;
3637
import org.spotter.shared.hierarchy.model.XPerformanceProblem;
@@ -222,17 +223,17 @@ public boolean saveServiceClientSettings(String newHost, String newPort) {
222223
}
223224

224225
/**
225-
* Starts the diagnosis using the given configuration file. Returns the
226+
* Starts the diagnosis using the given job description. Returns the
226227
* retrieved job id or <code>null</code> on failure.
227228
*
228-
* @param configurationFile
229-
* The configuration file to use.
229+
* @param jobDescription
230+
* The job description to use.
230231
* @return The retrieved job id or <code>null</code> on failure.
231232
*/
232-
public Long startDiagnosis(final String configurationFile) {
233+
public Long startDiagnosis(final JobDescription jobDescription) {
233234
lastException = null;
234235
try {
235-
return client.startDiagnosis(configurationFile);
236+
return client.startDiagnosis(jobDescription);
236237
} catch (Exception e) {
237238
handleException("startDiagnosis", MSG_START_DIAGNOSIS, e, false, false);
238239
}

org.spotter.eclipse.ui/src/org/spotter/eclipse/ui/handlers/RunHandler.java

+39-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.spotter.eclipse.ui.handlers;
1717

18+
import java.util.Properties;
1819
import java.util.Set;
1920

2021
import org.eclipse.core.commands.AbstractHandler;
@@ -24,9 +25,16 @@
2425
import org.eclipse.core.resources.IProject;
2526
import org.spotter.eclipse.ui.Activator;
2627
import org.spotter.eclipse.ui.ServiceClientWrapper;
28+
import org.spotter.eclipse.ui.UICoreException;
2729
import org.spotter.eclipse.ui.jobs.DynamicSpotterRunJob;
30+
import org.spotter.eclipse.ui.model.xml.HierarchyFactory;
31+
import org.spotter.eclipse.ui.model.xml.MeasurementEnvironmentFactory;
2832
import org.spotter.eclipse.ui.util.DialogUtils;
33+
import org.spotter.eclipse.ui.util.SpotterProjectSupport;
2934
import org.spotter.shared.configuration.FileManager;
35+
import org.spotter.shared.configuration.JobDescription;
36+
import org.spotter.shared.environment.model.XMeasurementEnvironment;
37+
import org.spotter.shared.hierarchy.model.XPerformanceProblem;
3038

3139
/**
3240
* A run handler for the DynamicSpotter run command which starts the
@@ -83,7 +91,7 @@ public Object execute(ExecutionEvent event) throws ExecutionException {
8391
boolean startConfirm = DialogUtils.openConfirm(DIALOG_TITLE,
8492
String.format(MSG_SPOTTER_STARTED, project.getName()));
8593
if (startConfirm) {
86-
startSpotterRun(project, client, spotterFilePath);
94+
startSpotterRun(project, client);
8795
}
8896
return null;
8997
}
@@ -93,8 +101,16 @@ public boolean isEnabled() {
93101
return Activator.getDefault().getSelectedProjects().size() == 1;
94102
}
95103

96-
private void startSpotterRun(IProject project, ServiceClientWrapper client, String spotterConfigPath) {
97-
Long jobId = client.startDiagnosis(spotterConfigPath);
104+
private void startSpotterRun(IProject project, ServiceClientWrapper client) {
105+
JobDescription jobDescription;
106+
try {
107+
jobDescription = createJobDescription(project);
108+
} catch (UICoreException e) {
109+
String msg = "Unable to read and parse all configuration files!";
110+
DialogUtils.openError(DIALOG_TITLE, DialogUtils.appendCause(msg, e.getMessage()));
111+
return;
112+
}
113+
Long jobId = client.startDiagnosis(jobDescription);
98114
if (jobId != null && jobId != 0) {
99115
DynamicSpotterRunJob job = new DynamicSpotterRunJob(project, jobId);
100116
job.schedule();
@@ -104,4 +120,24 @@ private void startSpotterRun(IProject project, ServiceClientWrapper client, Stri
104120
}
105121
}
106122

123+
private JobDescription createJobDescription(IProject project) throws UICoreException {
124+
JobDescription jobDescription = new JobDescription();
125+
126+
IFile spotterFile = project.getFile(FileManager.SPOTTER_CONFIG_FILENAME);
127+
Properties dynamicSpotterConfig = SpotterProjectSupport.getSpotterConfig(spotterFile);
128+
jobDescription.setDynamicSpotterConfig(dynamicSpotterConfig);
129+
130+
MeasurementEnvironmentFactory envFactory = MeasurementEnvironmentFactory.getInstance();
131+
String envFile = project.getFile(FileManager.ENVIRONMENT_FILENAME).getLocation().toString();
132+
XMeasurementEnvironment measurementEnvironment = envFactory.parseXMLFile(envFile);
133+
jobDescription.setMeasurementEnvironment(measurementEnvironment);
134+
135+
HierarchyFactory hierFactory = HierarchyFactory.getInstance();
136+
String hierFile = project.getFile(FileManager.HIERARCHY_FILENAME).getLocation().toString();
137+
XPerformanceProblem hierarchy = hierFactory.parseHierarchyFile(hierFile);
138+
jobDescription.setHierarchy(hierarchy);
139+
140+
return jobDescription;
141+
}
142+
107143
}

org.spotter.service/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010
dependency-reduced-pom.xml
1111
default-hierarchy.xml
1212
/plugins
13+
/runtime-diagnosis
1314
/pom.xml.versionsBackup

org.spotter.service/src/org/spotter/service/SpotterServiceWrapper.java

+45-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.spotter.service;
1717

18+
import java.io.IOException;
1819
import java.util.Collections;
1920
import java.util.HashSet;
2021
import java.util.Set;
@@ -23,11 +24,14 @@
2324
import java.util.concurrent.Executors;
2425
import java.util.concurrent.Future;
2526

27+
import javax.xml.bind.JAXBException;
28+
2629
import org.lpe.common.config.ConfigParameterDescription;
2730
import org.lpe.common.extension.ExtensionRegistry;
2831
import org.lpe.common.extension.Extensions;
2932
import org.lpe.common.extension.IExtension;
3033
import org.lpe.common.extension.IExtensionArtifact;
34+
import org.lpe.common.util.LpeFileUtils;
3135
import org.slf4j.Logger;
3236
import org.slf4j.LoggerFactory;
3337
import org.spotter.core.AbstractSpotterSatelliteExtension;
@@ -37,6 +41,8 @@
3741
import org.spotter.core.measurement.AbstractMeasurmentExtension;
3842
import org.spotter.core.workload.AbstractWorkloadExtension;
3943
import org.spotter.shared.configuration.ConfigKeys;
44+
import org.spotter.shared.configuration.FileManager;
45+
import org.spotter.shared.configuration.JobDescription;
4046
import org.spotter.shared.configuration.SpotterExtensionType;
4147
import org.spotter.shared.hierarchy.model.RawHierarchyFactory;
4248
import org.spotter.shared.hierarchy.model.XPerformanceProblem;
@@ -49,7 +55,20 @@
4955
*
5056
*/
5157
public class SpotterServiceWrapper {
58+
5259
private static final Logger LOGGER = LoggerFactory.getLogger(SpotterServiceWrapper.class);
60+
61+
/**
62+
* The path to the current working directory.
63+
*/
64+
private static final String WORKING_DIR = System.getProperty("user.dir").replace('\\', '/');
65+
66+
/**
67+
* The name of the folder where to put the configuration and results of
68+
* diagnosis runs.
69+
*/
70+
private static final String RUNTIME_FOLDER = "runtime-diagnosis";
71+
5372
private static SpotterServiceWrapper instance;
5473

5574
/**
@@ -74,23 +93,26 @@ public static synchronized SpotterServiceWrapper getInstance() {
7493
/**
7594
* Executes diagnostics process.
7695
*
77-
* @param configurationFile
78-
* path to the configuration file
96+
* @param jobDescription
97+
* job description object containing the whole DS setup such as
98+
* config values, environment and hierarchy configuration
7999
* @return job id for the started diagnosis task, 0 if currently a diagnosis
80100
* job is already running
81101
*/
82-
public synchronized long startDiagnosis(final String configurationFile) {
102+
public synchronized long startDiagnosis(final JobDescription jobDescription) {
83103
if (getState().equals(JobState.RUNNING)) {
84104
return 0;
85105
}
86106
final long tempJobId = System.currentTimeMillis();
87107
currentJob = tempJobId;
88108
currentJobState = JobState.RUNNING;
109+
89110
futureObject = executor.submit(new Runnable() {
90111

91112
@Override
92113
public void run() {
93114
try {
115+
String configurationFile = createDynamicSpotterConfiguration(tempJobId, jobDescription);
94116
Spotter.getInstance().startDiagnosis(configurationFile, tempJobId);
95117
currentJobState = JobState.FINISHED;
96118
} catch (Throwable e) {
@@ -106,6 +128,26 @@ public void run() {
106128
return tempJobId;
107129
}
108130

131+
private String createDynamicSpotterConfiguration(long jobId, JobDescription jobDescription) {
132+
FileManager fileManager = FileManager.getInstance();
133+
String location = SpotterServiceWrapper.WORKING_DIR + "/" + SpotterServiceWrapper.RUNTIME_FOLDER + "/" + jobId;
134+
LpeFileUtils.createDir(location);
135+
String configurationFile = null;
136+
137+
try {
138+
fileManager.writeEnvironmentConfig(location, jobDescription.getMeasurementEnvironment());
139+
fileManager.writeHierarchyConfig(location, jobDescription.getHierarchy());
140+
configurationFile = fileManager.writeSpotterConfig(location, jobDescription.getDynamicSpotterConfig());
141+
LOGGER.info("Storing configuration for diagnosis run #" + jobId + " in " + location);
142+
} catch (IOException | JAXBException e) {
143+
String msg = "Failed to create DS configuration.";
144+
LOGGER.error(msg + " Cause: {}", e.toString());
145+
throw new RuntimeException(msg);
146+
}
147+
148+
return configurationFile;
149+
}
150+
109151
/**
110152
* Returns the current state of the last issued job.
111153
*

org.spotter.service/src/org/spotter/service/rest/SpotterService.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.lpe.common.config.ConfigParameterDescription;
3030
import org.spotter.service.SpotterServiceWrapper;
3131
import org.spotter.shared.configuration.ConfigKeys;
32+
import org.spotter.shared.configuration.JobDescription;
3233
import org.spotter.shared.configuration.SpotterExtensionType;
3334
import org.spotter.shared.hierarchy.model.XPerformanceProblem;
3435
import org.spotter.shared.service.ResponseStatus;
@@ -49,8 +50,9 @@ public class SpotterService {
4950
/**
5051
* Starts Dynamic Spotter diagnosis.
5152
*
52-
* @param pathToConfigFile
53-
* configuration file
53+
* @param jobDescription
54+
* job description object containing the whole DS setup such as
55+
* config values, environment and hierarchy configuration
5456
* @throws IOException
5557
* thrown if experiment fails
5658
* @return job id, 0 if already running
@@ -59,9 +61,9 @@ public class SpotterService {
5961
@Path(ConfigKeys.SPOTTER_REST_START_DIAG)
6062
@Consumes(MediaType.APPLICATION_JSON)
6163
@Produces(MediaType.APPLICATION_JSON)
62-
public SpotterServiceResponse<Long> startDiagnosis(String pathToConfigFile) throws IOException {
64+
public SpotterServiceResponse<Long> startDiagnosis(JobDescription jobDescription) throws IOException {
6365
try {
64-
long jobId = SpotterServiceWrapper.getInstance().startDiagnosis(pathToConfigFile);
66+
long jobId = SpotterServiceWrapper.getInstance().startDiagnosis(jobDescription);
6567
if (jobId == 0) {
6668
return new SpotterServiceResponse<Long>(jobId, ResponseStatus.INVALID_STATE);
6769
} else {

org.spotter.shared/src/org/spotter/shared/configuration/FileManager.java

+26-4
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
import java.io.File;
1919
import java.io.FileWriter;
2020
import java.io.IOException;
21+
import java.util.HashMap;
2122
import java.util.Map;
2223
import java.util.Properties;
2324

2425
import javax.xml.bind.JAXBException;
2526

27+
import org.lpe.common.config.ConfigParameterDescription;
2628
import org.spotter.shared.environment.model.XMeasurementEnvironment;
2729
import org.spotter.shared.hierarchy.model.XPerformanceProblem;
2830
import org.spotter.shared.util.JAXBUtil;
@@ -68,10 +70,11 @@ public static synchronized FileManager getInstance() {
6870
* the location where to place this file (without the filename)
6971
* @param properties
7072
* the project specific properties to write
73+
* @return the filename of the created file
7174
* @throws IOException
7275
* if an I/O error occurs
7376
*/
74-
public void writeSpotterConfig(String location, Properties properties) throws IOException {
77+
public String writeSpotterConfig(String location, Properties properties) throws IOException {
7578
Properties general = createGeneralSpotterProperties(location);
7679

7780
String file = stripFileSeparator(location) + "/" + FileManager.SPOTTER_CONFIG_FILENAME;
@@ -84,6 +87,8 @@ public void writeSpotterConfig(String location, Properties properties) throws IO
8487
fileWriter.close();
8588
}
8689
}
90+
91+
return file;
8792
}
8893

8994
/**
@@ -93,12 +98,14 @@ public void writeSpotterConfig(String location, Properties properties) throws IO
9398
* the location where to place this file (without the filename)
9499
* @param environment
95100
* the environment object to write
101+
* @return the filename of the created file
96102
* @throws JAXBException
97103
* if a problem with the marshalling occurs
98104
*/
99-
public void writeEnvironmentConfig(String location, XMeasurementEnvironment environment) throws JAXBException {
105+
public String writeEnvironmentConfig(String location, XMeasurementEnvironment environment) throws JAXBException {
100106
String file = stripFileSeparator(location) + "/" + FileManager.ENVIRONMENT_FILENAME;
101107
JAXBUtil.writeElementToFile(new File(file), environment);
108+
return file;
102109
}
103110

104111
/**
@@ -108,12 +115,14 @@ public void writeEnvironmentConfig(String location, XMeasurementEnvironment envi
108115
* the location where to place this file (without the filename)
109116
* @param hierarchy
110117
* the hierarchy object to write
118+
* @return the filename of the created file
111119
* @throws JAXBException
112120
* if a problem with the marshalling occurs
113121
*/
114-
public void writeHierarchyConfig(String location, XPerformanceProblem hierarchy) throws JAXBException {
122+
public String writeHierarchyConfig(String location, XPerformanceProblem hierarchy) throws JAXBException {
115123
String file = stripFileSeparator(location) + "/" + FileManager.HIERARCHY_FILENAME;
116124
JAXBUtil.writeElementToFile(new File(file), hierarchy);
125+
return file;
117126
}
118127

119128
/**
@@ -157,8 +166,12 @@ public String createSpotterConfigFileContent(Map<String, String> descriptionMapp
157166
sb.append("\r\n\r\n");
158167
writeHeading(sb, "SPECIFIED SETTINGS");
159168

169+
if (descriptionMapping == null) {
170+
descriptionMapping = createDescriptionMapping();
171+
}
172+
160173
for (String key : properties.stringPropertyNames()) {
161-
String comment = descriptionMapping == null ? null : descriptionMapping.get(key);
174+
String comment = descriptionMapping.get(key);
162175
writeKeyValuePair(sb, properties, key, comment);
163176
}
164177
return sb.toString();
@@ -177,6 +190,15 @@ private void writeKeyValuePair(StringBuilder sb, Properties prop, String key, St
177190
sb.append(key + " = " + prop.getProperty(key) + "\r\n");
178191
}
179192

193+
private Map<String, String> createDescriptionMapping() {
194+
Map<String, String> descriptionMapping = new HashMap<>();
195+
196+
for (ConfigParameterDescription desc : ConfigKeys.getSpotterConfigParamters()) {
197+
descriptionMapping.put(desc.getName(), desc.getDescription());
198+
}
199+
return descriptionMapping;
200+
}
201+
180202
private String stripFileSeparator(String path) {
181203
if (path.endsWith("/") || path.endsWith("\\")) {
182204
return path.substring(0, path.length() - 1);

0 commit comments

Comments
 (0)