use of gov.sandia.n2a.host.Host in project n2a by frothga.
the class PanelRun method delete.
public void delete(TreePath[] paths) {
if (paths.length == 0)
return;
// The node that will be focused after all the deletes are done.
NodeBase nextSelection = null;
TreePath leadSelection = tree.getLeadSelectionPath();
if (leadSelection != null)
nextSelection = (NodeBase) leadSelection.getLastPathComponent();
int firstRow = Integer.MAX_VALUE;
int lastRow = 0;
for (int i = 0; i < paths.length; i++) {
TreePath path = paths[i];
// Ensure that we don't try to delete something twice.
NodeBase node = (NodeBase) path.getLastPathComponent();
if (node.markDelete) {
paths[i] = null;
continue;
}
node.markDelete = true;
// Current focus is a node that will be deleted. This is almost always the case, except when jobs are deleted by the Studies panel.
if (nextSelection == node)
nextSelection = null;
// In some cases (such as ctrl-click), the rows may not be in ascending order.
int row = tree.getRowForPath(path);
firstRow = Math.min(firstRow, row);
lastRow = Math.max(lastRow, row);
}
// No rows passed the filter above (because they were already selected).
if (firstRow == Integer.MAX_VALUE)
return;
NodeBase firstSelection = (NodeBase) tree.getPathForRow(firstRow).getLastPathComponent();
NodeBase lastSelection = (NodeBase) tree.getPathForRow(lastRow).getLastPathComponent();
if (nextSelection == null)
nextSelection = (NodeBase) lastSelection.getNextSibling();
if (nextSelection != null) {
// Could be root. Root is never selected, so the following test works correctly in that case.
NodeBase parent = (NodeBase) nextSelection.getParent();
if (// next sibling will also die, so need next sibling of parent.
tree.isPathSelected(new TreePath(parent.getPath()))) {
nextSelection = (NodeBase) parent.getNextSibling();
}
}
// If this exists, then it is guaranteed to continue to exist after deletion.
if (nextSelection == null)
nextSelection = (NodeBase) firstSelection.getPreviousSibling();
// "firstSelection" could be first file under a job, or first job in tree. In the latter case, the tree will be empty after delete.
if (nextSelection == null)
nextSelection = (NodeBase) firstSelection.getParent();
if (// Tree will be empty after delete.
nextSelection == root) {
// Shut down the display thread.
synchronized (displayText) {
if (displayThread != null) {
displayThread.stop = true;
displayThread = null;
}
// All access to this happens on EDT, so safe.
displayNode = null;
displayText.setText("");
}
displayChart.buttonBar.setVisible(false);
if (displayPane.getViewport().getView() != displayText)
displayPane.setViewportView(displayText);
} else // Set the new selection. This will not be touched by the delete process.
{
TreePath path = new TreePath(nextSelection.getPath());
tree.setSelectionPath(path);
tree.scrollPathToVisible(path);
}
// Ensure that strikethru marks will be displayed to user.
tree.repaint();
// Spawn the rest of the delete process off to a separate thread.
// The tree will be updated on the EDT as work progresses.
Thread deleteThread = new Thread("Delete Jobs") {
public void run() {
Map<Host, HostDeleteThread> hostThreads = new HashMap<Host, HostDeleteThread>();
Set<NodeJob> parents = new HashSet<NodeJob>();
for (TreePath path : paths) {
if (path == null)
continue;
final NodeBase node = (NodeBase) path.getLastPathComponent();
if (node instanceof NodeJob) {
NodeJob job = (NodeJob) node;
parents.add(job);
synchronized (job) {
if (job.complete < 1 || job.complete == 3) {
// It's important that the job not have resources locked in the directory when we try to delete it.
// If the job is still running, downgrade the delete request to a kill request.
// The user will have to hit delete again, once the job dies.
job.stop();
job.markDelete = false;
EventQueue.invokeLater(new Runnable() {
public void run() {
tree.repaint(tree.getPathBounds(new TreePath(job.getPath())));
}
});
continue;
}
}
} else {
if (parents.contains((NodeJob) node.getParent()))
continue;
}
NodeJob job;
if (node instanceof NodeJob) {
job = (NodeJob) node;
// Signal the monitor thread to drop this job.
synchronized (job) {
job.deleted = true;
}
synchronized (jobNodes) {
jobNodes.remove(job.key);
}
} else {
job = (NodeJob) node.getParent();
}
Host env = Host.get(job.getSource());
HostDeleteThread t = hostThreads.get(env);
if (t == null) {
t = new HostDeleteThread(env);
t.setDaemon(true);
t.start();
hostThreads.put(env, t);
}
synchronized (t.nodes) {
t.nodes.add(node);
}
}
for (HostDeleteThread t : hostThreads.values()) t.allQueued = true;
}
};
// It's OK if this work is interrupted. Any undeleted item will simply show up in the tree on next launch, and the user can try again.
deleteThread.setDaemon(true);
deleteThread.start();
}
use of gov.sandia.n2a.host.Host in project n2a by frothga.
the class NodeJob method reset.
/**
* Remove all files from the job dir except the main job file.
* This allows the job to restart cleanly, without file-creation conflicts.
*/
public synchronized void reset() {
// Reset variables to initial state.
complete = -1;
dateStarted = null;
dateFinished = null;
expectedSimTime = 0;
lastMonitored = 0;
lastActive = 0;
lastDisplay = 0;
// Purge files
Host localhost = Host.get();
MNode source = getSource();
Path localJobDir = Host.getJobDir(Host.getLocalResourceDir(), source);
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(localJobDir)) {
for (Path path : dirStream) {
if (path.endsWith("job"))
continue;
// deleteTree() works for both files and dirs, and also absorbs most exceptions.
localhost.deleteTree(path);
}
} catch (IOException e) {
e.printStackTrace();
}
PanelRun panelRun = PanelRun.instance;
if (!panelRun.tree.isCollapsed(new TreePath(getPath())))
build(panelRun.tree);
}
use of gov.sandia.n2a.host.Host in project n2a by frothga.
the class NodeJob method monitorProgress.
public synchronized void monitorProgress() {
if (deleted)
return;
if (complete >= 1 && complete != 3)
return;
// Limit monitoring to no more than once per second.
long elapsed = System.currentTimeMillis() - lastMonitored;
long wait = 1000 - elapsed;
if (wait > 0) {
try {
Thread.sleep(wait);
} catch (InterruptedException e) {
}
}
lastMonitored = System.currentTimeMillis();
float oldComplete = complete;
MNode source = getSource();
Host env = Host.get(source);
Path localJobDir = Host.getJobDir(Host.getLocalResourceDir(), source);
// If job is remote, attempt to grab its state files.
// TODO: handle remote jobs waiting in queue. Plan is to update "started" file with queue status.
Path finished = localJobDir.resolve("finished");
if (!Files.exists(finished) && env instanceof Remote) {
@SuppressWarnings("resource") Remote remote = (Remote) env;
if (remote.isConnected() || remote.isEnabled()) {
try {
Path remoteJobDir = Host.getJobDir(env.getResourceDir(), source);
Path remoteFinished = remoteJobDir.resolve("finished");
// throws an exception if the remote file does not exist
Files.copy(remoteFinished, finished);
} catch (Exception e) {
}
}
}
if (complete == -1) {
Path started = localJobDir.resolve("started");
if (Files.exists(started)) {
complete = 0;
dateStarted = new Date(Host.lastModified(started));
lastActive = dateStarted.getTime();
}
}
Backend simulator = Backend.getBackend(source.get("backend"));
if (complete >= 0 && complete < 1) {
float percentDone = 0;
if (expectedSimTime == 0)
expectedSimTime = new UnitValue(source.get("duration")).get();
if (expectedSimTime > 0)
percentDone = (float) (simulator.currentSimTime(source) / expectedSimTime);
if (Files.exists(finished)) {
checkFinished(finished);
} else {
try {
long currentTime = System.currentTimeMillis();
if (simulator.isActive(source)) {
lastActive = currentTime;
} else if (currentTime - lastActive > activeTimeout) {
if (percentDone < 1) {
// Give it up for dead.
Files.copy(new ByteArrayInputStream("dead".getBytes("UTF-8")), finished);
complete = 4;
} else // Job appears to be actually finished, even though "finished" hasn't been written yet.
{
// Fake the "finished" file. This might be overwritten later by the batch process.
// Most likely, it will also report that we succeeded, so presume that things are fine.
Files.copy(new ByteArrayInputStream("success".getBytes("UTF-8")), finished);
complete = 1;
}
}
} catch (Exception e) {
}
}
if (complete >= 0 && complete < 1)
complete = Math.min(0.99999f, percentDone);
}
if (complete == 3) {
// Check if process is still lingering
if (!simulator.isActive(source))
complete = 4;
}
PanelRun panelRun = PanelRun.instance;
PanelStudy panelStudy = PanelStudy.instance;
// Probably running headless, so skip all UI updates.
if (panelRun == null)
return;
if (complete != oldComplete) {
EventQueue.invokeLater(new Runnable() {
public void run() {
panelRun.model.nodeChanged(NodeJob.this);
if (panelRun.displayNode == NodeJob.this) {
panelRun.buttonStop.setEnabled(complete < 1 || complete == 3);
panelRun.viewJob(true);
} else if (panelRun.displayNode instanceof NodeFile && panelRun.displayNode.getParent() == NodeJob.this) {
panelRun.buttonStop.setEnabled(complete < 1 || complete == 3);
// Update the display every 5 seconds during the run.
// Some displays, such as a chart, could take longer than 5s to construct, so don't interrupt those.
// Always update the display when a run finishes.
long currentTime = System.currentTimeMillis();
if (complete >= 1 && complete != 3 || panelRun.displayThread == null && currentTime - lastDisplay > 5000) {
lastDisplay = currentTime;
panelRun.viewFile(true);
}
}
// panelStudy could be null for a brief moment during startup
if (panelStudy != null)
panelStudy.tableSamples.updateJob(key);
}
});
}
if (!panelRun.tree.isCollapsed(new TreePath(getPath())))
build(panelRun.tree);
}
use of gov.sandia.n2a.host.Host in project n2a by frothga.
the class SettingsBackend method getPanel.
@SuppressWarnings("serial")
@Override
public Component getPanel() {
if (scrollPane != null)
return scrollPane;
JPanel view = new JPanel();
scrollPane = new JScrollPane(view);
for (Host h : Host.getHosts()) model.addElement(h);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting())
return;
Host h = (Host) list.getSelectedValue();
if (h == null)
return;
bind(h.config.childOrCreate("backend", key));
}
});
list.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Host h = (Host) value;
String name = h.name;
if (h.config.get("backend", key).equals("0"))
name = "<html><s>" + name + "</s></html>";
return super.getListCellRendererComponent(list, name, index, isSelected, cellHasFocus);
}
});
InputMap inputMap = list.getInputMap();
inputMap.put(KeyStroke.getKeyStroke("DELETE"), "toggleEnable");
inputMap.put(KeyStroke.getKeyStroke("BACK_SPACE"), "toggleEnable");
inputMap.put(KeyStroke.getKeyStroke("SPACE"), "toggleEnable");
ActionMap actionMap = list.getActionMap();
actionMap.put("toggleEnable", new AbstractAction() {
public void actionPerformed(ActionEvent e) {
Host h = (Host) list.getSelectedValue();
if (h == null)
return;
boolean disabled = h.config.get("backend", key).equals("0");
if (disabled)
h.config.set(null, "backend", key);
else
h.config.set("0", "backend", key);
list.repaint();
}
});
JPanel panelList = Lay.BL("C", list, "pref=[100,200]");
panelList.setBorder(LineBorder.createBlackLineBorder());
panelList = (JPanel) Lay.eb(Lay.BL("C", panelList), "5");
editor = getEditor();
Lay.BLtg(view, "N", Lay.BL("W", Lay.BxL("H", Lay.BL("N", panelList), Box.createHorizontalStrut(5), Lay.BL("N", editor))));
if (list.getModel().getSize() > 0)
list.setSelectedIndex(0);
return scrollPane;
}
use of gov.sandia.n2a.host.Host in project n2a by frothga.
the class Main method runHeadless.
/**
* Assumes this app was started solely for the purpose of running one specific job.
* This job operates outside the normal job management. The user is responsible
* for everything, including load balancing, directory and file management.
* Jobs can run remotely, but there is no support for retrieving results.
*/
public static void runHeadless(MNode record) {
// See PanelEquations.launchJob()
// Use current working directory, on assumption that's what the caller wants.
Path jobDir = Paths.get(System.getProperty("user.dir")).toAbsolutePath();
// This allows a remote job to run in the regular jobs directory there.
String jobKey = new SimpleDateFormat("yyyy-MM-dd-HHmmss", Locale.ROOT).format(new Date());
// Make this appear as if it is from the jobs collection.
MDoc job = new MDoc(jobDir.resolve("job"), jobKey);
String key = record.key();
MNode doc = AppData.models.childOrEmpty(key);
record.mergeUnder(doc);
// TODO: the only reason to collate here is to ensure that host and backend are correctly identified if they are inherited. Need a more efficient method, such as lazy collation in MPart.
MPart collated = new MPart(record);
NodeJob.collectJobParameters(collated, key, job);
NodeJob.saveSnapshot(record, job);
// Handle remote host
// If a remote host is used, it must be specified exactly, rather than a list of possibilities.
Host host = Host.get(job);
if (// Need to note the key so user can easily find the remote job directory.
host instanceof Remote) {
job.set(jobKey, "remoteKey");
job.save();
}
// Start the job.
Backend backend = Backend.getBackend(job.get("backend"));
backend.start(job);
// Wait for completion
NodeJob node = new NodeJobHeadless(job);
while (node.complete < 1) node.monitorProgress();
// Convert to CSV, if requested.
if (record.getFlag("$metadata", "csv")) {
Table table = new Table(jobDir.resolve("out"), false);
try {
table.dumpCSV(jobDir.resolve("out.csv"));
} catch (IOException e) {
}
}
// Extract results requested in ASV
MNode ASV = record.child("$metadata", "dakota", "ASV");
// nothing more to do
if (ASV == null)
return;
OutputParser output = new OutputParser();
output.parse(jobDir.resolve("out"));
try (BufferedWriter writer = Files.newBufferedWriter(jobDir.resolve("results"))) {
for (MNode o : ASV) {
String name = o.get();
Column c = output.getColumn(name);
float value = 0;
if (c != null && !c.values.isEmpty())
value = c.values.get(c.values.size() - 1);
writer.write(value + " " + name);
}
} catch (IOException e) {
}
}
Aggregations