Skip to content
Snippets Groups Projects
Commit d3533a0b authored by Jan Kožusznik's avatar Jan Kožusznik
Browse files

Merge branch 'iss1026-changeInputOutputDir'

Conflicts:
	haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java
	haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java
	haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java
parents a3ac7c58 25866b14
No related branches found
No related tags found
No related merge requests found
Showing
with 550 additions and 126 deletions
......@@ -5,12 +5,14 @@ import java.io.InputStream;
import java.io.InterruptedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
......@@ -29,8 +31,10 @@ import cz.it4i.fiji.haas_java_client.ProgressNotifier;
import cz.it4i.fiji.haas_java_client.TransferFileProgressForHaaSClient;
import cz.it4i.fiji.haas_java_client.UploadingFile;
import cz.it4i.fiji.scpclient.TransferFileProgress;
/***
* TASK - napojit na UI
* TASK - napojit na UI
*
* @author koz01
*
*/
......@@ -52,13 +56,19 @@ public class Job {
private static final String JOB_INFO_FILENAME = ".jobinfo";
private static final String JOB_NEEDS_DOWNLOAD = "job.needs_download";
private static final String JOB_CAN_BE_DOWNLOADED = "job.can_be_downloaded";
private static final String JOB_IS_DOWNLOADED = "job.downloaded";
private static final String JOB_IS_UPLOADED = "job.uploaded";
private static final String JOB_OUTPUT_DIRECTORY_PATH = "job.output_directory_path";
private static final String JOB_INPUT_DIRECTORY_PATH = "job.input_directory_path";
private static final String JOB_USE_DEMO_DATA = "job.use_demo_data";
private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.Job.class);
private Path jobDir;
......@@ -66,41 +76,50 @@ public class Job {
private final Supplier<HaaSClient> haasClientSupplier;
private JobInfo jobInfo;
private Long jobId;
private PropertyHolder propertyHolder;
private final JobManager4Job jobManager;
private Synchronization synchronization;
private Path inputDirectory;
private Path outputDirectory;
private boolean useDemoData;
public Job(JobManager4Job jobManager, String name, Path basePath, Supplier<HaaSClient> haasClientSupplier)
public Job(JobManager4Job jobManager, String name, Path basePath, Supplier<HaaSClient> haasClientSupplier,
Function<Path, Path> inputDirectoryProvider, Function<Path, Path> outputDirectoryProvider)
throws IOException {
this(jobManager, haasClientSupplier);
HaaSClient client = getHaaSClient();
long id = client.createJob(name, Collections.emptyList());
setJobDirectory(basePath.resolve("" + id));
setJobDirectory(basePath.resolve("" + id), inputDirectoryProvider, outputDirectoryProvider);
propertyHolder = new PropertyHolder(jobDir.resolve(JOB_INFO_FILENAME));
Files.createDirectory(jobDir);
Files.createDirectory(this.jobDir);
storeInputOutputDirectory();
setName(name);
}
public Job(JobManager4Job jobManager, Path jobDirectory, Supplier<HaaSClient> haasClientSupplier) {
this(jobManager, haasClientSupplier);
setJobDirectory(jobDirectory);
propertyHolder = new PropertyHolder(jobDir.resolve(JOB_INFO_FILENAME));
propertyHolder = new PropertyHolder(jobDirectory.resolve(JOB_INFO_FILENAME));
useDemoData = getSafeBoolean(propertyHolder.getValue(JOB_USE_DEMO_DATA));
setJobDirectory(jobDirectory, jd -> useDemoData ? null : getDataDirectory(JOB_INPUT_DIRECTORY_PATH, jd),
jd -> getDataDirectory(JOB_OUTPUT_DIRECTORY_PATH, jd));
}
private Job(JobManager4Job jobManager, Supplier<HaaSClient> haasClientSupplier) {
this.haasClientSupplier = haasClientSupplier;
this.jobManager = jobManager;
}
public void startUploadData() {
setProperty(JOB_NEEDS_UPLOAD, true);
try {
......@@ -127,7 +146,7 @@ public class Job {
.collect(Collectors.toList());
synchronization.startDownload(files);
}
public void stopDownloadData() {
setProperty(JOB_NEEDS_DOWNLOAD, false);
try {
......@@ -137,14 +156,12 @@ public class Job {
throw new RuntimeException(e);
}
}
public synchronized void resumeUpload() {
if (needsUpload()) {
synchronization.resumeUpload();
}
}
public synchronized void resumeDownload() {
if (needsDownload()) {
......@@ -152,11 +169,10 @@ public class Job {
}
}
public boolean canBeDownloaded() {
return Boolean.parseBoolean(getProperty(JOB_CAN_BE_DOWNLOADED));
}
public void setUploaded(boolean b) {
setProperty(JOB_IS_UPLOADED, b);
}
......@@ -164,23 +180,23 @@ public class Job {
public void setDownloaded(boolean b) {
setProperty(JOB_IS_DOWNLOADED, b);
}
public boolean isUploaded() {
return getSafeBoolean(getProperty(JOB_IS_UPLOADED));
return getSafeBoolean(getProperty(JOB_IS_UPLOADED));
}
public boolean isDownloaded() {
return getSafeBoolean(getProperty(JOB_IS_DOWNLOADED));
}
public boolean needsDownload() {
return Boolean.parseBoolean(getProperty(JOB_NEEDS_DOWNLOAD));
}
public boolean needsUpload() {
return Boolean.parseBoolean(getProperty(JOB_NEEDS_UPLOAD));
}
public void uploadFile(String file, ProgressNotifier notifier) {
uploadFiles(Arrays.asList(file), notifier);
}
......@@ -224,14 +240,16 @@ public class Job {
setCanBeDownloaded(true);
}
synchronized public long getId() {
if (jobId == null) {
jobId = getJobId(jobDir);
}
return jobId;
}
public boolean isUseDemoData() {
return useDemoData;
}
public Path storeDataInWorkdirectory(UploadingFile uploadingFile) throws IOException {
Path result;
......@@ -242,8 +260,10 @@ public class Job {
}
synchronized public void download(Predicate<String> predicate, ProgressNotifier notifier) {
List<String> files = getHaaSClient().getChangedFiles(jobId).stream().filter(predicate).collect(Collectors.toList());
try (HaaSFileTransfer transfer = haasClientSupplier.get().startFileTransfer(getId(), HaaSClient.DUMMY_TRANSFER_FILE_PROGRESS)) {
List<String> files = getHaaSClient().getChangedFiles(jobId).stream().filter(predicate)
.collect(Collectors.toList());
try (HaaSFileTransfer transfer = haasClientSupplier.get().startFileTransfer(getId(),
HaaSClient.DUMMY_TRANSFER_FILE_PROGRESS)) {
List<Long> fileSizes;
try {
fileSizes = transfer.obtainSize(files);
......@@ -369,20 +389,44 @@ public class Job {
public void setUploadNotifier(ProgressNotifier notifier) {
synchronization.setUploadNotifier(notifier);
}
public void close() {
synchronization.close();
}
private void storeInputOutputDirectory() {
if (inputDirectory == null) {
useDemoData = true;
propertyHolder.setValue(JOB_USE_DEMO_DATA, "" + useDemoData);
} else {
storeDataDirectory(JOB_INPUT_DIRECTORY_PATH, inputDirectory);
}
storeDataDirectory(JOB_OUTPUT_DIRECTORY_PATH, outputDirectory);
}
private void storeDataDirectory(String directoryPropertyName, Path directory) {
if (!jobDir.equals(directory)) {
propertyHolder.setValue(directoryPropertyName, directory.toString());
}
}
private Path getDataDirectory(String typeOfDirectory, Path jobDirectory) {
String directory = propertyHolder.getValue(typeOfDirectory);
return directory != null ? Paths.get(directory) : jobDirectory;
}
private boolean getSafeBoolean(String value) {
return value != null ? Boolean.parseBoolean(value) : false;
}
private void setJobDirectory(Path jobDirectory) {
private void setJobDirectory(Path jobDirectory, Function<Path, Path> inputDirectoryProvider,
Function<Path, Path> outputDirectoryProvider) {
this.jobDir = jobDirectory;
try {
this.synchronization = new Synchronization(() -> startFileTransfer(HaaSClient.DUMMY_TRANSFER_FILE_PROGRESS),
jobDir, () -> {
jobDir, this.inputDirectory = inputDirectoryProvider.apply(jobDir),
this.outputDirectory = outputDirectoryProvider.apply(jobDir), () -> {
setProperty(JOB_NEEDS_UPLOAD, false);
setUploaded(true);
}, () -> {
......@@ -396,14 +440,10 @@ public class Job {
}
}
private HaaSFileTransfer startFileTransfer( TransferFileProgress progress) {
private HaaSFileTransfer startFileTransfer(TransferFileProgress progress) {
return haasClientSupplier.get().startFileTransfer(getId(), progress);
}
private void setName(String name) {
setProperty(JOB_NAME, name);
}
......@@ -426,7 +466,7 @@ public class Job {
private static long getJobId(Path path) {
return Long.parseLong(path.getFileName().toString());
}
private void setCanBeDownloaded(boolean b) {
setProperty(JOB_CAN_BE_DOWNLOADED, b);
}
......
......@@ -7,6 +7,7 @@ import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -45,10 +46,12 @@ public class JobManager implements Closeable {
this.settings = settings;
}
public Job createJob() throws IOException {
public Job createJob(Function<Path, Path> inputDirectoryProvider, Function<Path, Path> outputDirectoryProvider)
throws IOException {
Job result;
initJobsIfNecessary();
jobs.add(result = new Job(remover, settings.getJobName(), workDirectory, this::getHaasClient));
jobs.add(result = new Job(remover, settings.getJobName(), workDirectory, this::getHaasClient,
inputDirectoryProvider, outputDirectoryProvider));
return result;
}
......
......@@ -6,12 +6,12 @@ import java.io.InterruptedIOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
......@@ -24,20 +24,22 @@ import cz.it4i.fiji.haas_java_client.ProgressNotifier;
import cz.it4i.fiji.haas_java_client.UploadingFile;
import cz.it4i.fiji.haas_java_client.UploadingFileImpl;
public class Synchronization implements Closeable{
public class Synchronization implements Closeable {
public static final Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.data_transfer.Synchronization.class);
private static final String FILE_INDEX_TO_UPLOAD_FILENAME = ".toUploadFiles";
private static final String FILE_INDEX_TO_DOWNLOAD_FILENAME = ".toDownloadFiles";
private static final String FILE_INDEX_DOWNLOADED_FILENAME = ".downloaded";
private final Path workingDirectory;
private final Function<String,Path> pathResolver;
private final Path inputDirectory;
private final Path outputDirectory;
private final PersistentIndex<Path> filesDownloaded;
private final PersistentSynchronizationProcess<Path> uploadProcess;
......@@ -45,14 +47,22 @@ public class Synchronization implements Closeable{
private final P_PersistentDownloadProcess downloadProcess;
private final ExecutorService service;
// public Synchronization(Supplier<HaaSFileTransfer> fileTransferSupplier, Path workingDirectory,
// Runnable uploadFinishedNotifier, Runnable downloadFinishedNotifier) throws IOException {
// this(fileTransferSupplier, workingDirectory, workingDirectory, workingDirectory, uploadFinishedNotifier,
// downloadFinishedNotifier);
// }
public Synchronization(Supplier<HaaSFileTransfer> fileTransferSupplier, Path workingDirectory,
Runnable uploadFinishedNotifier, Runnable downloadFinishedNotifier) throws IOException {
this.service = Executors.newFixedThreadPool(2);
public Synchronization(Supplier<HaaSFileTransfer> fileTransferSupplier, Path workingDirectory, Path inputDirectory,
Path outputDirectory, Runnable uploadFinishedNotifier, Runnable downloadFinishedNotifier)
throws IOException {
this.workingDirectory = workingDirectory;
this.pathResolver = name -> workingDirectory.resolve(name);
this.inputDirectory = inputDirectory;
this.outputDirectory = outputDirectory;
this.service = Executors.newFixedThreadPool(2);
this.filesDownloaded = new PersistentIndex<>(workingDirectory.resolve(FILE_INDEX_DOWNLOADED_FILENAME),
pathResolver);
name -> Paths.get(name));
this.uploadProcess = createUploadProcess(fileTransferSupplier, service, uploadFinishedNotifier);
this.downloadProcess = createDownloadProcess(fileTransferSupplier, service, downloadFinishedNotifier);
}
......@@ -60,16 +70,16 @@ public class Synchronization implements Closeable{
public synchronized void setUploadNotifier(ProgressNotifier notifier) {
uploadProcess.setNotifier(notifier);
}
public void setDownloadNotifier(ProgressNotifier notifier) {
downloadProcess.setNotifier(notifier);
}
public synchronized void startUpload() throws IOException {
uploadProcess.start();
}
public void stopUpload() throws IOException {
uploadProcess.stop();
}
......@@ -77,16 +87,16 @@ public class Synchronization implements Closeable{
public void resumeUpload() {
uploadProcess.resume();
}
public synchronized void startDownload(Collection<String> files) throws IOException {
this.downloadProcess.setItems(files);
this.downloadProcess.start();
}
public synchronized void stopDownload() throws IOException {
this.downloadProcess.stop();
}
public synchronized void resumeDownload() {
this.downloadProcess.resume();
}
......@@ -99,23 +109,24 @@ public class Synchronization implements Closeable{
}
private boolean canUpload(Path file) {
return !file.getFileName().toString().matches("[.][^.]+") && !filesDownloaded.contains(file);
}
private PersistentSynchronizationProcess<Path> createUploadProcess(Supplier<HaaSFileTransfer> fileTransferSupplier,
ExecutorService service, Runnable uploadFinishedNotifier) throws IOException {
return new PersistentSynchronizationProcess<Path>(service, fileTransferSupplier, uploadFinishedNotifier,
workingDirectory.resolve(FILE_INDEX_TO_UPLOAD_FILENAME), pathResolver) {
workingDirectory.resolve(FILE_INDEX_TO_UPLOAD_FILENAME), name -> inputDirectory.resolve(name)) {
@Override
protected Iterable<Path> getItems() throws IOException {
try(DirectoryStream<Path> ds = Files.newDirectoryStream(workingDirectory,Synchronization.this::canUpload)) {
return StreamSupport.stream(ds.spliterator(), false).collect(Collectors.toList());
try (DirectoryStream<Path> ds = Files.newDirectoryStream(inputDirectory,
Synchronization.this::canUpload)) {
return StreamSupport.stream(ds.spliterator(), false).collect(Collectors.toList());
}
}
@Override
protected void processItem(HaaSFileTransfer tr, Path p) throws InterruptedIOException {
UploadingFile uf = new UploadingFileImpl(p);
......@@ -124,29 +135,28 @@ public class Synchronization implements Closeable{
@Override
protected long getTotalSize(Iterable<Path> items, HaaSFileTransfer tr) {
return StreamSupport.stream(items.spliterator(), false).map(p->{
return StreamSupport.stream(items.spliterator(), false).map(p -> {
try {
return Files.size(p);
} catch (IOException e) {
log.error(e.getMessage(), e);
return 0;
return 0;
}
}).collect(Collectors.summingLong(val->val.longValue()));
}).collect(Collectors.summingLong(val -> val.longValue()));
}
};
}
private P_PersistentDownloadProcess createDownloadProcess(
Supplier<HaaSFileTransfer> fileTransferSupplier, ExecutorService service,
Runnable uploadFinishedNotifier) throws IOException {
private P_PersistentDownloadProcess createDownloadProcess(Supplier<HaaSFileTransfer> fileTransferSupplier,
ExecutorService service, Runnable uploadFinishedNotifier) throws IOException {
return new P_PersistentDownloadProcess(service, fileTransferSupplier, uploadFinishedNotifier);
}
private class P_PersistentDownloadProcess extends PersistentSynchronizationProcess<String>{
private class P_PersistentDownloadProcess extends PersistentSynchronizationProcess<String> {
private Collection<String> items = Collections.emptyList();
public P_PersistentDownloadProcess(ExecutorService service, Supplier<HaaSFileTransfer> fileTransferSupplier,
Runnable processFinishedNotifier) throws IOException {
super(service, fileTransferSupplier, processFinishedNotifier,
......@@ -156,7 +166,7 @@ public class Synchronization implements Closeable{
private synchronized void setItems(Collection<String> items) {
this.items = new LinkedList<>(items);
}
@Override
protected synchronized Iterable<String> getItems() throws IOException {
return items;
......@@ -164,19 +174,20 @@ public class Synchronization implements Closeable{
@Override
protected void processItem(HaaSFileTransfer tr, String file) throws InterruptedIOException {
filesDownloaded.insert(workingDirectory.resolve(file));
filesDownloaded.insert(outputDirectory.resolve(file));
try {
filesDownloaded.storeToWorkingFile();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
tr.download(file, workingDirectory);
tr.download(file, outputDirectory);
}
@Override
protected long getTotalSize(Iterable<String> items, HaaSFileTransfer tr) throws InterruptedIOException {
return tr.obtainSize( StreamSupport.stream(items.spliterator(), false).collect(Collectors.toList())).stream().collect(Collectors.summingLong(val->val));
return tr.obtainSize(StreamSupport.stream(items.spliterator(), false).collect(Collectors.toList())).stream()
.collect(Collectors.summingLong(val -> val));
}
}
}
......@@ -30,16 +30,16 @@ public abstract class ObservableValueRegistry<K, V extends UpdatableObservableVa
};
}
public V addIfAbsent(K key) {
public synchronized V addIfAbsent(K key) {
V uov = map.computeIfAbsent(key, k -> constructObservableValue(k));
return uov;
}
public V get(K key) {
public synchronized V get(K key) {
return map.get(key);
}
public Collection<V> getAllItems() {
public synchronized Collection<V> getAllItems() {
return map.values().stream().map(val -> val).collect(Collectors.toList());
}
......
......@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
......@@ -48,9 +49,8 @@ import cz.it4i.fiji.haas_java_client.SynchronizableFileType;
import cz.it4i.fiji.haas_java_client.UploadingFile;
import net.imagej.updater.util.Progress;
public class BenchmarkJobManager implements Closeable{
public class BenchmarkJobManager implements Closeable {
private static Logger log = LoggerFactory
.getLogger(cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.class);
......@@ -59,7 +59,11 @@ public class BenchmarkJobManager implements Closeable{
public final class BenchmarkJob implements HaaSOutputHolder {
private final Job job;
public boolean isUseDemoData() {
return job.isUseDemoData();
}
private final List<Task> tasks;
private final List<BenchmarkError> nonTaskSpecificErrors;
private final SPIMComputationAccessor computationAccessor;
......@@ -84,14 +88,14 @@ public class BenchmarkJobManager implements Closeable{
}
public synchronized void startJob(Progress progress) throws IOException {
job.uploadFile(Constants.CONFIG_YAML, new P_ProgressNotifierAdapter(progress));
job.uploadFile(Constants.CONFIG_YAML, new P_ProgressNotifierAdapter(progress));
String outputName = getOutputName(job.openLocalFile(Constants.CONFIG_YAML));
verifiedState = null;
verifiedStateProcessed = false;
running = null;
job.submit();
job.setProperty(SPIM_OUTPUT_FILENAME_PATTERN, outputName);
}
public JobState getState() {
......@@ -106,7 +110,6 @@ public class BenchmarkJobManager implements Closeable{
job.stopUploadData();
}
public synchronized CompletableFuture<JobState> getStateAsync(Executor executor) {
if (running != null) {
return running;
......@@ -121,12 +124,12 @@ public class BenchmarkJobManager implements Closeable{
public void startDownload() throws IOException {
if (job.getState() == JobState.Finished) {
String filePattern = job.getProperty(SPIM_OUTPUT_FILENAME_PATTERN);
job.startDownload(downloadFinishedData(filePattern) );
job.startDownload(downloadFinishedData(filePattern));
} else if (job.getState() == JobState.Failed || job.getState() == JobState.Canceled) {
job.startDownload(downloadFailedData());
}
}
public boolean canBeDownloaded() {
return job.canBeDownloaded();
}
......@@ -250,6 +253,7 @@ public class BenchmarkJobManager implements Closeable{
public boolean needsUpload() {
return job.needsUpload();
}
@Override
public String toString() {
......@@ -413,7 +417,8 @@ public class BenchmarkJobManager implements Closeable{
private SPIMComputationAccessor getComputationAccessor() {
SPIMComputationAccessor result = new SPIMComputationAccessor() {
private final HaaSOutputHolder outputOfSnakemake = new HaaSOutputHolderImpl(list -> job.getOutput(list));
private final HaaSOutputHolder outputOfSnakemake = new HaaSOutputHolderImpl(
list -> job.getOutput(list));
@Override
public List<String> getActualOutput(List<SynchronizableFileType> content) {
......@@ -454,9 +459,12 @@ public class BenchmarkJobManager implements Closeable{
jobManager = new JobManager(params.workingDirectory(), constructSettingsFromParams(params));
}
public BenchmarkJob createJob() throws IOException {
Job job = jobManager.createJob();
job.storeDataInWorkdirectory(getUploadingFile());
public BenchmarkJob createJob(Function<Path, Path> inputDirectoryProvider,
Function<Path, Path> outputDirectoryProvider) throws IOException {
Job job = jobManager.createJob(inputDirectoryProvider, outputDirectoryProvider);
if (job.isUseDemoData()) {
job.storeDataInWorkdirectory(getConfigYamlFile());
}
return convertJob(job);
}
......@@ -570,7 +578,7 @@ public class BenchmarkJobManager implements Closeable{
jobManager.close();
}
private UploadingFile getUploadingFile() {
private UploadingFile getConfigYamlFile() {
return new UploadingFileFromResource("", Constants.CONFIG_YAML);
}
......
......@@ -3,6 +3,7 @@ package cz.it4i.fiji.haas_spim_benchmark.ui;
import java.awt.Desktop;
import java.awt.Window;
import java.io.IOException;
import java.nio.file.Path;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedList;
......@@ -50,21 +51,21 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
private TableView<ObservableBenchmarkJob> jobs;
private final BenchmarkJobManager manager;
private final ExecutorService executorServiceJobState = Executors.newWorkStealingPool();
private final Executor executorServiceFX = new FXFrameExecutorService();
private Window root;
private ExecutorService executorServiceUI;
private ExecutorService executorServiceWS;
private Timer timer;
private ObservableBenchmarkJobRegistry registry;
private static Logger log = LoggerFactory
.getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.BenchmarkSPIMController.class);
......@@ -102,7 +103,7 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
private void initMenu() {
TableViewContextMenu<ObservableBenchmarkJob> menu = new TableViewContextMenu<>(jobs);
menu.addItem("Create job", x -> executeWSCallAsync("Creating job", p -> manager.createJob()), j -> true);
menu.addItem("Create job", x -> askForCreateJob(), j -> true);
menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> {
job.getValue().startJob(p);
job.getValue().update();
......@@ -112,7 +113,8 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
menu.addItem("Cancel job", job -> executeWSCallAsync("Canceling job", p -> {
job.getValue().cancelJob();
job.getValue().update();
}), job -> JavaFXRoutines.notNullValue(job, j -> j.getState() == JobState.Running || j.getState() == JobState.Queued ));
}), job -> JavaFXRoutines.notNullValue(job,
j -> j.getState() == JobState.Running || j.getState() == JobState.Queued));
menu.addItem("Execution details", job -> {
try {
......@@ -127,15 +129,15 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
menu.addItem("Upload data", job -> executeWSCallAsync("Uploading data", p -> job.getValue().startUpload()),
job -> executeWSCallAsync("Stop uploading data", p -> job.getValue().stopUpload()),
job -> JavaFXRoutines.notNullValue(job,
j -> !EnumSet.of(JobState.Running, JobState.Disposed).contains(j.getState())),
j -> !j.isUseDemoData() && !EnumSet.of(JobState.Running, JobState.Disposed).contains(j.getState())),
job -> job.getUploadProgress().isWorking());
menu.addItem("Download result",
job -> executeWSCallAsync("Downloading data", p -> job.getValue().startDownload()),
job -> executeWSCallAsync("Stop downloading data", p -> job.getValue().stopDownload()),
job -> JavaFXRoutines.notNullValue(job,
j -> EnumSet.of(JobState.Failed, JobState.Finished, JobState.Canceled).contains(j.getState())
&& j.canBeDownloaded()),
job -> JavaFXRoutines
.notNullValue(job,
j -> EnumSet.of(JobState.Failed, JobState.Finished, JobState.Canceled)
.contains(j.getState()) && j.canBeDownloaded()),
job -> job.getDownloadProgress().isWorking());
menu.addItem("Download statistics",
......@@ -155,6 +157,24 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
registry.update();
}
private void askForCreateJob() {
NewJobWindow newJobWindow = new NewJobWindow(null);
ModalDialogs.doModal(newJobWindow, WindowConstants.DISPOSE_ON_CLOSE);
newJobWindow.setCreatePressedNotifier(() -> executeWSCallAsync("Creating job", false,p -> doCreateJob(wd -> newJobWindow.getInputDirectory(wd), wd -> newJobWindow.getOutputDirectory(wd))));
}
private void doCreateJob(Function<Path,Path> inputProvider, Function<Path,Path> outputProvider) throws IOException {
BenchmarkJob bj = manager.createJob(inputProvider, outputProvider);
ObservableBenchmarkJob obj = registry.addIfAbsent(bj);
addJobToItems(obj);
jobs.refresh();
}
private synchronized void addJobToItems(ObservableBenchmarkJob obj) {
jobs.getItems().add(obj);
}
private void open(BenchmarkJob j) {
executorServiceUI.execute(() -> {
Desktop desktop = Desktop.getDesktop();
......@@ -181,8 +201,9 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
}
return null;
}, x -> {
if (update)
if (update) {
updateJobs();
}
});
}
......@@ -208,11 +229,11 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
}
registry.update();
Set<ObservableValue<BenchmarkJob>> actual = new HashSet<>(this.jobs.getItems());
executorServiceFX.execute(() -> {
for (ObservableBenchmarkJob value : registry.getAllItems()) {
if (!actual.contains(value)) {
this.jobs.getItems().add(value);
addJobToItems(value);
}
}
});
......@@ -258,12 +279,10 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont
@SuppressWarnings("unchecked")
private void setCellValueFactoryCompletable(int index, Function<BenchmarkJob, CompletableFuture<String>> mapper) {
JavaFXRoutines.setCellValueFactory(jobs, index, mapper);
((TableColumn<ObservableBenchmarkJob, CompletableFuture<String>>) jobs.getColumns().get(index))
.setCellFactory(
column -> new JavaFXRoutines.TableCellAdapter<ObservableBenchmarkJob, CompletableFuture<String>>(
new JavaFXRoutines.FutureValueUpdater<ObservableBenchmarkJob, String, CompletableFuture<String>>(
new JavaFXRoutines.StringValueUpdater<ObservableBenchmarkJob>(),
executorServiceFX)));
((TableColumn<ObservableBenchmarkJob, CompletableFuture<String>>) jobs.getColumns().get(index)).setCellFactory(
column -> new JavaFXRoutines.TableCellAdapter<ObservableBenchmarkJob, CompletableFuture<String>>(
new JavaFXRoutines.FutureValueUpdater<ObservableBenchmarkJob, String, CompletableFuture<String>>(
new JavaFXRoutines.StringValueUpdater<ObservableBenchmarkJob>(), executorServiceFX)));
}
private interface P_JobAction {
......
package cz.it4i.fiji.haas_spim_benchmark.ui;
import java.awt.Window;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cz.it4i.fiji.haas.ui.CloseableControl;
import cz.it4i.fiji.haas.ui.FXFrame;
import cz.it4i.fiji.haas.ui.InitiableControl;
import cz.it4i.fiji.haas.ui.JavaFXRoutines;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.Parent;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.stage.DirectoryChooser;
public class NewJobController extends BorderPane implements CloseableControl, InitiableControl {
public enum DataLocation {
DEMONSTRATION_ON_SERVER, WORK_DIRECTORY, CUSTOM_DIRECTORY
}
private static final Runnable EMPTY_NOTIFIER = () -> {
};
@SuppressWarnings("unused")
private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.NewJobController.class);
@FXML
private Button bt_create;
@FXML
private ToggleGroup tg_inputDataLocation;
@FXML
private ToggleGroup tg_outputDataLocation;
@FXML
private RadioButton rb_ownInput;
@FXML
private RadioButton rb_ownOutput;
@FXML
private TextField et_inputDirectory;
@FXML
private TextField et_outputDirectory;
private DataLocation inputDataLocation;
private DataLocation outputDataLocation;
private FXFrame<?> ownerWindow;
private Runnable createPressedNotifier;
@FXML
private Button bt_selectInput;
@FXML
private Button bt_selectOutput;
public NewJobController() {
JavaFXRoutines.initRootAndController("NewJobView.fxml", this);
getStylesheets().add(getClass().getResource("NewJobView.css").toExternalForm());
bt_create.setOnMouseClicked(X -> createPressed());
tg_inputDataLocation.selectedToggleProperty().addListener((v, old, n) -> selected(v, old, n, rb_ownInput));
tg_outputDataLocation.selectedToggleProperty().addListener((v, o, n) -> selected(v, o, n, rb_ownOutput));
initSelectButton(et_inputDirectory, bt_selectInput);
initSelectButton(et_outputDirectory, bt_selectOutput);
}
@Override
public void close() {
}
@Override
public void init(Window parameter) {
ownerWindow = (FXFrame<?>) parameter;
}
public Path getInputDirectory(Path workingDirectory) {
return getDirectory(inputDataLocation, et_inputDirectory.getText(), workingDirectory);
}
public Path getOutputDirectory(Path workingDirectory) {
return getDirectory(outputDataLocation, et_outputDirectory.getText(), workingDirectory);
}
public void setCreatePressedNotifier(Runnable createPressedNotifier) {
if (createPressedNotifier != null) {
this.createPressedNotifier = createPressedNotifier;
} else {
this.createPressedNotifier = EMPTY_NOTIFIER;
}
}
private void initSelectButton(TextField textField, Button button) {
button.setOnAction(x -> {
Path p = Paths.get(textField.getText());
DirectoryChooser dch = new DirectoryChooser();
if (Files.exists(p)) {
dch.setInitialDirectory(p.toAbsolutePath().toFile());
}
File result = dch.showDialog(ownerWindow.getFxPanel().getScene().getWindow());
if (result != null) {
textField.setText(result.toString());
}
});
}
private Path getDirectory(DataLocation dataLocation, String selectedDirectory, Path workingDirectory) {
switch (dataLocation) {
case DEMONSTRATION_ON_SERVER:
return null;
case WORK_DIRECTORY:
return workingDirectory;
case CUSTOM_DIRECTORY:
return Paths.get(selectedDirectory).toAbsolutePath();
default:
throw new UnsupportedOperationException("Not support " + dataLocation);
}
}
private void createPressed() {
obtainValues();
if (checkDirectoryLocationIfNeeded()) {
ownerWindow.setVisible(false);
ownerWindow.dispose();
createPressedNotifier.run();
}
}
private boolean checkDirectoryLocationIfNeeded() {
return checkDataLocationValue(inputDataLocation, et_inputDirectory.getText(), "input")
&& checkDataLocationValue(outputDataLocation, et_outputDirectory.getText(), "output");
}
private boolean checkDataLocationValue(DataLocation dataLocation, String directory, String type) {
Path directoryPath = Paths.get(directory);
if (dataLocation == DataLocation.CUSTOM_DIRECTORY && (!Files.exists(directoryPath) || directory.isEmpty())) {
Alert alert = new Alert(AlertType.WARNING);
alert.setTitle("Invalid input provided");
alert.setHeaderText(null);
String message = !directory.isEmpty() ? "Directory %s for %s not exists"
: "Directory for %2$s is not selected.";
alert.setContentText(String.format(message, directoryPath.toAbsolutePath(), type));
alert.showAndWait();
return false;
}
return true;
}
private void obtainValues() {
inputDataLocation = obtainDataLocation(tg_inputDataLocation);
outputDataLocation = obtainDataLocation(tg_outputDataLocation);
}
private DataLocation obtainDataLocation(ToggleGroup group) {
int backawardOrderOfSelected = group.getToggles().size()
- group.getToggles().indexOf(group.getSelectedToggle());
return DataLocation.values()[DataLocation.values().length - backawardOrderOfSelected];
}
private void selected(ObservableValue<? extends Toggle> v, Toggle o, Toggle n, Parent disableIfNotSelected) {
disableIfNotSelected.getChildrenUnmodifiable().forEach(node -> node.setDisable(n != disableIfNotSelected));
}
}
package cz.it4i.fiji.haas_spim_benchmark.ui;
import java.awt.Window;
import java.nio.file.Path;
import cz.it4i.fiji.haas.ui.FXFrame;
public class NewJobWindow extends FXFrame<NewJobController>{
private static final long serialVersionUID = 1L;
public NewJobWindow(Window parentWindow) {
super(parentWindow,()->{
return new NewJobController();
});
setTitle("Create job");
}
public Path getInputDirectory(Path workingDirectory) {
return getFxPanel().getControl().getInputDirectory(workingDirectory);
}
public Path getOutputDirectory(Path workingDirectory) {
return getFxPanel().getControl().getOutputDirectory(workingDirectory);
}
public void setCreatePressedNotifier(Runnable runnable) {
getFxPanel().getControl().setCreatePressedNotifier(runnable);
}
}
\ No newline at end of file
{
-fx-padding: 3 3 3 3;
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" type="BorderPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.it4i.fiji.haas_spim_benchmark.ui.NewJobController">
<center>
<VBox BorderPane.alignment="CENTER">
<children>
<TitledPane animated="false" collapsible="false" text="Input">
<content>
<AnchorPane>
<children>
<VBox>
<children>
<RadioButton mnemonicParsing="false" selected="true">
<toggleGroup>
<ToggleGroup fx:id="tg_inputDataLocation" />
</toggleGroup>
<graphic>
<Label maxHeight="1.7976931348623157E308" text="Demonstration data on IT4I cluster" />
</graphic>
</RadioButton>
<RadioButton maxHeight="1.7976931348623157E308" mnemonicParsing="false" toggleGroup="$tg_inputDataLocation">
<graphic>
<Label maxHeight="1.7976931348623157E308" text="Job subdirectory" />
</graphic>
</RadioButton>
<RadioButton fx:id="rb_ownInput" mnemonicParsing="false" toggleGroup="$tg_inputDataLocation">
<graphic>
<HBox disable="true">
<children>
<TextField fx:id="et_inputDirectory" prefWidth="350.0" />
<Button fx:id="bt_selectInput" mnemonicParsing="false" text="Select" />
</children>
</HBox>
</graphic>
</RadioButton>
</children>
</VBox>
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane animated="false" collapsible="false" text="Output">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0">
<children>
<VBox>
<children>
<HBox>
<children>
<RadioButton maxHeight="1.7976931348623157E308" mnemonicParsing="false" selected="true">
<toggleGroup>
<ToggleGroup fx:id="tg_outputDataLocation" />
</toggleGroup>
<graphic>
<Label maxHeight="1.7976931348623157E308" text="Job subdirectory" />
</graphic>
</RadioButton>
</children>
</HBox>
<HBox>
<children>
<RadioButton fx:id="rb_ownOutput" mnemonicParsing="false" toggleGroup="$tg_outputDataLocation">
<graphic>
<HBox disable="true">
<children>
<TextField fx:id="et_outputDirectory" prefWidth="350.0" />
<Button fx:id="bt_selectOutput" mnemonicParsing="false" text="Select" />
</children>
</HBox>
</graphic>
</RadioButton>
</children>
</HBox>
</children>
</VBox>
</children>
</AnchorPane>
</content>
</TitledPane>
</children>
</VBox>
</center>
<bottom>
<BorderPane BorderPane.alignment="CENTER">
<right>
<Button fx:id="bt_create" mnemonicParsing="false" prefHeight="22.0" prefWidth="71.0" text="Create" BorderPane.alignment="CENTER">
<BorderPane.margin>
<Insets right="3.0" />
</BorderPane.margin></Button>
</right>
</BorderPane>
</bottom>
</fx:root>
/**
*
*/
/**
* @author koz01
*
*/
package cz.it4i.fiji.haas_spim_benchmark.ui;
\ No newline at end of file
package cz.it4i.fiji.haas;
import java.io.IOException;
import cz.it4i.fiji.haas_spim_benchmark.ui.NewJobWindow;
public class NewJobWindowShow {
public static void main(String[] args) throws IOException {
new NewJobWindow(null).setVisible(true);
}
}
......@@ -20,7 +20,7 @@ public class RunBenchmark {
public static class CreateJob {
public static void main(String[] args) throws IOException {
BenchmarkJobManager benchmarkJobManager = new BenchmarkJobManager(getBenchmarkSPIMParameters());
BenchmarkJob ji = benchmarkJobManager.createJob();
BenchmarkJob ji = benchmarkJobManager.createJob(jd -> jd, jd -> jd);
log.info("job: " + ji.getId() + " created.");
}
}
......@@ -42,8 +42,6 @@ public class RunBenchmark {
}
}
private static BenchmarkSPIMParameters getBenchmarkSPIMParameters() throws IOException {
Path p = Paths.get("/tmp/benchmark");
if (!Files.exists(p)) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment