Skip to content

Commit 72c07c1

Browse files
committed
Add automatic fetch of results in navigator (sopeco#116)
The main run results are now automatically fetched if they are not present already. This also solved the label issue of nodes (see sopeco#18). Change-Id: I02583fa477720ba61e97e0f5c2a97987193325da Signed-off-by: Denis Knoepfle <denis.knoepfle@sap.com>
1 parent 8b973e9 commit 72c07c1

File tree

7 files changed

+185
-45
lines changed

7 files changed

+185
-45
lines changed

org.spotter.eclipse.ui/src/org/spotter/eclipse/ui/jobs/DynamicSpotterRunJob.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ public class DynamicSpotterRunJob extends Job {
6262

6363
private final IProject project;
6464
private final long jobId;
65-
private final long timestamp;
6665
private final Set<String> processedProblems;
6766
private Map.Entry<String, DiagnosisProgress> currentProblem;
6867

@@ -81,7 +80,6 @@ public DynamicSpotterRunJob(IProject project, long jobId, long timestamp) {
8180

8281
this.project = project;
8382
this.jobId = jobId;
84-
this.timestamp = timestamp;
8583
this.processedProblems = new HashSet<>();
8684

8785
ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(Activator.PLUGIN_ID, ICON_PATH);
@@ -95,7 +93,7 @@ public DynamicSpotterRunJob(IProject project, long jobId, long timestamp) {
9593
setPriority(LONG);
9694
setUser(true);
9795

98-
if (!JobsContainer.registerJobId(project, jobId)) {
96+
if (!JobsContainer.registerJobId(project, jobId, timestamp)) {
9997
DialogUtils.openError(RunHandler.DIALOG_TITLE,
10098
"There was an error when saving the job id. You may not access the results of the diagnosis run.");
10199
}

org.spotter.eclipse.ui/src/org/spotter/eclipse/ui/jobs/JobsContainer.java

+47-9
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
import java.io.File;
1919
import java.io.IOException;
2020
import java.io.Serializable;
21+
import java.util.HashMap;
2122
import java.util.HashSet;
23+
import java.util.Map;
2224
import java.util.Set;
2325

2426
import org.eclipse.core.resources.IProject;
@@ -42,6 +44,7 @@ public class JobsContainer implements Serializable {
4244
private static final long serialVersionUID = 2437447304864394397L;
4345

4446
private final Set<Long> jobIds = new HashSet<>();
47+
private final Map<Long, Long> timestamps = new HashMap<>();
4548

4649
/**
4750
* Returns <code>true</code> if the id is included, otherwise
@@ -56,6 +59,20 @@ public boolean hasJobId(Long jobId) {
5659
return jobIds.contains(jobId);
5760
}
5861

62+
/**
63+
* Returns the timestamp that corresponds to the given job id.
64+
*
65+
* @param jobId
66+
* the job id the timestamp shall be returned for
67+
* @return the corresponding timestamp
68+
*/
69+
public Long getTimestamp(Long jobId) {
70+
if (!jobIds.contains(jobId)) {
71+
throw new IllegalArgumentException("The given job id is not registered");
72+
}
73+
return timestamps.get(jobId);
74+
}
75+
5976
/**
6077
* Returns an array of all stored job ids.
6178
*
@@ -79,9 +96,12 @@ public int count() {
7996
*
8097
* @param jobId
8198
* the id to add
99+
* @param timestamp
100+
* the corresponding timestamp
82101
*/
83-
public void addJobId(Long jobId) {
102+
public void addJobId(Long jobId, Long timestamp) {
84103
jobIds.add(jobId);
104+
timestamps.put(jobId, timestamp);
85105
}
86106

87107
/**
@@ -91,13 +111,15 @@ public void addJobId(Long jobId) {
91111
* the id to remove
92112
*/
93113
public void removeJobId(Long jobId) {
114+
timestamps.remove(jobId);
94115
jobIds.remove(jobId);
95116
}
96117

97118
/**
98119
* Clears all job ids.
99120
*/
100121
public void reset() {
122+
timestamps.clear();
101123
jobIds.clear();
102124
}
103125

@@ -108,33 +130,49 @@ public void reset() {
108130
* the project the id belongs to
109131
* @param jobId
110132
* the id to register
133+
* @param timestamp
134+
* the corresponding timestamp
111135
* @return <code>true</code> on success, otherwise <code>false</code>
112136
*/
113-
public static boolean registerJobId(IProject project, long jobId) {
137+
public static boolean registerJobId(IProject project, long jobId, long timestamp) {
114138
boolean success = false;
115139
synchronized (JobsContainer.jobMonitor) {
116140
JobsContainer jobsContainer = readJobsContainer(project);
117-
jobsContainer.addJobId(jobId);
141+
jobsContainer.addJobId(jobId, timestamp);
118142
success = writeJobsContainer(project, jobsContainer);
119143
}
120144
return success;
121145
}
122146

123147
/**
124-
* Returns the job ids that belong to the given project.
148+
* Removes the given job id for the project.
125149
*
126150
* @param project
127-
* the project whose job ids should be returned
128-
* @return array of related job ids
151+
* the project the id belongs to
152+
* @param jobId
153+
* the id to remove
154+
* @return <code>true</code> on success, otherwise <code>false</code>
129155
*/
130-
public static Long[] getJobIds(IProject project) {
156+
public static boolean removeJobId(IProject project, long jobId) {
157+
boolean success = false;
131158
synchronized (JobsContainer.jobMonitor) {
132159
JobsContainer jobsContainer = readJobsContainer(project);
133-
return jobsContainer.getJobIds();
160+
jobsContainer.removeJobId(jobId);
161+
success = writeJobsContainer(project, jobsContainer);
134162
}
163+
return success;
135164
}
136165

137-
private static JobsContainer readJobsContainer(IProject project) {
166+
/**
167+
* Retrieves the current job container for the given project. In case the
168+
* file does not exist or an error occurs while reading it an empty
169+
* container is returned.
170+
*
171+
* @param project
172+
* the project the container should be retrieved for
173+
* @return the corresponding job container or an empty one
174+
*/
175+
public static JobsContainer readJobsContainer(IProject project) {
138176
String fileName = project.getFile(FileManager.JOBS_CONTAINER_FILENAME).getLocation().toString();
139177
File file = new File(fileName);
140178
JobsContainer jobsContainer = new JobsContainer();

org.spotter.eclipse.ui/src/org/spotter/eclipse/ui/navigator/FixedOrderViewerComparator.java

-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ private String getLabel(Viewer viewer, Object e1) {
7575
IBaseLabelProvider prov = ((ContentViewer) viewer).getLabelProvider();
7676
if (prov instanceof ILabelProvider) {
7777
ILabelProvider lprov = (ILabelProvider) prov;
78-
// TODO: convert between timestamp and nice date representation
79-
// for SpotterProjectRunResult elements
8078
name1 = lprov.getText(e1);
8179
} else {
8280
name1 = e1.toString();

org.spotter.eclipse.ui/src/org/spotter/eclipse/ui/navigator/SpotterProjectResults.java

+72-17
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,27 @@
1616
package org.spotter.eclipse.ui.navigator;
1717

1818
import java.io.File;
19+
import java.io.IOException;
20+
import java.text.SimpleDateFormat;
1921
import java.util.ArrayList;
22+
import java.util.Date;
2023
import java.util.List;
2124

2225
import org.eclipse.core.resources.IFolder;
2326
import org.eclipse.core.resources.IProject;
2427
import org.eclipse.core.resources.IResource;
2528
import org.eclipse.core.runtime.CoreException;
2629
import org.eclipse.swt.graphics.Image;
30+
import org.lpe.common.util.LpeFileUtils;
2731
import org.slf4j.Logger;
2832
import org.slf4j.LoggerFactory;
2933
import org.spotter.eclipse.ui.Activator;
34+
import org.spotter.eclipse.ui.ServiceClientWrapper;
35+
import org.spotter.eclipse.ui.jobs.JobsContainer;
36+
import org.spotter.eclipse.ui.util.DialogUtils;
3037
import org.spotter.shared.configuration.FileManager;
38+
import org.spotter.shared.result.ResultsLocationConstants;
39+
import org.spotter.shared.result.model.ResultsContainer;
3140

3241
/**
3342
* An element that represents the results node.
@@ -125,39 +134,85 @@ public void refreshChildren() {
125134
}
126135

127136
private ISpotterProjectElement[] initializeChildren(IProject iProject) {
128-
String defaultResultsDir = FileManager.DEFAULT_RESULTS_DIR_NAME;
129-
IFolder resDir = iProject.getFolder(defaultResultsDir);
137+
IFolder resDir = iProject.getFolder(FileManager.DEFAULT_RESULTS_DIR_NAME);
130138

131139
if (!resDir.isSynchronized(IResource.DEPTH_INFINITE)) {
132140
try {
133141
resDir.refreshLocal(IResource.DEPTH_INFINITE, null);
134142
} catch (CoreException e) {
135-
LOGGER.warn("Failed to refresh results directory");
143+
String msg = "Failed to refresh results directory.";
144+
LOGGER.warn(msg);
145+
DialogUtils.openWarning(msg);
136146
return SpotterProjectParent.NO_CHILDREN;
137147
}
138148
}
139149

140-
File res = new File(resDir.getLocation().toString());
141-
List<File> runFolders = new ArrayList<>();
142-
ISpotterProjectElement[] elements = SpotterProjectParent.NO_CHILDREN;
150+
return synchronizeRunResults(iProject, resDir.getLocation().toString());
151+
}
152+
153+
private ISpotterProjectElement[] synchronizeRunResults(IProject iProject, String resultsLocation) {
154+
File res = new File(resultsLocation);
155+
List<ISpotterProjectElement> elements = new ArrayList<>();
156+
ServiceClientWrapper client = Activator.getDefault().getClient(iProject.getName());
157+
158+
if (!res.exists() || !res.isDirectory()) {
159+
DialogUtils.openWarning("The project's results folder is missing or corrupted!");
160+
} else {
161+
boolean connected = client.testConnection(false);
162+
if (!connected) {
163+
DialogUtils.openAsyncWarning("No connection to DS service! New results cannot be fetched from the server.");
164+
}
165+
JobsContainer jobsContainer = JobsContainer.readJobsContainer(iProject);
143166

144-
if (res.exists() && res.isDirectory()) {
145-
File[] files = res.listFiles();
146-
for (File file : files) {
147-
if (file.isDirectory()) {
148-
runFolders.add(file);
167+
for (Long jobId : jobsContainer.getJobIds()) {
168+
SpotterProjectRunResult runResult = processJobId(jobId, connected, client, jobsContainer,
169+
resultsLocation, iProject);
170+
if (runResult != null) {
171+
elements.add(runResult);
149172
}
150173
}
174+
}
175+
176+
return elements.toArray(new ISpotterProjectElement[elements.size()]);
177+
}
178+
179+
private SpotterProjectRunResult processJobId(Long jobId, boolean connected, ServiceClientWrapper client,
180+
JobsContainer jobsContainer, String resultsLocation, IProject iProject) {
181+
if (connected && client.isRunning(true) && jobId.equals(client.getCurrentJobId())) {
182+
LOGGER.debug("Ignore job " + jobId + " because it is currently running");
183+
return null;
184+
}
151185

152-
elements = new ISpotterProjectElement[runFolders.size()];
153-
int i = 0;
154-
for (File runFolder : runFolders) {
155-
IFolder runResultFolder = iProject.getFolder(defaultResultsDir + File.separator + runFolder.getName());
156-
elements[i++] = new SpotterProjectRunResult(this, runFolder.getName(), runResultFolder);
186+
Long timestamp = jobsContainer.getTimestamp(jobId);
187+
SimpleDateFormat dateFormat = new SimpleDateFormat("yy-MM-dd_HH-mm-ss-SSS");
188+
String formattedTimestamp = dateFormat.format(new Date(timestamp));
189+
190+
String fileName = resultsLocation + "/" + formattedTimestamp;
191+
File file = new File(fileName);
192+
boolean success = file.exists();
193+
if (!success && connected) {
194+
// try to fetch data from server
195+
ResultsContainer resultsContainer = client.requestResults(jobId.toString());
196+
if (resultsContainer != null && file.mkdir()) {
197+
String resultsFile = fileName + "/" + ResultsLocationConstants.RESULTS_SERIALIZATION_FILE_NAME;
198+
try {
199+
LpeFileUtils.writeObject(resultsFile, resultsContainer);
200+
success = true;
201+
} catch (IOException e) {
202+
String msg = "Error while saving fetched results for job " + jobId + "!";
203+
DialogUtils.openError(msg);
204+
LOGGER.error(msg + " Cause: {}", e.toString());
205+
}
157206
}
158207
}
159208

160-
return elements;
209+
if (success) {
210+
IFolder runResultFolder = iProject.getFolder(FileManager.DEFAULT_RESULTS_DIR_NAME + "/"
211+
+ formattedTimestamp);
212+
return new SpotterProjectRunResult(this, jobId, timestamp, runResultFolder);
213+
} else {
214+
return null;
215+
}
161216
}
162217

163218
}

org.spotter.eclipse.ui/src/org/spotter/eclipse/ui/navigator/SpotterProjectRunResult.java

+26-9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.eclipse.ui.PartInitException;
2929
import org.eclipse.ui.PlatformUI;
3030
import org.spotter.eclipse.ui.Activator;
31+
import org.spotter.eclipse.ui.jobs.JobsContainer;
3132
import org.spotter.eclipse.ui.util.DialogUtils;
3233
import org.spotter.eclipse.ui.view.ResultsView;
3334

@@ -47,31 +48,35 @@ public class SpotterProjectRunResult implements IOpenableProjectElement, IDeleta
4748
private final ISpotterProjectElement parent;
4849
private final IFolder resultFolder;
4950
private Image image;
51+
private final long jobId;
52+
private final long timestamp;
5053
private final String elementName;
5154

5255
/**
5356
* Creates a new instance of this element.
5457
*
5558
* @param parent
5659
* the parent element
57-
* @param elementName
58-
* the name of the element
60+
* @param jobId
61+
* the corresponding job id of this run result
62+
* @param timestamp
63+
* the corresponding timestamp of this run result
5964
* @param resultFolder
6065
* the result folder that is represented by this node
6166
*/
62-
public SpotterProjectRunResult(ISpotterProjectElement parent, String elementName, IFolder resultFolder) {
67+
public SpotterProjectRunResult(ISpotterProjectElement parent, long jobId, long timestamp, IFolder resultFolder) {
6368
this.parent = parent;
64-
this.elementName = elementName;
69+
this.jobId = jobId;
70+
this.timestamp = timestamp;
71+
72+
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd (HH:mm:ss)");
73+
this.elementName = dateFormat.format(new Date(timestamp));
74+
6575
this.resultFolder = resultFolder;
6676
}
6777

6878
@Override
6979
public String getText() {
70-
long timestamp = System.currentTimeMillis(); // TODO: replaced later by saved timestamp
71-
Date date = new Date(timestamp);
72-
SimpleDateFormat dateFormat = new SimpleDateFormat("yy-MM-dd (HH:mm:ss)");
73-
String readableTimestamp = dateFormat.format(date);
74-
//return readableTimestamp;
7580
return elementName;
7681
}
7782

@@ -84,6 +89,13 @@ public Image getImage() {
8489
return image;
8590
}
8691

92+
/**
93+
* @return the corresponding timestamp of this run result
94+
*/
95+
public long getTimestamp() {
96+
return timestamp;
97+
}
98+
8799
/**
88100
* @return the result folder this element is linked to
89101
*/
@@ -156,6 +168,11 @@ public void delete() {
156168

157169
ResultsView.reset(resultFolder);
158170
resultFolder.delete(true, null);
171+
// clear job id
172+
if (!JobsContainer.removeJobId(getProject(), jobId)) {
173+
DialogUtils
174+
.openError("There was an error while updating the project's job ids. The results of the corresponding id will be fetched again.");
175+
}
159176
// update navigator viewer
160177
((SpotterProjectResults) getParent()).refreshChildren();
161178
TreeViewer viewer = Activator.getDefault().getNavigatorViewer();

0 commit comments

Comments
 (0)