diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..57bc88a15a0ee8266c259b2667e64608d3f7e292 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/benchmark-collector/src/it4i/fiji/benchmark_extractor/Extractor.java b/benchmark-collector/src/it4i/fiji/benchmark_extractor/Extractor.java index 2354ccec7a66c5a046427ce058ff326c350d9d96..55c3c4739c4c5ad4d15cfae8a5c3d08b5d43c2bb 100644 --- a/benchmark-collector/src/it4i/fiji/benchmark_extractor/Extractor.java +++ b/benchmark-collector/src/it4i/fiji/benchmark_extractor/Extractor.java @@ -7,8 +7,6 @@ import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -29,7 +27,8 @@ public class Extractor { private Map<String, String> valueWithTypes; - public Extractor(Path inputFile, Set<String> valuesToExport, Map<String, String> valuesWithTypes, OutputStream out) { + public Extractor(Path inputFile, Set<String> valuesToExport, Map<String, String> valuesWithTypes, + OutputStream out) { this.inputFile = inputFile; this.valuesToExport = valuesToExport; this.valueWithTypes = valuesWithTypes; @@ -61,7 +60,7 @@ public class Extractor { } } } - if(valueCollector != null) { + if (valueCollector != null) { write(pw, collector, valueCollector); } } catch (IOException e) { @@ -102,12 +101,12 @@ public class Extractor { out.printf("jobs #;%d\n", ids.size()); out.printf("job ids;%s\n", String.join(";", ids)); for (String key : valuesToExport) { - out.printf("%s;%s\n", key, String.join(";", convert(key,values4Job.get(key)))); + out.printf("%s;%s\n", key, String.join(";", convert(key, values4Job.get(key)))); } } private List<String> convert(String key, List<String> list) { - if(!valueWithTypes.containsKey(key)) { + if (!valueWithTypes.containsKey(key)) { return list; } Function<String, String> conversion = getConversion(valueWithTypes.get(key)); @@ -122,7 +121,13 @@ public class Extractor { //return str->nf.format(Double.parseDouble(str.replace("kb", ""))/1024.); return str -> "" + Double.parseDouble(str.replace("kb", ""))/1024.; case "tm": - return str-> Duration.between(LocalTime.of(0, 0, 0), LocalTime.parse(str, DateTimeFormatter.ofPattern("H:m:s"))).getSeconds() + ""; + + return str-> { + String []tokens = str.split(":"); + return Duration.ofHours(Integer.parseInt(tokens[0])) + .plusMinutes(Integer.parseInt(tokens[1])) + .plusSeconds(Integer.parseInt(tokens[2])).getSeconds() + ""; + }; } return str->str; diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java index 555b1742666d9791de536e8219ca6154c3808a30..41c3b33f1f3677d357a08acef27d6f5cc847696a 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/Job.java @@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory; import cz.it4i.fiji.haas.JobManager.JobManager4Job; import cz.it4i.fiji.haas.JobManager.JobSynchronizableFile; +import cz.it4i.fiji.haas_java_client.DummyProgressNotifier; import cz.it4i.fiji.haas_java_client.HaaSClient; import cz.it4i.fiji.haas_java_client.HaaSClient.UploadingFile; import cz.it4i.fiji.haas_java_client.HaaSFileTransfer; @@ -55,7 +56,7 @@ public class Job { public Job(JobManager4Job jobManager, String name, Path basePath, Supplier<HaaSClient> haasClientSupplier) throws IOException { this(jobManager,haasClientSupplier); - HaaSClient client = this.haasClientSupplier.get(); + HaaSClient client = getHaaSClient(); long id = client.createJob(name, Collections.emptyList()); jobDir = basePath.resolve("" + id); propertyHolder = new PropertyHolder(jobDir.resolve(JOB_INFO_FILE)); @@ -75,7 +76,7 @@ public class Job { } public void uploadFiles(Iterable<UploadingFile> files, Progress notifier) { - HaaSClient client = this.haasClientSupplier.get(); + HaaSClient client = getHaaSClient(); try(HaaSFileTransfer transfer = client.startFileTransfer(getId(), new P_ProgressNotifierAdapter(notifier))){ transfer.upload(files); } @@ -88,7 +89,7 @@ public class Job { } public void submit() { - HaaSClient client = this.haasClientSupplier.get(); + HaaSClient client = getHaaSClient(); client.submitJob(jobId); } @@ -119,8 +120,8 @@ public class Job { } synchronized public void download(Predicate<String> predicate, Progress notifier) { - try (HaaSFileTransfer fileTransfer = haasClientSupplier.get().startFileTransfer(jobId, new P_ProgressNotifierAdapter(notifier))) { - fileTransfer.download(haasClientSupplier.get().getChangedFiles(jobId).stream().filter(predicate).collect(Collectors.toList()), jobDir); + try (HaaSFileTransfer fileTransfer = getHaaSClient().startFileTransfer(jobId, new P_ProgressNotifierAdapter(notifier))) { + fileTransfer.download(getHaaSClient().getChangedFiles(jobId).stream().filter(predicate).collect(Collectors.toList()), jobDir); } } @@ -144,7 +145,7 @@ public class Job { HaaSClient.SynchronizableFiles taskFileOffset = new HaaSClient.SynchronizableFiles(); long taskId = (Long) getJobInfo().getTasks().toArray()[0]; output.forEach(file -> taskFileOffset.addFile(taskId, file.getType(), file.getOffset())); - return haasClientSupplier.get().downloadPartsOfJobFiles(jobId, taskFileOffset).stream().map(f -> f.getContent()) + return getHaaSClient().downloadPartsOfJobFiles(jobId, taskFileOffset).stream().map(f -> f.getContent()) .collect(Collectors.toList()); } @@ -185,6 +186,10 @@ public class Job { return result; } + private HaaSClient getHaaSClient() { + return this.haasClientSupplier.get(); + } + private JobInfo getJobInfo() { if (jobInfo == null) { updateJobInfo(); @@ -193,7 +198,7 @@ public class Job { } private void updateJobInfo() { - jobInfo = haasClientSupplier.get().obtainJobInfo(getId()); + jobInfo = getHaaSClient().obtainJobInfo(getId()); } private static boolean isValidPath(Path path) { @@ -244,11 +249,24 @@ public class Job { } public Collection<String> getChangedFiles() { - return haasClientSupplier.get().getChangedFiles(getId()); + return getHaaSClient().getChangedFiles(getId()); } public void cancelJob() { - haasClientSupplier.get().cancelJob(jobId); + getHaaSClient().cancelJob(jobId); + } + + public List<Long> getFileSizes(List<String> names) { + + try (HaaSFileTransfer transfer = getHaaSClient().startFileTransfer(getId(), new DummyProgressNotifier())) { + return transfer.obtainSize(names); + } + } + + public List<String> getFileContents(List<String> logs) { + try (HaaSFileTransfer transfer = getHaaSClient().startFileTransfer(getId(), new DummyProgressNotifier())) { + return transfer.getContent(logs); + } } diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/FXFrame.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/FXFrame.java index 7b981a33910a5fdea3348929595ae54d5d544f3b..23dda8e8dc97ad23bd3788559e814c3528e21897 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/FXFrame.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/FXFrame.java @@ -30,18 +30,17 @@ public abstract class FXFrame<T extends Parent&CloseableControl> extends JDialog public FXFrame(Window parent, Supplier<T> fxSupplier) { super(parent, ModalityType.MODELESS); fxPanel = new JFXPanel<>(fxSupplier); + init(); if (fxPanel.getControl() instanceof InitiableControl) { InitiableControl control = (InitiableControl) fxPanel.getControl(); control.init(this); } - init(); } private void init() { addWindowListener(new WindowAdapter() { @Override - public void windowClosed(WindowEvent e) { - super.windowClosed(e); + public void windowClosing(WindowEvent e) { getFxPanel().getControl().close(); } }); diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/JavaFXRoutines.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/JavaFXRoutines.java index 59ae9b7c86a5c374991c1d6f0ffe9e410b62bed0..c33528cde87f4dad3d174482c44b0698620a7924 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/JavaFXRoutines.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/JavaFXRoutines.java @@ -6,6 +6,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -135,5 +136,13 @@ public interface JavaFXRoutines { } }); } + + public static <T> boolean notNullValue(ObservableValue<T> j, Predicate<T> pred) { + if (j == null || j.getValue() == null) { + return false; + } else { + return pred.test(j.getValue()); + } + } } diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java index 355ab32036a370e82100599234f44316e57fbe9b..b47f0739cd6a60e14d2649f977a18334101d68a2 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ObservableValueRegistry.java @@ -1,7 +1,7 @@ package cz.it4i.fiji.haas.ui; import java.util.Collection; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; import java.util.function.Consumer; @@ -29,7 +29,7 @@ public class ObservableValueRegistry<T> { } - private Map<T,UpdatableObservableValue<T>> map = new HashMap<>(); + private Map<T,UpdatableObservableValue<T>> map = new LinkedHashMap<>(); public ObservableValue<T> addIfAbsent(T value) { UpdatableObservableValue<T> uov = map.computeIfAbsent(value, v-> new UpdatableObservableValue<T>(v, updateFunction, stateProvider)); diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ProgressDialog.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ProgressDialog.java index 93ad84c8caeaf3a21849ad29d8b5a489ac80af6a..c86acb066ac80fa35b9db30573361a743a3e55ba 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ProgressDialog.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/ProgressDialog.java @@ -27,14 +27,13 @@ import net.imagej.updater.util.Progress; import net.imagej.updater.util.UpdateCanceledException; /** - * TODO * * @author Johannes Schindelin */ @SuppressWarnings("serial") public class ProgressDialog extends JDialog implements Progress { @SuppressWarnings("unused") - private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.ui.ProgressDialog.class); + public final static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.ui.ProgressDialog.class); JProgressBar progress; JButton detailsToggle; @@ -110,7 +109,6 @@ public class ProgressDialog extends JDialog implements Progress { if (title != null) setTitle(title); pack(); - if (owner != null) { final Dimension o = owner.getSize(); final Dimension size = getSize(); @@ -119,6 +117,8 @@ public class ProgressDialog extends JDialog implements Progress { setSize(size); } setLocation(owner.getX() + (o.width - size.width) / 2, owner.getY() + (o.height - size.height) / 2); + } else { + setLocationRelativeTo(owner); } final KeyAdapter keyAdapter = new KeyAdapter() { @@ -133,7 +133,6 @@ public class ProgressDialog extends JDialog implements Progress { detailsToggle.addKeyListener(keyAdapter); cancel.addKeyListener(keyAdapter); - setLocationRelativeTo(null); if (title != null) setVisible(true); } @@ -293,7 +292,7 @@ public class ProgressDialog extends JDialog implements Progress { return false; } - public static void main(final String[] args) { + private static void main(final String[] args) { final ProgressDialog dialog = new ProgressDialog(null, "Hello"); dialog.addItem("Bello"); dialog.setVisible(true); diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/TableViewContextMenu.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/TableViewContextMenu.java index ed828856dc41ca8c3f311de33f0fc5849d26a362..0789e95c66f6a7124e5398cecb10e6a107a67923 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/TableViewContextMenu.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/TableViewContextMenu.java @@ -2,6 +2,8 @@ package cz.it4i.fiji.haas.ui; import java.util.Collection; import java.util.LinkedList; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; @@ -11,42 +13,73 @@ import org.slf4j.LoggerFactory; import javafx.event.EventHandler; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; +import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.input.ContextMenuEvent; public class TableViewContextMenu<T> { - @SuppressWarnings("unused") - private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.ui.TableViewContextMenu.class); - private Collection<P_MenuItem> items = new LinkedList<TableViewContextMenu<T>.P_MenuItem>(); - private ContextMenu cm; + + public final static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.ui.TableViewContextMenu.class); + + private final Collection<P_MenuItem> items = new LinkedList<>(); + private final Collection<P_MenuItemWithColumnIndex> itemsWithColumnIndex = new LinkedList<>(); + private TableView<T> tableView; + private int columnIndex = -1; + public TableViewContextMenu(TableView<T> tableView) { - this.cm = new ContextMenu(); this.tableView = tableView; - tableView.setContextMenu(cm); - tableView.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() { - @Override - public void handle(ContextMenuEvent event) { - T selected = getSelectedItem(); - - for (P_MenuItem item : items) { - item.updateEnable(selected); - } - } - }); } public void addItem(String text, Consumer<T> eventHandler, Predicate<T> enableHandler) { items.add(new P_MenuItem(text, eventHandler, enableHandler)); } - private T getSelectedItem() { - T result = null; - if (tableView.getSelectionModel().getSelectedCells().size() >= 0) { - result = tableView.getSelectionModel().getSelectedItem(); + public void addItem(String text, BiConsumer<T, Integer> eventHandler, BiPredicate<T, Integer> enableHandler) { + itemsWithColumnIndex.add(new P_MenuItemWithColumnIndex(text, eventHandler, enableHandler)); + } + + private T getRequestedItem() { + return tableView.getFocusModel().getFocusedItem(); + } + + private int getRequestedColumn() { + return columnIndex; + } + + private ContextMenu getOrCreateContextMenu() { + ContextMenu cm = tableView.getContextMenu(); + if (cm == null) { + cm = new ContextMenu(); + tableView.setContextMenu(cm); + tableView.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() { + @Override + public void handle(ContextMenuEvent event) { + T requestedItem = getRequestedItem(); + updateColumnIndex(event.getSceneX()); + int column = getRequestedColumn(); + items.forEach(item -> item.updateEnable(requestedItem)); + itemsWithColumnIndex.forEach(item -> item.updateEnable(requestedItem, column)); + } + + private void updateColumnIndex(double sceneX) { + double last = 0; + columnIndex = tableView.getColumns().size(); + int index = 0; + for (TableColumn<?, ?> column : tableView.getColumns()) { + last += column.getWidth(); + if (last > sceneX) { + columnIndex = index; + break; + } + index++; + } + } + }); + } - return result; + return cm; } private class P_MenuItem { @@ -57,8 +90,8 @@ public class TableViewContextMenu<T> { public P_MenuItem(String text, Consumer<T> eventHandler, Predicate<T> enableHandler) { this.enableHandler = enableHandler; item = new MenuItem(text); - item.setOnAction(e -> eventHandler.accept(getSelectedItem())); - cm.getItems().add(item); + item.setOnAction(e -> eventHandler.accept(getRequestedItem())); + getOrCreateContextMenu().getItems().add(item); } public void updateEnable(T selected) { @@ -67,4 +100,23 @@ public class TableViewContextMenu<T> { } + private class P_MenuItemWithColumnIndex { + + private MenuItem item; + private BiPredicate<T, Integer> enableHandler; + + public P_MenuItemWithColumnIndex(String text, BiConsumer<T, Integer> eventHandler, + BiPredicate<T, Integer> enableHandler) { + this.enableHandler = enableHandler; + item = new MenuItem(text); + item.setOnAction(e -> eventHandler.accept(getRequestedItem(), getRequestedColumn())); + getOrCreateContextMenu().getItems().add(item); + } + + public void updateEnable(T selected, int column) { + item.setDisable(!enableHandler.test(selected, column)); + } + + } + } diff --git a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java index a4c41a15cfa241aa801cfcf6a7b5a5d33e906d30..4116da697e01d538211eee84d879f538e4160b26 100644 --- a/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java +++ b/haas-imagej-client/src/main/java/cz/it4i/fiji/haas/ui/UpdatableObservableValue.java @@ -2,10 +2,16 @@ package cz.it4i.fiji.haas.ui; import java.util.function.Function; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javafx.beans.value.ObservableValueBase; public class UpdatableObservableValue<T> extends ObservableValueBase<T> { + @SuppressWarnings("unused") + private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.ui.UpdatableObservableValue.class); + public enum UpdateStatus { Deleted, Updated, NotUpdated } diff --git a/haas-imagej-client/src/test/java/cz/it4i/fiji/haas/TableProof.fxml b/haas-imagej-client/src/test/java/cz/it4i/fiji/haas/TableProof.fxml new file mode 100644 index 0000000000000000000000000000000000000000..ac481ad65cac5d34e5ac0e3dff9b362fb1b0b7a1 --- /dev/null +++ b/haas-imagej-client/src/test/java/cz/it4i/fiji/haas/TableProof.fxml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.control.TableView?> +<?import javafx.scene.control.TableColumn?> +<?import javafx.geometry.Insets?> + + +<fx:root type="BorderPane" xmlns="http://javafx.com/javafx/8.0.65" + xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.it4i.fiji.haas.TableProofControl"> + <center> + + <HBox> + <children> + + <TableView fx:id="table" HBox.hgrow="ALWAYS"> + <columns> + <TableColumn prefWidth="75.0" text="Job Id" /> + <TableColumn prefWidth="149.0" text="Status" /> + <TableColumn prefWidth="230.0" text="Creation time" /> + <TableColumn prefWidth="230.0" text="Start time" /> + <TableColumn prefWidth="230.0" text="End Time" /> + </columns> + </TableView> + </children> + <padding> + <Insets bottom="1.0" left="1.0" right="1.0" top="1.0" /> + </padding> + </HBox> + </center> + +</fx:root> + diff --git a/haas-imagej-client/src/test/java/cz/it4i/fiji/haas/TableProofControl.java b/haas-imagej-client/src/test/java/cz/it4i/fiji/haas/TableProofControl.java new file mode 100644 index 0000000000000000000000000000000000000000..7c03872a9866460fd4111019b725900cf76effc7 --- /dev/null +++ b/haas-imagej-client/src/test/java/cz/it4i/fiji/haas/TableProofControl.java @@ -0,0 +1,97 @@ +package cz.it4i.fiji.haas; + +import java.awt.Window; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.WindowConstants; + +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 cz.it4i.fiji.haas.ui.TableViewContextMenu; +import javafx.beans.value.ObservableValue; +import javafx.beans.value.ObservableValueBase; +import javafx.fxml.FXML; +import javafx.scene.control.TableView; +import javafx.scene.layout.BorderPane; + +public class TableProofControl extends BorderPane implements CloseableControl, InitiableControl { + + @SuppressWarnings("unused") + private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas.TableProofControl.class); + + @FXML + private TableView<ObservableValue<String[]>> table; + private TableViewContextMenu<ObservableValue<String[]>> menu; + + public TableProofControl() { + JavaFXRoutines.initRootAndController("TableProof.fxml", this); + menu = new TableViewContextMenu<>(table); + for (int i = 0; i < 4; i++) { + final int index = i; + JavaFXRoutines.setCellValueFactory(table, index, vals -> vals[index]); + } + menu.addItem("Proof", (val, index) -> proof(index), (val, index) -> index < 4); + addItem(); + addItem(); + addItem(); + addItem(); + } + + private void addItem() { + String[] values = new String[] { "0", "1", "2", "3" }; + class Values extends ObservableValueBase<String[]> { + + @Override + public String[] getValue() { + return values; + } + } + table.getItems().add(new Values()); + } + + private void proof(int index) { + System.out.println(index); + } + + @Override + public void init(Window parameter) { + // TODO Auto-generated method stub + + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + public static void main(String[] args) { + class Window extends FXFrame<TableProofControl> { + + public Window() { + super(() -> new TableProofControl()); + } + + /** + * + */ + private static final long serialVersionUID = 1L; + } + + Window w = new Window(); + w.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + w.setVisible(true); + w.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + } +} diff --git a/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/DummyProgressNotifier.java b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/DummyProgressNotifier.java new file mode 100644 index 0000000000000000000000000000000000000000..927d4c048226546d76acd64d99fb3953b886ce70 --- /dev/null +++ b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/DummyProgressNotifier.java @@ -0,0 +1,29 @@ +package cz.it4i.fiji.haas_java_client; + +public class DummyProgressNotifier implements ProgressNotifier { + + @Override + public void setCount(int count, int total) { + } + + @Override + public void addItem(Object item) { + } + + @Override + public void setItemCount(int count, int total) { + + } + + @Override + public void itemDone(Object item) { + } + + @Override + public void done() { + } + + @Override + public void setTitle(String title) { + } +} diff --git a/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSClient.java b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSClient.java index dac7e14f777a0eaf8532726a8acd5326a2fe2275..c2aa23c2afad67cbec975cf18d453a7c4bdff3f0 100644 --- a/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSClient.java +++ b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSClient.java @@ -163,6 +163,8 @@ public class HaaSClient { private String projectId; + private Map<Long, P_FileTransferPool> filetransferPoolMap = new HashMap<>(); + public static ProgressNotifier DUMMY_NOTIFIER = new ProgressNotifier() { @Override @@ -246,8 +248,7 @@ public class HaaSClient { public HaaSFileTransfer startFileTransfer(long jobId, ProgressNotifier notifier) { try { - FileTransferMethodExt ft = getFileTransfer().getFileTransferMethod(jobId, getSessionID()); - return new HaaSFileTransferImp(ft, getSessionID(), jobId, getFileTransfer(), getScpClient(ft), notifier); + return getFileTransferMethod(jobId, notifier); } catch (RemoteException | ServiceException | UnsupportedEncodingException | JSchException e) { throw new HaaSClientException(e); } @@ -304,7 +305,7 @@ public class HaaSClient { throw new HaaSClientException(e); } } - + public Collection<String> getChangedFiles(long jobId) { try { return Arrays.asList(getFileTransfer().listChangedFilesForJob(jobId, getSessionID())); @@ -312,8 +313,7 @@ public class HaaSClient { throw new HaaSClientException(e); } } - - + public void cancelJob(Long jobId) { try { getJobManagement().cancelJob(jobId, getSessionID()); @@ -322,6 +322,27 @@ public class HaaSClient { } } + private HaaSFileTransferImp getFileTransferMethod(long jobId, ProgressNotifier notifier) + throws RemoteException, UnsupportedEncodingException, ServiceException, JSchException { + P_FileTransferPool pool = filetransferPoolMap.computeIfAbsent(jobId, id -> new P_FileTransferPool(id)); + FileTransferMethodExt ft = pool.obtain(); + try { + return new HaaSFileTransferImp(ft, getScpClient(ft), notifier) { + public void close() { + super.close(); + try { + pool.release(); + } catch (RemoteException | ServiceException e) { + throw new HaaSClientException(e); + } + }; + }; + } catch (UnsupportedEncodingException | JSchException e) { + pool.release(); + throw e; + } + } + private void doSubmitJob(long jobId) throws RemoteException, ServiceException { getJobManagement().submitJob(jobId, getSessionID()); } @@ -469,4 +490,43 @@ public class HaaSClient { } } + private interface P_Supplier<T> { + + T get() throws RemoteException, ServiceException; + } + + private interface P_Consumer<T> { + + void accept(T val) throws RemoteException, ServiceException; + } + + private class P_FileTransferPool { + private FileTransferMethodExt holded; + private int counter; + private final P_Supplier<FileTransferMethodExt> factory; + private final P_Consumer<FileTransferMethodExt> destroyer; + + public P_FileTransferPool(long jobId) { + this.factory = () -> getFileTransfer().getFileTransferMethod(jobId, getSessionID()); + this.destroyer = val -> getFileTransfer().endFileTransfer(jobId, val, sessionID); + ; + } + + public synchronized FileTransferMethodExt obtain() throws RemoteException, ServiceException { + if (holded == null) { + holded = factory.get(); + } + counter++; + return holded; + } + + public synchronized void release() throws RemoteException, ServiceException { + if (--counter == 0) { + destroyer.accept(holded); + holded = null; + } + } + + } + } diff --git a/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransfer.java b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransfer.java index e3b427f2a1cdbdfbaef67fbfa10b3a5d9bc789a8..c6c8a4b9b31142c0b5041b1ccf1882bae1a82b4d 100644 --- a/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransfer.java +++ b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransfer.java @@ -18,4 +18,5 @@ public interface HaaSFileTransfer extends Closeable { List<Long> obtainSize(List<String> files); + List<String> getContent(List<String> logs); } diff --git a/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransferImp.java b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransferImp.java index 6d59b42f6240640ab78a8f692f43d17e00e39bad..5cbaf90c68a5b762795ae6b58365bcfdf7948ab1 100644 --- a/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransferImp.java +++ b/haas-java-client/src/main/java/cz/it4i/fiji/haas_java_client/HaaSFileTransferImp.java @@ -1,9 +1,10 @@ package cz.it4i.fiji.haas_java_client; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; -import java.rmi.RemoteException; +import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -16,39 +17,26 @@ import com.jcraft.jsch.JSchException; import cz.it4i.fiji.haas_java_client.HaaSClient.P_ProgressNotifierDecorator4Size; import cz.it4i.fiji.haas_java_client.HaaSClient.UploadingFile; import cz.it4i.fiji.haas_java_client.proxy.FileTransferMethodExt; -import cz.it4i.fiji.haas_java_client.proxy.FileTransferWsSoap; import cz.it4i.fiji.scpclient.ScpClient; class HaaSFileTransferImp implements HaaSFileTransfer { + @SuppressWarnings("unused") private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas_java_client.HaaSFileTransferImp.class); private FileTransferMethodExt ft; private ScpClient scpClient; - private FileTransferWsSoap fileTransfer; - private String sessionId; - private long jobId; private ProgressNotifier notifier; - public HaaSFileTransferImp(FileTransferMethodExt ft, String sessionId, long jobId, FileTransferWsSoap fileTransfer, - ScpClient scpClient, ProgressNotifier notifier) { + public HaaSFileTransferImp(FileTransferMethodExt ft, ScpClient scpClient, ProgressNotifier notifier) { this.ft = ft; this.scpClient = scpClient; - this.fileTransfer = fileTransfer; - this.sessionId = sessionId; - this.jobId = jobId; this.notifier = notifier; } @Override public void close() { scpClient.close(); - try { - fileTransfer.endFileTransfer(jobId, ft, sessionId); - } catch (RemoteException e) { - throw new HaaSClientException(e); - } - } @Override @@ -108,11 +96,52 @@ class HaaSFileTransferImp implements HaaSFileTransfer { public List<Long> obtainSize(List<String> files) { try { return HaaSClient.getSizes(files.stream() - .map(filename -> "'" + ft.getSharedBasepath() + "/" + filename + "'").collect(Collectors.toList()), scpClient, notifier); + .map(filename -> "'" + ft.getSharedBasepath() + "/" + filename + "'").collect(Collectors.toList()), + scpClient, notifier); + } catch (JSchException | IOException e) { + throw new HaaSClientException(e); + } + + } + + // FIXME: merge with download - stream provider for file, consumer for stream + @Override + public List<String> getContent(List<String> files) { + List<String> result = new LinkedList<>(); + List<Long> fileSizes; + try { + fileSizes = HaaSClient.getSizes(StreamSupport.stream(files.spliterator(), false) + .map(filename -> "'" + ft.getSharedBasepath() + "/" + filename + "'").collect(Collectors.toList()), + scpClient, new P_ProgressNotifierDecorator4Size(notifier)); + + final long totalFileSize = fileSizes.stream().mapToLong(i -> i.longValue()).sum(); + TransferFileProgressForHaaSClient progress = new TransferFileProgressForHaaSClient(totalFileSize, notifier); + int idx = 0; + for (String fileName : files) { + fileName = replaceIfFirstFirst(fileName, "/", ""); + try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { + String fileToDownload = "'" + ft.getSharedBasepath() + "/" + fileName + "'"; + String item; + progress.addItem(item = fileName); + progress.startNewFile(fileSizes.get(idx)); + scpClient.download(fileToDownload, os, progress); + os.flush(); + progress.itemDone(item); + idx++; + result.add(os.toString()); + } + } } catch (JSchException | IOException e) { throw new HaaSClientException(e); } + return result; + } + private String replaceIfFirstFirst(String fileName, String string, String string2) { + if (fileName.length() < 0 && fileName.charAt(0) == '/') { + fileName = fileName.substring(1); + } + return fileName; } } diff --git a/haas-java-client/src/test/java/cz/it4i/fiji/haas_java_client/TestConcurentAccessToHaaSFileTransfer.java b/haas-java-client/src/test/java/cz/it4i/fiji/haas_java_client/TestConcurentAccessToHaaSFileTransfer.java new file mode 100644 index 0000000000000000000000000000000000000000..cdeedef7f7bcb4a58bdd249520d82c5dfa6eae2b --- /dev/null +++ b/haas-java-client/src/test/java/cz/it4i/fiji/haas_java_client/TestConcurentAccessToHaaSFileTransfer.java @@ -0,0 +1,26 @@ +package cz.it4i.fiji.haas_java_client; + +import java.io.IOException; +import java.util.Arrays; + +import javax.xml.rpc.ServiceException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestConcurentAccessToHaaSFileTransfer { + + private static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas_java_client.TestConcurentAccessToHaaSFileTransfer.class); + + public static void main(String[] args) throws ServiceException, IOException { + HaaSClient client = new HaaSClient(TestingConstants.getSettings(1l, 600, 7l, "OPEN-12-20")); + HaaSFileTransfer tr1 = client.startFileTransfer(250, new DummyProgressNotifier()); + HaaSFileTransfer tr2 = client.startFileTransfer(249, new DummyProgressNotifier()); + log.info("config.yaml - size:" + tr1.obtainSize(Arrays.asList("config.yaml"))); + tr1.close(); + log.info("config.yaml - size:" + tr2.obtainSize(Arrays.asList("config.yaml"))); + tr2.close(); + } + + +} diff --git a/haas-spim-benchmark/pom.xml b/haas-spim-benchmark/pom.xml index 92859dc556c15ffd153120c062eef63adf87d9ea..10057406c4c5b478647fc61aae0ee12efb56925d 100644 --- a/haas-spim-benchmark/pom.xml +++ b/haas-spim-benchmark/pom.xml @@ -78,6 +78,14 @@ <artifactId>haas-imagej-client</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> + + <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.6</version> + </dependency> + <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api --> <dependency> <groupId>org.slf4j</groupId> diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java index 4f54ce6bbb8c77cca64905f994a716c7a75ec6ab..f7e6b93d1c66fd775eaa7c88fadb1633d19a753d 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/commands/ManageSPIMBenchmark.java @@ -17,6 +17,7 @@ import org.scijava.widget.TextWidget; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import cz.it4i.fiji.haas_spim_benchmark.core.Constants; import cz.it4i.fiji.haas_spim_benchmark.ui.BenchmarkSPIMWindow; import net.imagej.ImageJ; @@ -43,8 +44,6 @@ public class ManageSPIMBenchmark implements Command { @Parameter(style = TextWidget.PASSWORD_STYLE) private String password; - @Parameter(style = TextWidget.FIELD_STYLE) - private String phone; @Parameter(style = TextWidget.FIELD_STYLE) private String email; @@ -56,7 +55,7 @@ public class ManageSPIMBenchmark implements Command { public void run() { try { JDialog dialog = - new BenchmarkSPIMWindow(null, new BenchmarkSPIMParametersImpl(userName, password, phone, + new BenchmarkSPIMWindow(null, new BenchmarkSPIMParametersImpl(userName, password, Constants.PHONE, email, Paths.get(workingDirectory.getPath()))); dialog.setTitle("SPIM workflow computation manager"); dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java index fb63795c97bda42a976575902ed0661956867192..1a90371e33e179e9c2f474d733d5c9cd94d3adcb 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/BenchmarkJobManager.java @@ -65,7 +65,7 @@ public class BenchmarkJobManager { private JobState verifiedState; private boolean verifiedStateProcessed; private CompletableFuture<JobState> running; - + public BenchmarkJob(Job job) { this.job = job; tasks = new LinkedList<Task>(); @@ -85,14 +85,18 @@ public class BenchmarkJobManager { } public JobState getState() { - return getStateAsync(r->r.run()).getNow(JobState.Unknown); + return getStateAsync(r -> r.run()).getNow(JobState.Unknown); } - + public synchronized CompletableFuture<JobState> getStateAsync(Executor executor) { - if(running != null) { + if (running != null) { return running; } - return running = doGetStateAsync(executor); + CompletableFuture<JobState> result = doGetStateAsync(executor); + if (!result.isCancelled() && !result.isCompletedExceptionally() && !result.isDone()) { + running = result; + } + return result; } private synchronized CompletableFuture<JobState> doGetStateAsync(Executor executor) { @@ -103,28 +107,27 @@ public class BenchmarkJobManager { return CompletableFuture.completedFuture(verifiedState); } verifiedStateProcessed = true; - return CompletableFuture.supplyAsync(()->{ + return CompletableFuture.supplyAsync(() -> { try { - verifiedState = Stream - .concat(Arrays.asList(state).stream(), getTasks().stream() + verifiedState = + Stream.concat(Arrays.asList(state).stream(), getTasks().stream().filter(task->!task.getDescription().equals(Constants.DONE_TASK)) .flatMap(task -> task.getComputations().stream()).map(tc -> tc.getState())) - .max(new JobStateComparator()).get(); - + .max(new JobStateComparator()).get(); if (verifiedState != JobState.Finished && verifiedState != JobState.Canceled) { verifiedState = JobState.Failed; } - synchronized(BenchmarkJob.this) { - //test whether job was restarted - it sets running to null - if(!verifiedStateProcessed) { + synchronized (BenchmarkJob.this) { + // test whether job was restarted - it sets running to null + if (!verifiedStateProcessed) { verifiedState = null; - return doGetStateAsync(r->r.run()).getNow(null); - } + return doGetStateAsync(r -> r.run()).getNow(null); + } running = null; return verifiedState; } } finally { - synchronized(BenchmarkJob.this) { - if(running != null) { + synchronized (BenchmarkJob.this) { + if (running != null) { running = null; } } @@ -233,7 +236,7 @@ public class BenchmarkJobManager { public List<String> getActualOutput(List<SynchronizableFileType> content) { return computationAccessor.getActualOutput(content); } - + @Override public String toString() { return "" + getId(); @@ -365,6 +368,16 @@ public class BenchmarkJobManager { public java.util.Collection<String> getChangedFiles() { return job.getChangedFiles(); + } + + @Override + public List<Long> getFileSizes(List<String> names) { + return job.getFileSizes(names); + } + + @Override + public List<String> getFileContents(List<String> logs) { + return job.getFileContents(logs); }; }; diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java index fb92a8c287a4ba3e15ef253ccce02e5f6561d3e1..dd3ce0507d0be10acf7170cce0f1360630e85b94 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/Constants.java @@ -4,6 +4,7 @@ import java.util.LinkedHashMap; import java.util.Map; public interface Constants { + String PHONE = "123456789"; int HAAS_UPDATE_TIMEOUT = 30000; short UI_TO_HAAS_FREQUENCY_UPDATE_RATIO = 10; String HAAS_JOB_NAME = "HaaSSPIMBenchmark"; @@ -37,7 +38,7 @@ public interface Constants { put("define_output", "Define output"); put("hdf5_xml_output", "Define hdf5 output"); put("resave_hdf5_output", "Resave output to hdf5"); - put("done", "Done"); + put(DONE_TASK, "Done"); }}; String STATISTICS_TASK_NAME = "Task name"; @@ -50,4 +51,6 @@ public interface Constants { String STATISTICS_SUMMARY_FILENAME = "summary.csv"; String SUMMARY_FILE_HEADER = "Task;AvgMemoryUsage;AvgWallTime;MaxWallTime;TotalTime;JobCount"; + String DONE_TASK = "done"; + } diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/JobStateComparator.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/JobStateComparator.java index 09a568863ac634140c85fbc810d56e0b73e11d1e..6b312cb88b6761acec362c04c476de2049906b48 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/JobStateComparator.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/JobStateComparator.java @@ -14,7 +14,7 @@ public class JobStateComparator implements Comparator<JobState>{ priorities.put(state, priorities.size()); } - { + static { Arrays.asList(JobState.Finished,JobState.Queued, JobState.Running, JobState.Canceled, JobState.Failed).forEach(state->add(state)); } @Override diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/ResultFileTask.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/ResultFileTask.java index 7cb8b1ceca95e7588b676eec1d3b83f032e2c3eb..4f0bed3365cb2dc1fd08a856588365c88eb69df8 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/ResultFileTask.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/ResultFileTask.java @@ -41,7 +41,9 @@ public class ResultFileTask { .appendOptional(DateTimeFormatter.ofPattern("EEE MMM dd kk:mm:ss z yyyy")) .appendOptional(DateTimeFormatter.ofPattern("EEE MMM dd kk:mm:ss yyyy")).toFormatter(); Collection<Double> startTimeValues = retrieveValues(Constants.STATISTICS_RESOURCES_START_TIME) - .map(s -> (double) LocalDateTime.parse(s, formatter).toEpochSecond(ZoneOffset.UTC)) + .map(s -> s != null && !s.equals("null") + ? (double) LocalDateTime.parse(s, formatter).toEpochSecond(ZoneOffset.UTC) + : Double.NaN) .collect(Collectors.toList()); Collection<Double> wallTimeValues = retrieveValues(Constants.STATISTICS_RESOURCES_WALL_TIME) .map(s -> Double.parseDouble(s)).collect(Collectors.toList()); diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessor.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessor.java index d0283db80c1ae69815923886723074ecf57bf31b..3b1a6a9bbd69528d4eabc6c1c9ec41dec980e383 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessor.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessor.java @@ -1,6 +1,7 @@ package cz.it4i.fiji.haas_spim_benchmark.core; import java.util.Collection; +import java.util.List; import cz.it4i.fiji.haas.HaaSOutputHolder; @@ -11,6 +12,9 @@ public interface SPIMComputationAccessor extends HaaSOutputHolder { default boolean fileExists(String fileName) { return getChangedFiles().contains(FILE_SEPARATOR_UNIX + fileName); } - Collection<String> getChangedFiles(); + + List<Long> getFileSizes(List<String> names); + + List<String> getFileContents(List<String> logs); } diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessorDecoratorWithTimeout.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessorDecoratorWithTimeout.java index d308d8a4d015622e98f970d678eb789d2317d205..3f9b2ce48d1a6a3a2832d13241891cdf8613d3af 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessorDecoratorWithTimeout.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/SPIMComputationAccessorDecoratorWithTimeout.java @@ -18,10 +18,12 @@ public class SPIMComputationAccessorDecoratorWithTimeout implements SPIMComputat private final P_ResultCacheHolder<Set<String>> changedFilesCache; private final Map<SynchronizableFileType, Integer> allowedTypesIndices = new HashMap<>(); private final List<SynchronizableFileType> allowedTypes = new LinkedList<>(); + private SPIMComputationAccessor decorated; public SPIMComputationAccessorDecoratorWithTimeout(SPIMComputationAccessor decorated, Set<SynchronizableFileType> allowedTypes, long intervalForQueryInMs) { this.intervalForQueryInMs = intervalForQueryInMs; + this.decorated = decorated; initAllowedTypes(allowedTypes); outputCache = new P_ResultCacheHolder<List<String>>(x -> decorated.getActualOutput(this.allowedTypes)); changedFilesCache = new P_ResultCacheHolder<>(set -> { @@ -49,6 +51,16 @@ public class SPIMComputationAccessorDecoratorWithTimeout implements SPIMComputat return changedFilesCache.getResult(); } + @Override + public List<Long> getFileSizes(List<String> names) { + return decorated.getFileSizes(names); + } + + @Override + public List<String> getFileContents(List<String> logs) { + return decorated.getFileContents(logs); + } + private void initAllowedTypes(Set<SynchronizableFileType> allowedTypes) { for (SynchronizableFileType type : allowedTypes) { this.allowedTypes.add(type); diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/TaskComputation.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/TaskComputation.java index 15f1664cf52147f976726e3c78ec1c5a3652df09..4aacf63016dd8d92ee92a6c8fcbbd9dd09ae74e1 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/TaskComputation.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/core/TaskComputation.java @@ -2,15 +2,81 @@ package cz.it4i.fiji.haas_spim_benchmark.core; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Scanner; +import java.util.stream.Collectors; + +import org.apache.commons.math3.util.Pair; + +import com.google.common.collect.Streams; import cz.it4i.fiji.haas_java_client.JobState; import cz.it4i.fiji.haas_java_client.SynchronizableFileType; +//FIXME: TaskComputation 'done' should be Finished not Queued public class TaskComputation { + public static class Log { + final private String name; + final private String content; + + public Log(String name, String content) { + this.name = name; + this.content = content; + } + + public String getName() { + return name; + } + + public String getContent() { + return content; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Log other = (Log) obj; + if (content == null) { + if (other.content != null) + return false; + } else if (!content.equals(other.content)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + } + + public static class File { + final private String name; + final private long size; + + public File(String name, long size) { + this.name = name; + this.size = size; + } + + public String getName() { + return name; + } + + public long getSize() { + return size; + } + } + private final SPIMComputationAccessor computationAccessor; private final String taskDescription; private final int timepoint; @@ -19,13 +85,12 @@ public class TaskComputation { private int positionInOutput; private Collection<String> inputs; - @SuppressWarnings("unused") - private Collection<String> outputs; - private Collection<String> logs; + private Collection<String> outputs = Collections.emptyList(); + private Collection<String> logs = Collections.emptyList(); private Long id; private final List<BenchmarkError> errors; - + /** * Creates a TaskComputation object. At the time of creation, the job parameters * are not populated @@ -61,11 +126,10 @@ public class TaskComputation { return id; } - // TODO: Method stub public void update() { } - + /** * @return computations errors */ @@ -73,6 +137,13 @@ public class TaskComputation { return errors; } + public Collection<Log> getLogs() { + List<String> logNames = new LinkedList<>(logs); + List<String> contents = computationAccessor.getFileContents(logNames); + return Streams.<String, String, Log>zip(logNames.stream(), contents.stream(), + (name, content) -> new Log(name, content)).collect(Collectors.toList()); + } + /** * Populates parameters of the current object by searching the output * @@ -99,6 +170,17 @@ public class TaskComputation { return true; } + public Collection<String> getOutputs() { + return outputs; + } + + public Map<String, Long> getOutFileSizes() { + List<String> names = new LinkedList<>(outputs); + List<Long> sizes = computationAccessor.getFileSizes(names); + return Streams.zip(names.stream(), sizes.stream(), (name, size) -> new Pair<>(name, size)) + .collect(Collectors.toMap(p -> p.getFirst(), p -> p.getSecond())); + } + private void updateState() { // Should the state be queued, try to find out whether a log file exists diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java index 14a0ffddbee390b5e2453f3446d0b1ec4b0443eb..2dd990dff6715ed43d07a51a4025464dcca57d4e 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/BenchmarkSPIMController.java @@ -3,9 +3,10 @@ package cz.it4i.fiji.haas_spim_benchmark.ui; import java.awt.Desktop; import java.awt.Window; import java.io.IOException; -import java.util.Collection; import java.util.EnumSet; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -15,7 +16,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Function; -import java.util.function.Predicate; import javax.swing.WindowConstants; @@ -30,7 +30,6 @@ import cz.it4i.fiji.haas.ui.ModalDialogs; import cz.it4i.fiji.haas.ui.ProgressDialog; import cz.it4i.fiji.haas.ui.TableViewContextMenu; import cz.it4i.fiji.haas_java_client.JobState; -import cz.it4i.fiji.haas_java_client.SynchronizableFileType; import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager; import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob; import cz.it4i.fiji.haas_spim_benchmark.core.Constants; @@ -42,16 +41,9 @@ import javafx.scene.control.TableView; import javafx.scene.layout.BorderPane; import net.imagej.updater.util.Progress; +//FIXME: fix Exception during context menu request on task with N/A state public class BenchmarkSPIMController extends BorderPane implements CloseableControl, InitiableControl { - private static boolean notNullValue(ObservableValue<BenchmarkJob> j, Predicate<BenchmarkJob> pred) { - if (j == null || j.getValue() == null) { - return false; - } else { - return pred.test(j.getValue()); - } - } - @FXML private TableView<ObservableValue<BenchmarkJob>> jobs; @@ -89,8 +81,7 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont }, Constants.HAAS_UPDATE_TIMEOUT, Constants.HAAS_UPDATE_TIMEOUT); initTable(); initMenu(); - updateJobs(); - + executorServiceFX.execute(this::updateJobs); } private void initMenu() { @@ -99,46 +90,37 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> { job.getValue().startJob(p); registry.get(job.getValue()).update(); - }), job -> notNullValue(job, j -> j.getState() == JobState.Configuring || j.getState() == JobState.Finished - || j.getState() == JobState.Failed)); + }), job -> JavaFXRoutines.notNullValue(job, j -> j.getState() == JobState.Configuring + || j.getState() == JobState.Finished || j.getState() == JobState.Failed)); menu.addItem("Cancel job", job -> executeWSCallAsync("Canceling job", p -> { job.getValue().cancelJob(); registry.get(job.getValue()).update(); - }), job -> notNullValue(job, j -> j.getState() == JobState.Running)); + }), job -> JavaFXRoutines.notNullValue(job, j -> j.getState() == JobState.Running)); - menu.addItem("Show details", job -> { + menu.addItem("Execution details", job -> { try { new JobDetailWindow(root, job.getValue()).setVisible(true); } catch (IOException e) { - // TODO Auto-generated catch block log.error(e.getMessage(), e); } - }, job -> notNullValue(job, j -> j.getState() == JobState.Running || j.getState() == JobState.Finished - || j.getState() == JobState.Failed || j.getState() == JobState.Canceled)); + }, job -> JavaFXRoutines.notNullValue(job, + j -> j.getState() == JobState.Running || j.getState() == JobState.Finished + || j.getState() == JobState.Failed || j.getState() == JobState.Canceled)); menu.addItem("Download result", job -> executeWSCallAsync("Downloading data", p -> job.getValue().downloadData(p)), - job -> notNullValue(job, + job -> JavaFXRoutines.notNullValue(job, j -> EnumSet.of(JobState.Failed, JobState.Finished, JobState.Canceled).contains(j.getState()) && !j.downloaded())); menu.addItem("Download statistics", job -> executeWSCallAsync("Downloading data", p -> job.getValue().downloadStatistics(p)), - job -> notNullValue(job, j -> j.getState() == JobState.Finished)); + job -> JavaFXRoutines.notNullValue(job, j -> j.getState() == JobState.Finished)); menu.addItem("Explore errors", job -> job.getValue().exploreErrors(), - job -> notNullValue(job, j -> j.getState().equals(JobState.Failed))); - - menu.addItem("Show output", j -> { - new JobOutputView(root, executorServiceUI, j.getValue(), SynchronizableFileType.StandardErrorFile, - job -> job.getSnakemakeOutput(), Constants.HAAS_UPDATE_TIMEOUT); - new JobOutputView(root, executorServiceUI, j.getValue(), SynchronizableFileType.StandardOutputFile, - job -> job.getAnotherOutput(), Constants.HAAS_UPDATE_TIMEOUT); - }, job -> notNullValue(job, j -> EnumSet - .of(JobState.Failed, JobState.Finished, JobState.Running, JobState.Canceled).contains(j.getState()))); - menu.addItem("Open working directory", j -> open(j.getValue()), x -> notNullValue(x, j -> true)); - menu.addItem("Update table", job -> updateJobs(), j -> true); + job -> JavaFXRoutines.notNullValue(job, j -> j.getState().equals(JobState.Failed))); + menu.addItem("Open working directory", j -> open(j.getValue()), x -> JavaFXRoutines.notNullValue(x, j -> true)); } private void open(BenchmarkJob j) { @@ -180,15 +162,15 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont if (manager == null) { return; } + Progress progress = showProgress + ? ModalDialogs.doModal(new ProgressDialog(root, "Updating jobs"), WindowConstants.DO_NOTHING_ON_CLOSE) + : new DummyProgress(); + executorServiceWS.execute(() -> { - Progress progress = showProgress - ? ModalDialogs.doModal(new ProgressDialog(root, "Updating jobs"), - WindowConstants.DO_NOTHING_ON_CLOSE) - : new DummyProgress(); try { - Collection<BenchmarkJob> jobs = manager.getJobs(); - //jobs.forEach(bj->bj.getStateAsync(executorServiceJobState)); + List<BenchmarkJob> jobs = new LinkedList<>(manager.getJobs()); + jobs.sort((bj1, bj2) -> (int) (bj1.getId() - bj2.getId())); Set<ObservableValue<BenchmarkJob>> actual = new HashSet<>(this.jobs.getItems()); for (BenchmarkJob bj : jobs) { registry.addIfAbsent(bj); @@ -210,13 +192,13 @@ public class BenchmarkSPIMController extends BorderPane implements CloseableCont } private void initTable() { - registry = new ObservableBenchmarkJobRegistry(bj -> remove(bj),executorServiceJobState); + registry = new ObservableBenchmarkJobRegistry(bj -> remove(bj), executorServiceJobState); setCellValueFactory(0, j -> j.getId() + ""); - setCellValueFactoryCompletable(1, - j -> j.getStateAsync(executorServiceJobState).thenApply(state -> "" + state)); + setCellValueFactoryCompletable(1, j -> j.getStateAsync(executorServiceJobState).thenApply(state -> "" + state)); setCellValueFactory(2, j -> j.getCreationTime().toString()); setCellValueFactory(3, j -> j.getStartTime().toString()); setCellValueFactory(4, j -> j.getEndTime().toString()); + // jobs.getSortOrder().add(jobs.getColumns().get(0)); } private void remove(BenchmarkJob bj) { diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFileInfo.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFileInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..60d2855437c4df3f77eeb1fbbef26c17ada17c8c --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFileInfo.java @@ -0,0 +1,12 @@ +package cz.it4i.fiji.haas_spim_benchmark.ui; + +public interface RemoteFileInfo { + + /** + * + * @return size of file or -1 in case of absence + */ + Long getSize(); + + String getName(); +} diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFilesInfo.fxml b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFilesInfo.fxml new file mode 100644 index 0000000000000000000000000000000000000000..d16c28005d7c4d5544e947867934119c805b160a --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFilesInfo.fxml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.TableColumn?> +<?import javafx.scene.control.TableView?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> + +<fx:root 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.RemoteFilesInfoControl"> + <center> + + <HBox> + <children> + + <TableView fx:id="files" HBox.hgrow="ALWAYS"> + <columns> + <TableColumn prefWidth="450.0" text="File name" /> + <TableColumn minWidth="150.0" prefWidth="0.0" text="Size of file" /> + </columns> + </TableView> + </children> + <padding> + <Insets bottom="1.0" left="1.0" right="1.0" top="1.0" /> + </padding> + </HBox> + </center> + +</fx:root> diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFilesInfoControl.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFilesInfoControl.java new file mode 100644 index 0000000000000000000000000000000000000000..3b2f64db03ace0d8c2ca91a1833ac7e3931c2755 --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/RemoteFilesInfoControl.java @@ -0,0 +1,62 @@ +package cz.it4i.fiji.haas_spim_benchmark.ui; + +import java.awt.Window; +import java.util.List; +import java.util.function.Function; + +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cz.it4i.fiji.haas.ui.CloseableControl; +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.control.TableView; +import javafx.scene.layout.BorderPane; + +public class RemoteFilesInfoControl extends BorderPane implements CloseableControl, InitiableControl { + + @SuppressWarnings("unused") + private static Logger log = LoggerFactory + .getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.RemoteFilesInfoControl.class); + + @SuppressWarnings("unused") + private Window root; + + @FXML + private TableView<ObservableValue<RemoteFileInfo>> files; + + public RemoteFilesInfoControl() { + JavaFXRoutines.initRootAndController("RemoteFilesInfo.fxml", this); + } + + public void setFiles(List<ObservableValue<RemoteFileInfo>> files) { + files.forEach(file -> this.files.getItems().add(file)); + } + + @Override + public void init(Window parameter) { + this.root = parameter; + initTable(); + } + + @Override + public void close() { + + } + + private void initTable() { + JavaFXRoutines.setCellValueFactory(files, 0, file -> file.getName()); + JavaFXRoutines.setCellValueFactory(files, 1, + (Function<RemoteFileInfo, String>) file -> file.getSize() >= 0 ? formatSize(file.getSize()) + : "Not exists"); + + } + + private String formatSize(long size) { + return FileUtils.byteCountToDisplaySize(size); + } + +} diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressView.fxml b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressView.fxml index 294e40a69f10160d5ed436a4855a311c3d5c9a02..b765d90ce6c58696ac1be866c03b90ac93635eb3 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressView.fxml +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressView.fxml @@ -1,22 +1,20 @@ <?xml version="1.0" encoding="UTF-8"?> +<?import javafx.geometry.Insets?> <?import javafx.scene.control.TableColumn?> <?import javafx.scene.control.TableView?> <?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.HBox?> -<?import javafx.geometry.Insets?> -<fx:root 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.SPIMPipelineProgressViewController"> +<fx:root 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.SPIMPipelineProgressViewController"> <center> <HBox> <children> - <TableView fx:id="tasks" HBox.hgrow="ALWAYS"> + <TableView fx:id="tasks" stylesheets="@style.css" HBox.hgrow="ALWAYS"> <columns> - <TableColumn prefWidth="101.0" text="Task name" /> + <TableColumn prefWidth="179.0" text="Task name" /> </columns> </TableView> diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java index 282ecd41623affc6ea6d6afeefe9e3f2df3bafcc..2b3de110b2065a43dbcf1581996bd65bd2bd797e 100644 --- a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressViewController.java @@ -1,5 +1,7 @@ package cz.it4i.fiji.haas_spim_benchmark.ui; +import java.awt.Window; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -12,8 +14,16 @@ import java.util.concurrent.Executors; import java.util.function.Function; import java.util.stream.Collectors; +import javax.swing.WindowConstants; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import cz.it4i.fiji.haas.ui.CloseableControl; +import cz.it4i.fiji.haas.ui.InitiableControl; import cz.it4i.fiji.haas.ui.JavaFXRoutines; +import cz.it4i.fiji.haas.ui.ModalDialogs; +import cz.it4i.fiji.haas.ui.TableViewContextMenu; import cz.it4i.fiji.haas_java_client.JobState; import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob; import cz.it4i.fiji.haas_spim_benchmark.core.Constants; @@ -21,29 +31,28 @@ import cz.it4i.fiji.haas_spim_benchmark.core.FXFrameExecutorService; import cz.it4i.fiji.haas_spim_benchmark.core.Task; import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation; import javafx.beans.value.ObservableValue; +import javafx.beans.value.ObservableValueBase; import javafx.fxml.FXML; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.layout.BorderPane; import javafx.scene.paint.Color; -public class SPIMPipelineProgressViewController extends BorderPane implements CloseableControl { +public class SPIMPipelineProgressViewController extends BorderPane implements CloseableControl, InitiableControl { + public final static Logger log = LoggerFactory + .getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.SPIMPipelineProgressViewController.class); + private static final String EMPTY_VALUE = "\u2007\u2007\u2007"; private static final int PREFERRED_WIDTH = 900; - protected static final String RUNNING_STATE_COMPUTATION = Color.YELLOW.toString(); - - protected static final String FINISHED_STATE_COMPUTATION = null; - - protected static final String UNKNOWN_STATE_COMPUTATION = Color.GRAY.toString(); - private static final Map<JobState, Color> taskExecutionState2Color = new HashMap<>(); static { - taskExecutionState2Color.put(JobState.Running, Color.YELLOW); - taskExecutionState2Color.put(JobState.Finished, Color.GREEN); - taskExecutionState2Color.put(JobState.Failed, Color.RED); + taskExecutionState2Color.put(JobState.Running, Color.rgb(0xF2, 0xD5, 0x39)); + taskExecutionState2Color.put(JobState.Finished, Color.rgb(0x41, 0xB2, 0x80)); + taskExecutionState2Color.put(JobState.Failed, Color.rgb(0xFF, 0x51, 0x3D)); + taskExecutionState2Color.put(JobState.Queued, Color.rgb(0x30, 0xA2, 0xCC)); taskExecutionState2Color.put(JobState.Unknown, Color.GRAY); } @@ -70,11 +79,11 @@ public class SPIMPipelineProgressViewController extends BorderPane implements Cl private ObservableTaskRegistry registry; private ExecutorService executorServiceWS; private Executor executorFx = new FXFrameExecutorService(); + private Window root; public SPIMPipelineProgressViewController() { executorServiceWS = Executors.newSingleThreadExecutor(); init(); - } public SPIMPipelineProgressViewController(BenchmarkJob job) { @@ -98,12 +107,54 @@ public class SPIMPipelineProgressViewController extends BorderPane implements Cl executorServiceWS.shutdown(); } + @Override + public void init(Window parameter) { + this.root = parameter; + } + private void init() { JavaFXRoutines.initRootAndController("SPIMPipelineProgressView.fxml", this); tasks.setPrefWidth(PREFERRED_WIDTH); timer = new Timer(); registry = new ObservableTaskRegistry(task -> tasks.getItems().remove(registry.get(task))); + TableViewContextMenu<ObservableValue<Task>> menu = new TableViewContextMenu<ObservableValue<Task>>(this.tasks); + menu.addItem("Open view", (task, columnIndex) -> proof(task, columnIndex), + (x, columnIndex) -> check(x, columnIndex)); + } + + private boolean check(ObservableValue<Task> x, Integer columnIndex) { + boolean result = x != null && 0 < columnIndex &&columnIndex - 1 < x.getValue().getComputations().size(); + return result; + } + + private void proof(ObservableValue<Task> task, int columnIndex) { + ModalDialogs.doModal(new TaskComputationWindow(root, task.getValue().getComputations().get(columnIndex - 1)), + WindowConstants.DISPOSE_ON_CLOSE); + } + + static void add(Collection<ObservableValue<RemoteFileInfo>> files, String name, long size) { + RemoteFileInfo file = new RemoteFileInfo() { + + @Override + public Long getSize() { + return size; + } + + @Override + public String getName() { + return name; + } + + }; + ObservableValue<RemoteFileInfo> value = new ObservableValueBase<RemoteFileInfo>() { + + @Override + public RemoteFileInfo getValue() { + return file; + } + }; + files.add(value); } private void fillTable() { @@ -162,6 +213,7 @@ public class SPIMPipelineProgressViewController extends BorderPane implements Cl cell.setStyle(""); } else { cell.setText(EMPTY_VALUE); + cell.getStyleClass().add("bordered-class"); cell.setStyle("-fx-background-color: " + getColorTaskExecState(val.getState())); } })); diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationAdapter.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..40c7fa85d825b3ffe1f06f9f96ea20156bcfea8e --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationAdapter.java @@ -0,0 +1,170 @@ +package cz.it4i.fiji.haas_spim_benchmark.ui; + +import java.io.Closeable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cz.it4i.fiji.haas_spim_benchmark.core.Constants; +import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation; +import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation.Log; +import javafx.beans.value.ObservableValue; +import javafx.beans.value.ObservableValueBase; + +public class TaskComputationAdapter implements Closeable { + + public final static Logger log = LoggerFactory + .getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.TaskComputationAdapter.class); + + private final TaskComputation computation; + + private final List<ObservableValue<RemoteFileInfo>> outputs = new LinkedList<>(); + + private final List<ObservableLog> logs = new LinkedList<>(); + + private Timer timer; + + public TaskComputationAdapter(TaskComputation computation) { + this.computation = computation; + timer = new Timer(); + } + + public void init() { + Map<String, Long> sizes = computation.getOutFileSizes(); + computation.getOutputs().forEach(outputFile -> addOutputFile(outputFile, sizes.get(outputFile))); + computation.getLogs().forEach(log -> logs.add(new ObservableLog(log))); + synchronized (this) { + if(timer != null) { + timer.schedule(new P_TimerTask(), Constants.HAAS_TIMEOUT, Constants.HAAS_TIMEOUT); + } + } + + } + + @Override + public synchronized void close() { + timer.cancel(); + timer = null; + } + + public List<ObservableValue<RemoteFileInfo>> getOutputs() { + return outputs; + } + + public List<ObservableLog> getLogs() { + return logs; + } + + private void addOutputFile(String outputFile, Long size) { + outputs.add(new ObservableOutputFile(outputFile, size)); + } + + public static class ObservableLog { + + private final String name; + + private final P_ObservableString value; + + public ObservableLog(Log content) { + this.value = new P_ObservableString(content.getContent()); + this.name = content.getName(); + } + + public String getName() { + return name; + } + + public ObservableValue<String> getContent() { + return value; + } + + public void setContentValue(Log log) { + if (!getName().equals(log.getName())) { + throw new IllegalArgumentException( + "this.name=" + getName() + ", log.name=" + log.getName()); + } + value.setValue(log.getContent()); + } + + private class P_ObservableString extends ObservableValueBase<String> { + + private String value; + + public P_ObservableString(String value) { + this.value = value; + } + + @Override + public String getValue() { + return value; + } + + public void setValue(String value) { + if(this.value != null && !this.value.equals(value) || + value != null && !value.equals(this.value)) { + this.value = value; + fireValueChangedEvent(); + } + } + } + + } + + private class ObservableOutputFile extends ObservableValueBase<RemoteFileInfo> { + + private final String name; + + private Long size; + + private final RemoteFileInfo value = new RemoteFileInfo() { + + @Override + public Long getSize() { + return size; + } + + @Override + public String getName() { + return name; + } + }; + + public ObservableOutputFile(String name, Long size) { + this.name = name; + this.size = size; + } + + @Override + public RemoteFileInfo getValue() { + return value; + } + + public void setSize(Long newValue) { + Long oldValue = size; + size = newValue; + if (oldValue != newValue && oldValue != null && !oldValue.equals(newValue)) { + fireValueChangedEvent(); + } + } + } + + private class P_TimerTask extends TimerTask { + + @Override + public void run() { + Map<String, Long> sizes = computation.getOutFileSizes(); + Map<String, Log> logs = computation.getLogs().stream() + .collect(Collectors.<Log, String, Log>toMap((Log log) -> log.getName(), (Log log) -> log)); + TaskComputationAdapter.this.logs + .forEach(log -> ((ObservableLog) log).setContentValue(logs.get(log.getName()))); + outputs.forEach(value -> ((ObservableOutputFile) value).setSize(sizes.get(value.getValue().getName()))); + } + + } +} diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationControl.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationControl.java new file mode 100644 index 0000000000000000000000000000000000000000..c354adf04b1badb986ea9aa9d159c1fa0bc0e27a --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationControl.java @@ -0,0 +1,87 @@ +package cz.it4i.fiji.haas_spim_benchmark.ui; + +import java.awt.Window; +import java.util.Collection; +import java.util.LinkedList; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.swing.WindowConstants; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import cz.it4i.fiji.haas.ui.CloseableControl; +import cz.it4i.fiji.haas.ui.InitiableControl; +import cz.it4i.fiji.haas.ui.JavaFXRoutines; +import cz.it4i.fiji.haas.ui.ModalDialogs; +import cz.it4i.fiji.haas.ui.ProgressDialog; +import cz.it4i.fiji.haas_spim_benchmark.core.FXFrameExecutorService; +import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation; +import cz.it4i.fiji.haas_spim_benchmark.ui.TaskComputationAdapter.ObservableLog; +import javafx.fxml.FXML; +import javafx.scene.Node; +import javafx.scene.control.Tab; +import javafx.scene.control.TabPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +public class TaskComputationControl extends TabPane implements CloseableControl, InitiableControl { + public final static Logger log = LoggerFactory.getLogger(cz.it4i.fiji.haas_spim_benchmark.ui.TaskComputationControl.class); + + private TaskComputationAdapter adapter; + + private Executor uiExecutor = new FXFrameExecutorService(); + + private ExecutorService wsExecutorService = Executors.newSingleThreadExecutor(); + @FXML + private RemoteFilesInfoControl remoteFilesInfo; + + private TaskComputation computation; + + + public TaskComputationControl(TaskComputation computation) { + JavaFXRoutines.initRootAndController("TaskComputationView.fxml", this); + this.computation = computation; + } + + @Override + public void init(Window parameter) { + wsExecutorService.execute(() -> { + ProgressDialog dialog = ModalDialogs.doModal(new ProgressDialog(parameter, "Updating infos..."), + WindowConstants.DO_NOTHING_ON_CLOSE); + try { + adapter = new TaskComputationAdapter(computation); + adapter.init(); + } finally { + dialog.done(); + } + remoteFilesInfo.setFiles(adapter.getOutputs()); + remoteFilesInfo.init(parameter); + Collection<Runnable> runs = new LinkedList<>(); + for (ObservableLog log : adapter.getLogs()) { + LogViewControl logViewControl = new LogViewControl(); + logViewControl.setObservable(log.getContent()); + runs.add(() -> addTab(log.getName(), logViewControl)); + } + uiExecutor.execute(() -> runs.forEach(r -> r.run())); + }); + } + + private void addTab(String title, Node control) { + Tab t = new Tab(title); + t.setClosable(false); + HBox hbox = new HBox(); + HBox.setHgrow(control, Priority.ALWAYS); + hbox.getChildren().add(control); + t.setContent(hbox); + getTabs().add(t); + } + @Override + public void close() { + adapter.close(); + wsExecutorService.shutdown(); + } + + +} diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationView.fxml b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationView.fxml new file mode 100644 index 0000000000000000000000000000000000000000..6964bc2e111b00a7c2324beab046ac8ddc933f34 --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationView.fxml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import cz.it4i.fiji.haas_spim_benchmark.ui.RemoteFilesInfoControl?> +<?import javafx.scene.control.Tab?> +<?import javafx.scene.control.TabPane?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.HBox?> + + +<fx:root type="TabPane" xmlns:fx="http://javafx.com/fxml/1" + xmlns="http://javafx.com/javafx/8.0.65" fx:controller="cz.it4i.fiji.haas_spim_benchmark.ui.TaskComputationControl"> + <Tab closable="false" text="Output files"> + <content> + <HBox> + <RemoteFilesInfoControl fx:id="remoteFilesInfo" + HBox.hgrow="ALWAYS" /> + + </HBox> + </content> + </Tab> +</fx:root> diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationWindow.java b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..98f8f2aed4ea8afcefc63d18b253940befd16961 --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/TaskComputationWindow.java @@ -0,0 +1,18 @@ +package cz.it4i.fiji.haas_spim_benchmark.ui; + +import java.awt.Window; + +import cz.it4i.fiji.haas.ui.FXFrame; +import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation; + +public class TaskComputationWindow extends FXFrame<TaskComputationControl> { + + private static final long serialVersionUID = 1L; + + public TaskComputationWindow(Window applicationFrame,TaskComputation computation) { + super(applicationFrame,()->new TaskComputationControl(computation)); + + } + + +} diff --git a/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/style.css b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/style.css new file mode 100644 index 0000000000000000000000000000000000000000..e5bc5bca424e96c7f7182f288beafcf16f52ce8a --- /dev/null +++ b/haas-spim-benchmark/src/main/java/cz/it4i/fiji/haas_spim_benchmark/ui/style.css @@ -0,0 +1,7 @@ +.table-row-cell { + -fx-table-cell-border-color: #909090; +} + +.bordered-class { + -fx-background-insets:1 1 1 1; +} \ No newline at end of file diff --git a/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/RunRemoteFilesView.java b/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/RunRemoteFilesView.java new file mode 100644 index 0000000000000000000000000000000000000000..fc6190b4024ab749e97c2a70152725f8970bf29a --- /dev/null +++ b/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/RunRemoteFilesView.java @@ -0,0 +1,54 @@ +package cz.it4i.fiji.haas; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import cz.it4i.fiji.haas_spim_benchmark.ui.RemoteFileInfo; +import cz.it4i.fiji.haas_spim_benchmark.ui.RemoteFilesInfoControl; +import javafx.beans.value.ObservableValue; +import javafx.beans.value.ObservableValueBase; + +public class RunRemoteFilesView { + + + public static void main(String[] args) { + List<ObservableValue<RemoteFileInfo>> files = new LinkedList<>(); + add(files, "Some file.txt", 100025456); + + @SuppressWarnings("serial") + class Window extends cz.it4i.fiji.haas.ui.FXFrame<RemoteFilesInfoControl>{ + public Window() { + super(()-> new RemoteFilesInfoControl()); + } + } + + new Window().setVisible(true); + } + + static void add(Collection<ObservableValue<RemoteFileInfo>> files, String name, long size) { + RemoteFileInfo file = new RemoteFileInfo() { + + @Override + public Long getSize() { + return size; + } + + @Override + public String getName() { + return name; + } + + }; + ObservableValue<RemoteFileInfo> value = new ObservableValueBase<RemoteFileInfo>() { + + @Override + public RemoteFileInfo getValue() { + return file; + } + }; + + files.add(value); + } + +} diff --git a/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/RunSPIMPipelineView.java b/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/RunSPIMPipelineView.java deleted file mode 100644 index c73535a5e9bfa4958469dfce131be4a0ab0295e0..0000000000000000000000000000000000000000 --- a/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/RunSPIMPipelineView.java +++ /dev/null @@ -1,21 +0,0 @@ -package cz.it4i.fiji.haas; - -import cz.it4i.fiji.haas.ui.FXFrameNative; - -public class RunSPIMPipelineView { - - - public static void main(String[] args) { - class Window extends FXFrameNative<SPIMPipelineProgressViewController>{ - - public Window() { - super(()-> new SPIMPipelineProgressViewController()); - - } - - } - - new Window().setVisible(true); - } - -} diff --git a/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/SPIMPipelineProgressViewController.java b/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/SPIMPipelineProgressViewController.java deleted file mode 100644 index d3bc5de9384b8a5594ac8470049a4c738a3f5732..0000000000000000000000000000000000000000 --- a/haas-spim-benchmark/src/test/java/cz/it4i/fiji/haas/SPIMPipelineProgressViewController.java +++ /dev/null @@ -1,115 +0,0 @@ -package cz.it4i.fiji.haas; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -import cz.it4i.fiji.haas.ui.CloseableControl; -import cz.it4i.fiji.haas.ui.JavaFXRoutines; -import cz.it4i.fiji.haas.ui.ResizeableControl; -import cz.it4i.fiji.haas_java_client.JobState; -import javafx.beans.value.ObservableValue; -import javafx.beans.value.ObservableValueBase; -import javafx.fxml.FXML; -import javafx.scene.control.TableCell; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableView; -import javafx.scene.layout.BorderPane; -import javafx.scene.paint.Color; - -public class SPIMPipelineProgressViewController extends BorderPane implements CloseableControl, ResizeableControl { - - protected static final String RUNNING_STATE_COMPUTATION = Color.YELLOW.toString(); - - protected static final String FINISHED_STATE_COMPUTATION = null; - - protected static final String UNKNOWN_STATE_COMPUTATION = Color.GRAY.toString(); - - private final Map<JobState, Color> taskExecutionState2Color = new HashMap<>(); - { - taskExecutionState2Color.put(JobState.Running, Color.YELLOW); - taskExecutionState2Color.put(JobState.Finished, Color.GREEN); - taskExecutionState2Color.put(JobState.Failed, Color.RED); - taskExecutionState2Color.put(JobState.Unknown, Color.GRAY); - } - - private String getColorTaskExecState(JobState jobState) { - Color result = null; - if (jobState == null) { - result = Color.GRAY; - } else { - result = taskExecutionState2Color.get(jobState); - } - return toCss(result != null ? result : Color.ORANGE); - } - - private static String toCss(Color color) { - return "rgb(" + Math.round(color.getRed() * 255.0) + "," + Math.round(color.getGreen() * 255.0) + "," - + Math.round(color.getBlue() * 255.0) + ")"; - } - - @FXML - public TableView<ObservableValue<String>> tasks; - - public SPIMPipelineProgressViewController() { - init(); - } - - public void close() { - - } - - @Override - public void setSize(double width, double height) { - tasks.setPrefSize(width, height); - } - - private void init() { - JavaFXRoutines.initRootAndController("SPIMPipelineProgressView.fxml", this); - fillTable(); - - } - - private void fillTable() { - - JavaFXRoutines.setCellValueFactory(this.tasks, 0, (Function<String, String>) v -> v); - for (int i = 1; i <= 91; i++) { - this.tasks.getColumns().add(new TableColumn<>(i + "")); - constructCellFactory(i); - } - for (int i = 0; i < 10; i++) { - tasks.getItems().add(new ObservableValueBase<String>() { - - @Override - public String getValue() { - return "Value"; - } - - }); - } - - } - - @SuppressWarnings("unchecked") - private void constructCellFactory(int index) { - JavaFXRoutines.setCellValueFactory(this.tasks, index, (Function<String, String>) v -> { - return v; - }); - ((TableColumn<ObservableValue<String>, String>) this.tasks.getColumns().get(index)).setCellFactory(column -> { - TableCell<ObservableValue<String>, String> result = new TableCell<ObservableValue<String>, String>() { - - @Override - protected void updateItem(String computation, boolean empty) { - if (computation == null || empty) { - setText(null); - setStyle(""); - } else { - setText("\u2007\u2007\u2007"); - setStyle("-fx-background-color: " + getColorTaskExecState(JobState.Finished)); - } - } - }; - return result; - }); - } -} diff --git a/java-scpclient/src/main/java/cz/it4i/fiji/scpclient/ScpClient.java b/java-scpclient/src/main/java/cz/it4i/fiji/scpclient/ScpClient.java index 49247986b3fd2a1234021e7647ea23366173ad1c..a25697caf0d88cfb3c9daa69c7429fc79710fb06 100644 --- a/java-scpclient/src/main/java/cz/it4i/fiji/scpclient/ScpClient.java +++ b/java-scpclient/src/main/java/cz/it4i/fiji/scpclient/ScpClient.java @@ -23,6 +23,7 @@ import com.jcraft.jsch.SftpException; import com.jcraft.jsch.UserInfo; public class ScpClient implements Closeable { + private String hostName; private String username; private JSch jsch = new JSch(); @@ -314,6 +315,15 @@ public class ScpClient implements Closeable { return null; } + @Override + public void close() { + if (session != null && session.isConnected()) { + //log.info("disconnect"); + session.disconnect(); + session = null; + } + } + private int getBufferSize() { return 1024 * 1024; } @@ -327,6 +337,7 @@ public class ScpClient implements Closeable { session.setUserInfo(ui); } if (!session.isConnected()) { + //log.info("connect"); session.connect(); } return session; @@ -392,12 +403,4 @@ public class ScpClient implements Closeable { } return b; } - - @Override - public void close() { - if (session != null && session.isConnected()) { - session.disconnect(); - session = null; - } - } }