Skip to content

Commit

Permalink
Add automatic fetch of results in navigator (sopeco#116)
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
DenisKnoepfle committed Oct 14, 2014
1 parent 8b973e9 commit 72c07c1
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ public class DynamicSpotterRunJob extends Job {

private final IProject project;
private final long jobId;
private final long timestamp;
private final Set<String> processedProblems;
private Map.Entry<String, DiagnosisProgress> currentProblem;

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

this.project = project;
this.jobId = jobId;
this.timestamp = timestamp;
this.processedProblems = new HashSet<>();

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

if (!JobsContainer.registerJobId(project, jobId)) {
if (!JobsContainer.registerJobId(project, jobId, timestamp)) {
DialogUtils.openError(RunHandler.DIALOG_TITLE,
"There was an error when saving the job id. You may not access the results of the diagnosis run.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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

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

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

/**
* Returns the timestamp that corresponds to the given job id.
*
* @param jobId
* the job id the timestamp shall be returned for
* @return the corresponding timestamp
*/
public Long getTimestamp(Long jobId) {
if (!jobIds.contains(jobId)) {
throw new IllegalArgumentException("The given job id is not registered");
}
return timestamps.get(jobId);
}

/**
* Returns an array of all stored job ids.
*
Expand All @@ -79,9 +96,12 @@ public int count() {
*
* @param jobId
* the id to add
* @param timestamp
* the corresponding timestamp
*/
public void addJobId(Long jobId) {
public void addJobId(Long jobId, Long timestamp) {
jobIds.add(jobId);
timestamps.put(jobId, timestamp);
}

/**
Expand All @@ -91,13 +111,15 @@ public void addJobId(Long jobId) {
* the id to remove
*/
public void removeJobId(Long jobId) {
timestamps.remove(jobId);
jobIds.remove(jobId);
}

/**
* Clears all job ids.
*/
public void reset() {
timestamps.clear();
jobIds.clear();
}

Expand All @@ -108,33 +130,49 @@ public void reset() {
* the project the id belongs to
* @param jobId
* the id to register
* @param timestamp
* the corresponding timestamp
* @return <code>true</code> on success, otherwise <code>false</code>
*/
public static boolean registerJobId(IProject project, long jobId) {
public static boolean registerJobId(IProject project, long jobId, long timestamp) {
boolean success = false;
synchronized (JobsContainer.jobMonitor) {
JobsContainer jobsContainer = readJobsContainer(project);
jobsContainer.addJobId(jobId);
jobsContainer.addJobId(jobId, timestamp);
success = writeJobsContainer(project, jobsContainer);
}
return success;
}

/**
* Returns the job ids that belong to the given project.
* Removes the given job id for the project.
*
* @param project
* the project whose job ids should be returned
* @return array of related job ids
* the project the id belongs to
* @param jobId
* the id to remove
* @return <code>true</code> on success, otherwise <code>false</code>
*/
public static Long[] getJobIds(IProject project) {
public static boolean removeJobId(IProject project, long jobId) {
boolean success = false;
synchronized (JobsContainer.jobMonitor) {
JobsContainer jobsContainer = readJobsContainer(project);
return jobsContainer.getJobIds();
jobsContainer.removeJobId(jobId);
success = writeJobsContainer(project, jobsContainer);
}
return success;
}

private static JobsContainer readJobsContainer(IProject project) {
/**
* Retrieves the current job container for the given project. In case the
* file does not exist or an error occurs while reading it an empty
* container is returned.
*
* @param project
* the project the container should be retrieved for
* @return the corresponding job container or an empty one
*/
public static JobsContainer readJobsContainer(IProject project) {
String fileName = project.getFile(FileManager.JOBS_CONTAINER_FILENAME).getLocation().toString();
File file = new File(fileName);
JobsContainer jobsContainer = new JobsContainer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ private String getLabel(Viewer viewer, Object e1) {
IBaseLabelProvider prov = ((ContentViewer) viewer).getLabelProvider();
if (prov instanceof ILabelProvider) {
ILabelProvider lprov = (ILabelProvider) prov;
// TODO: convert between timestamp and nice date representation
// for SpotterProjectRunResult elements
name1 = lprov.getText(e1);
} else {
name1 = e1.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,27 @@
package org.spotter.eclipse.ui.navigator;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.swt.graphics.Image;
import org.lpe.common.util.LpeFileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spotter.eclipse.ui.Activator;
import org.spotter.eclipse.ui.ServiceClientWrapper;
import org.spotter.eclipse.ui.jobs.JobsContainer;
import org.spotter.eclipse.ui.util.DialogUtils;
import org.spotter.shared.configuration.FileManager;
import org.spotter.shared.result.ResultsLocationConstants;
import org.spotter.shared.result.model.ResultsContainer;

/**
* An element that represents the results node.
Expand Down Expand Up @@ -125,39 +134,85 @@ public void refreshChildren() {
}

private ISpotterProjectElement[] initializeChildren(IProject iProject) {
String defaultResultsDir = FileManager.DEFAULT_RESULTS_DIR_NAME;
IFolder resDir = iProject.getFolder(defaultResultsDir);
IFolder resDir = iProject.getFolder(FileManager.DEFAULT_RESULTS_DIR_NAME);

if (!resDir.isSynchronized(IResource.DEPTH_INFINITE)) {
try {
resDir.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
LOGGER.warn("Failed to refresh results directory");
String msg = "Failed to refresh results directory.";
LOGGER.warn(msg);
DialogUtils.openWarning(msg);
return SpotterProjectParent.NO_CHILDREN;
}
}

File res = new File(resDir.getLocation().toString());
List<File> runFolders = new ArrayList<>();
ISpotterProjectElement[] elements = SpotterProjectParent.NO_CHILDREN;
return synchronizeRunResults(iProject, resDir.getLocation().toString());
}

private ISpotterProjectElement[] synchronizeRunResults(IProject iProject, String resultsLocation) {
File res = new File(resultsLocation);
List<ISpotterProjectElement> elements = new ArrayList<>();
ServiceClientWrapper client = Activator.getDefault().getClient(iProject.getName());

if (!res.exists() || !res.isDirectory()) {
DialogUtils.openWarning("The project's results folder is missing or corrupted!");
} else {
boolean connected = client.testConnection(false);
if (!connected) {
DialogUtils.openAsyncWarning("No connection to DS service! New results cannot be fetched from the server.");
}
JobsContainer jobsContainer = JobsContainer.readJobsContainer(iProject);

if (res.exists() && res.isDirectory()) {
File[] files = res.listFiles();
for (File file : files) {
if (file.isDirectory()) {
runFolders.add(file);
for (Long jobId : jobsContainer.getJobIds()) {
SpotterProjectRunResult runResult = processJobId(jobId, connected, client, jobsContainer,
resultsLocation, iProject);
if (runResult != null) {
elements.add(runResult);
}
}
}

return elements.toArray(new ISpotterProjectElement[elements.size()]);
}

private SpotterProjectRunResult processJobId(Long jobId, boolean connected, ServiceClientWrapper client,
JobsContainer jobsContainer, String resultsLocation, IProject iProject) {
if (connected && client.isRunning(true) && jobId.equals(client.getCurrentJobId())) {
LOGGER.debug("Ignore job " + jobId + " because it is currently running");
return null;
}

elements = new ISpotterProjectElement[runFolders.size()];
int i = 0;
for (File runFolder : runFolders) {
IFolder runResultFolder = iProject.getFolder(defaultResultsDir + File.separator + runFolder.getName());
elements[i++] = new SpotterProjectRunResult(this, runFolder.getName(), runResultFolder);
Long timestamp = jobsContainer.getTimestamp(jobId);
SimpleDateFormat dateFormat = new SimpleDateFormat("yy-MM-dd_HH-mm-ss-SSS");
String formattedTimestamp = dateFormat.format(new Date(timestamp));

String fileName = resultsLocation + "/" + formattedTimestamp;
File file = new File(fileName);
boolean success = file.exists();
if (!success && connected) {
// try to fetch data from server
ResultsContainer resultsContainer = client.requestResults(jobId.toString());
if (resultsContainer != null && file.mkdir()) {
String resultsFile = fileName + "/" + ResultsLocationConstants.RESULTS_SERIALIZATION_FILE_NAME;
try {
LpeFileUtils.writeObject(resultsFile, resultsContainer);
success = true;
} catch (IOException e) {
String msg = "Error while saving fetched results for job " + jobId + "!";
DialogUtils.openError(msg);
LOGGER.error(msg + " Cause: {}", e.toString());
}
}
}

return elements;
if (success) {
IFolder runResultFolder = iProject.getFolder(FileManager.DEFAULT_RESULTS_DIR_NAME + "/"
+ formattedTimestamp);
return new SpotterProjectRunResult(this, jobId, timestamp, runResultFolder);
} else {
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.spotter.eclipse.ui.Activator;
import org.spotter.eclipse.ui.jobs.JobsContainer;
import org.spotter.eclipse.ui.util.DialogUtils;
import org.spotter.eclipse.ui.view.ResultsView;

Expand All @@ -47,31 +48,35 @@ public class SpotterProjectRunResult implements IOpenableProjectElement, IDeleta
private final ISpotterProjectElement parent;
private final IFolder resultFolder;
private Image image;
private final long jobId;
private final long timestamp;
private final String elementName;

/**
* Creates a new instance of this element.
*
* @param parent
* the parent element
* @param elementName
* the name of the element
* @param jobId
* the corresponding job id of this run result
* @param timestamp
* the corresponding timestamp of this run result
* @param resultFolder
* the result folder that is represented by this node
*/
public SpotterProjectRunResult(ISpotterProjectElement parent, String elementName, IFolder resultFolder) {
public SpotterProjectRunResult(ISpotterProjectElement parent, long jobId, long timestamp, IFolder resultFolder) {
this.parent = parent;
this.elementName = elementName;
this.jobId = jobId;
this.timestamp = timestamp;

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd (HH:mm:ss)");
this.elementName = dateFormat.format(new Date(timestamp));

this.resultFolder = resultFolder;
}

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

Expand All @@ -84,6 +89,13 @@ public Image getImage() {
return image;
}

/**
* @return the corresponding timestamp of this run result
*/
public long getTimestamp() {
return timestamp;
}

/**
* @return the result folder this element is linked to
*/
Expand Down Expand Up @@ -156,6 +168,11 @@ public void delete() {

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

0 comments on commit 72c07c1

Please sign in to comment.