r1310 - in trunk/isis-fish/src: java/fr/ifremer/isisfish java/fr/ifremer/isisfish/actions java/fr/ifremer/isisfish/datastore java/fr/ifremer/isisfish/simulator java/fr/ifremer/isisfish/simulator/launcher java/fr/ifremer/isisfish/ui/simulator uimodel/fr/ifremer/isisfish/ui uimodel/fr/ifremer/isisfish/ui/simulator
Author: bpoussin Date: 2008-08-22 22:46:00 +0000 (Fri, 22 Aug 2008) New Revision: 1310 Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/Queue.java Removed: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/AbstractSimulationQueueModel.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/PlanGenerator.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointExternalProcessThread.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointRemoteThread.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationDoneQueueModel.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueEvent.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueListener.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisConfig.java trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisFish.java trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisTray.java trunk/isis-fish/src/java/fr/ifremer/isisfish/actions/SimulationAction.java trunk/isis-fish/src/java/fr/ifremer/isisfish/datastore/SimulationStorage.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationContext.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationParameter.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/Simulator.java trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulatorServer.java trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorAction.java trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorListeners.java trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/context.xml trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Params.xml trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Queue.xml trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/SimulQueue.xml Log: - tout reecrit le SimulationManager qui se nome maintenent SimulationService Il permet facilement de pluger de nouvelle facon de simuler (obligatoire pour caparmor) tout ca n'est pas encore tester, mais ca compile Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisConfig.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisConfig.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisConfig.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -27,8 +27,9 @@ import fr.ifremer.isisfish.actions.SimulationAction; import fr.ifremer.isisfish.actions.VCSAction; import fr.ifremer.isisfish.simulator.SimulationContext; +import fr.ifremer.isisfish.simulator.launcher.InProcessSimulatorLauncher; +import fr.ifremer.isisfish.simulator.launcher.SimulationService; import fr.ifremer.isisfish.vcs.VCS; -import fr.ifremer.isisfish.vcs.VCSNone; import java.io.File; import java.net.MalformedURLException; import java.net.URL; @@ -572,7 +573,7 @@ SIMULATOR_CLASSFILE("simulator.classfile", _("isisfish.config.main.defaultSimulator.description"), "DefaultSimulator.java"), /** prevu pour l'architecture de lancement en plugin: local, isis-server, caparmor, ... */ - SIMULATOR_LAUNCHER("simulator.launcher", _("isisfish.config.main.localSimulator.description"), "local"), + SIMULATOR_LAUNCHER(SimulationService.SIMULATION_LAUNCHER + ".localDefault", _("isisfish.config.main.localSimulator.description"), InProcessSimulatorLauncher.class.getName()), SIMULATOR_SERVER("simulation.server", _("isisfish.config.main.simulationServer.description"), "http://simulateur.ifremer.fr:9090"), /** le login a utiliser pour les launcher distant, le type du launcher est ajouter a la cle (car 1 login par launcher) */ Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisFish.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisFish.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisFish.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -31,7 +31,6 @@ package fr.ifremer.isisfish; -import com.sun.tools.internal.xjc.generator.util.ExistingBlockReference; import fr.ifremer.isisfish.datastore.AnalysePlanStorage; import fr.ifremer.isisfish.datastore.ExportStorage; import fr.ifremer.isisfish.datastore.FormuleStorage; @@ -40,7 +39,7 @@ import fr.ifremer.isisfish.datastore.ScriptStorage; import fr.ifremer.isisfish.datastore.SimulationStorage; import fr.ifremer.isisfish.datastore.SimulatorStorage; -import fr.ifremer.isisfish.simulator.SimulationManager; +import fr.ifremer.isisfish.simulator.launcher.SimulationService; import fr.ifremer.isisfish.swix.LayoutConverter; import fr.ifremer.isisfish.types.Date; import fr.ifremer.isisfish.types.Month; @@ -55,7 +54,6 @@ import fr.ifremer.isisfish.vcs.VCSActionEvent; import fr.ifremer.isisfish.vcs.VCSException; import fr.ifremer.isisfish.vcs.VCSFactory; -import fr.ifremer.isisfish.vcs.VCSNone; import fr.ifremer.isisfish.vcs.VetoableActionListener; import java.io.File; import java.text.SimpleDateFormat; @@ -78,6 +76,7 @@ import org.codelutin.topia.TopiaException; import org.codelutin.util.LocaleConverter; import org.codelutin.util.VersionNumber; +import org.swixml.SwingEngine; import static javax.swing.JOptionPane.showOptionDialog; @@ -369,7 +368,7 @@ */ static public void launchUI() { // init simulater manager - SimulationManager.getInstance(); + SimulationService.getService(); if (config.isLaunchUI()) { // init IsisTray Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisTray.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisTray.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/IsisTray.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -53,9 +53,9 @@ import org.jdesktop.jdic.tray.TrayIcon; import fr.ifremer.isisfish.simulator.SimulationControl; -import fr.ifremer.isisfish.simulator.SimulationManager; -import fr.ifremer.isisfish.simulator.SimulationQueueEvent; -import fr.ifremer.isisfish.simulator.SimulationQueueListener; +import fr.ifremer.isisfish.simulator.launcher.SimulationJob; +import fr.ifremer.isisfish.simulator.launcher.SimulationService; +import fr.ifremer.isisfish.simulator.launcher.SimulationServiceListener; /** @@ -63,7 +63,7 @@ * */ -public abstract class IsisTray implements SimulationQueueListener, PropertyChangeListener { +public abstract class IsisTray implements SimulationServiceListener, PropertyChangeListener { /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(IsisTray.class); @@ -95,35 +95,25 @@ } log.info("Use System tray: " + instance.getClass().getName()); instance.setToolTip(_(NO_SIMULATION_TEXT)); - SimulationManager.getInstance().addSimulationQueueListener(instance); + SimulationService.getService().addSimulationServiceListener(instance); } return instance; } /* (non-Javadoc) - * @see fr.ifremer.isisfish.simulator.SimulationQueueListener#simulationAdded(fr.ifremer.isisfish.simulator.SimulationQueueEvent) - */ - public void simulationAdded(SimulationQueueEvent e) { - } - /* (non-Javadoc) - * @see fr.ifremer.isisfish.simulator.SimulationQueueListener#simulationWillBeRemoved(fr.ifremer.isisfish.simulator.SimulationQueueEvent) - */ - public void simulationWillBeRemoved(SimulationQueueEvent e) { - } - /* (non-Javadoc) * @see fr.ifremer.isisfish.simulator.SimulationQueueListener#simulationStart(fr.ifremer.isisfish.simulator.SimulationQueueEvent) */ - public void simulationStart(SimulationQueueEvent e) { - SimulationControl control = SimulationManager.getInstance().getControl(e.getId()); + public void simulationStart(SimulationJob job) { + SimulationControl control = job.getItem().getControl(); control.addPropertyChangeListener(this); - getInstance().setToolTip(_(SIMULATION_TEXT, e.getId(), control.getProgress(), control.getProgressMax())); + getInstance().setToolTip(_(SIMULATION_TEXT, control.getId(), control.getProgress(), control.getProgressMax())); getInstance().setImage(TRAY_IMAGE_START); } /* (non-Javadoc) * @see fr.ifremer.isisfish.simulator.SimulationQueueListener#simulationStop(fr.ifremer.isisfish.simulator.SimulationQueueEvent) */ - public void simulationStop(SimulationQueueEvent e) { - SimulationControl control = SimulationManager.getInstance().getControl(e.getId()); + public void simulationStop(SimulationJob job) { + SimulationControl control = job.getItem().getControl(); control.removePropertyChangeListener(this); getInstance().setToolTip(_(NO_SIMULATION_TEXT)); getInstance().setImage(TRAY_IMAGE_STOP); Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/actions/SimulationAction.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/actions/SimulationAction.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/actions/SimulationAction.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -24,8 +24,11 @@ import fr.ifremer.isisfish.IsisConfig; import fr.ifremer.isisfish.datastore.RegionStorage; import fr.ifremer.isisfish.datastore.SimulationStorage; -import fr.ifremer.isisfish.simulator.SimulationHelper; +import fr.ifremer.isisfish.simulator.SimulationControl; import fr.ifremer.isisfish.simulator.SimulationParameter; +import fr.ifremer.isisfish.simulator.launcher.InProcessSimulatorLauncher; +import fr.ifremer.isisfish.simulator.launcher.SimulationService; +import fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher; import java.io.File; import java.io.FileInputStream; import java.text.SimpleDateFormat; @@ -72,7 +75,7 @@ } } - SimulationHelper.simulate(simulId, params, false); + SimulationService.getService().submit(simulId, params, 0); } /** @@ -81,32 +84,17 @@ * @param zip Zip de la simulation * @param parameterFile parametre optionnel pour la simulation */ - public static void simulateWithSimulation(String simulId, File parameterFile, File simulationZip) throws Exception { - SimulationParameter params = null; - if (parameterFile != null && parameterFile.exists()) { - Properties props = new Properties(); - FileInputStream inStream = new FileInputStream(parameterFile); - props.load(inStream); - inStream.close(); + public static void simulateWithSimulation(String simulId, File simulationZip) throws Exception { + log.info("id:" + simulId + ", zip:" + simulationZip); - params = new SimulationParameter(); - params.fromProperties(props); - } - log.info("id:" + simulId + ", zip:" + simulationZip + (params!=null?" with parameters":"")); - - // import de cette simulation String name = simulId + " " + new SimpleDateFormat("yyyy-MM-dd-HH-mm").format(new Date()); - // import de la simulation avec un autre nom - SimulationStorage sim = SimulationStorage.importAndRenameZip(simulationZip, name); - if (params != null) { - sim.setParameter(params); - } + SimulationControl control = new SimulationControl(name); // lancement de la simulation - SimulationHelper.simulate(null, sim); + SimulatorLauncher launcher = new InProcessSimulatorLauncher(); + SimulationStorage simulation = launcher.simulate(null, control, simulationZip); - sim.getStorage().closeContext(); - + simulation.getStorage().closeContext(); } } Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/datastore/SimulationStorage.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/datastore/SimulationStorage.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/datastore/SimulationStorage.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -78,6 +78,7 @@ /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(SimulationStorage.class); + /** cache des simulation storage */ @SuppressWarnings("unchecked") static protected Map<String, SimulationStorage> simulations = (Map<String, SimulationStorage>) new ReferenceMap(); @@ -548,15 +549,39 @@ * @throws TopiaException si problème lors de la création du contexte */ public static SimulationStorage importAndRenameZip(File file, String newName) throws IOException, TopiaException { + SimulationStorage result = importAndRenameZip(getSimulationDirectory(), file, newName); + // put result in cache + simulations.put(result.getName(), result); + return result; + } + + /** + * import zipped simulation in specific directory, result is not put in cache + * + * @param directory where we want new simulation storage + * @param file zipped region file + * @param newName new name for the imported simulation + * @return region storage or null + * @throws IOException si problème IO lors de la lecture du zip + * @throws TopiaException si problème lors de la création du contexte + */ + public static SimulationStorage importAndRenameZip(File directory, File file, String newName) throws IOException, TopiaException { + if (!directory.exists()) { + directory.mkdirs(); + } + if(!directory.isDirectory()) { + throw new IllegalArgumentException(_("directory %s must be a directory", + directory.getAbsolutePath())); + } String renameFrom = null; String renameTo = null; if (newName != null) { renameFrom = "^.*?/(.*)$"; renameTo = newName + "/$1"; } - String lastEntry = ZipUtil.uncompressAndRename(file, getSimulationDirectory(), renameFrom, renameTo); + String lastEntry = ZipUtil.uncompressAndRename(file, directory, renameFrom, renameTo); String name = lastEntry.substring(0, lastEntry.indexOf("/")); - SimulationStorage result = SimulationStorage.getSimulation(name); + SimulationStorage result = new SimulationStorage(directory, name, null); if (result != null) { File data = result.getDataBackupFile(); if (file.exists()) { @@ -568,7 +593,7 @@ } return result; } - + /** * Extract the region of a given simulation in a * @param regionName the name of the region to export Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/AbstractSimulationQueueModel.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/AbstractSimulationQueueModel.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/AbstractSimulationQueueModel.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,454 +0,0 @@ -package fr.ifremer.isisfish.simulator; - -import static org.codelutin.i18n.I18nf._; -import org.codelutin.log.LutinLog; -import org.codelutin.log.LutinLogFactory; - -import javax.swing.JComponent; -import javax.swing.JProgressBar; -import javax.swing.JTable; -import javax.swing.event.EventListenerList; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableModel; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Abstract model for a set of simulation (should not be named QueueModel but SetModel). - * <p/> - * This layer implememnts TableModel and PropertyChangeListener logic. - * <p/> - * Sub class should normally just implements SimulationQueueListener interface - * (and the two abstract methods to obtain data from {@link #queue} - * - * @author chemit - */ -public abstract class AbstractSimulationQueueModel extends JComponent - implements TableModel, SimulationQueueListener, PropertyChangeListener { - - /** @return list of ids of simulations contained in this model */ - protected abstract List<String> getSimulationIds(); - - /** @return map of QueueItems (indexed by id) */ - protected abstract Map<String, SimulationManager.SimulationItem> getQueueItemsAsMap(); - - /** to use log facility, just put in your code: log.info("..."); */ - protected static LutinLog log = LutinLogFactory.getLutinLog(AbstractSimulationQueueModel.class); - - /** List of listeners */ - protected EventListenerList listenerList = new EventListenerList(); - - /** the simulator manager */ - protected SimulationManager queue; - - /** header names */ - protected String[] header = new String[]{_("isisfish.queue.id"), _("isisfish.queue.plan"), _("isisfish.queue.name"), _("isisfish.queue.local"), _("isisfish.queue.status"), _("isisfish.queue.progression")}; - - /** columns types */ - protected Class[] columnClass = new Class[]{ - String.class, // id - String.class, // analyse plan number - Boolean.class, // in queue - String.class, // local, remote, batch - String.class, // text - JProgressBar.class // progress - }; - - /** progress bar (one for each row) */ - protected Map<String, JProgressBar> progress = new HashMap<String, JProgressBar>(); - - protected AbstractSimulationQueueModel() { - this(SimulationManager.getInstance()); - } - - protected AbstractSimulationQueueModel(SimulationManager queue) { - this.queue = queue; - if (queue == null) { - this.queue = SimulationManager.getInstance(); - } - this.queue.addSimulationQueueListener(this); - - // add this model as listener on all already done simulations - for (String id : this.getSimulationIds()) { - SimulationControl control = getSimulationControl(id); - if (control != null) { - control.addPropertyChangeListener(this); - } - } - } - - /** @param queue The queue to set. */ - public void setQueue(SimulationManager queue) { - this.queue = queue; - fireTableDataChanged(); - } - - /** @return the manager used */ - protected SimulationManager getQueue() { - return queue; - } - - /** - * @param index rowIndex to check - * @return <code>true</code> if this is a valid rowIndex, - * <code>false</code> otherwise - */ - protected boolean isRowIndexValid(int index) { - return index > -1 && index < getRowCount(); - } - - /** - * @param id id of the simulation to use - * @return the rowIndex of the given simulation, - */ - protected int getSimulationIndex(String id) { - return getSimulationIds().indexOf(id); - } - - /** - * @param rowIndex the rowIndex of the simulation in table - * @return the id of the simulation given - */ - protected String getSimulationId(int rowIndex) { - if (rowIndex < 0 || rowIndex >= getSimulationIds().size()) return ""; - return getSimulationIds().get(rowIndex); - } - - /** - * @param id id of the QueueItem to find - * @return the queueItem found via his id - */ - protected SimulationManager.SimulationItem getItem(String id) { - return getQueueItemsAsMap().get(id); - } - - /** - * @param rowIndex rowIndex of the QueueItem to find - * @return the queueItem found via his rowIndex - */ - protected SimulationManager.SimulationItem getItem(int rowIndex) { - String id = getSimulationId(rowIndex); - return id == null ? null : getQueueItemsAsMap().get(id); - } - - /** - * @param id id of simulation to use - * @return the SimulationControl of the given simulation - */ - protected SimulationControl getSimulationControl(String id) { - SimulationControl result = queue.getControl(id); - if (result == null) { - log.user(_("isisfish.error.invalid.simulation.id", id, getSimulationIds())); - } - return result; - } - - public SimulationControl getSimulationControl(int rowIndex) { - String id = getSimulationId(rowIndex); - SimulationControl result = getSimulationControl(id); - return result; - } - /** - * @param id id of the simulation used - * @return the SimulationParameter associated to the simulation given - */ - protected SimulationParameter getSimulationParameter(String id) { - SimulationParameter result = null; - SimulationManager.SimulationItem item = getItem(id); - if (item != null) { - result = item.param; - } else { - log.user(_("isisfish.error.invalid.simulation.index.availables", id, getSimulationIds())); - } - return result; - } - - protected JProgressBar getProgressBar(String id) { - JProgressBar result = progress.get(id); - if (result == null) { - result = new JProgressBar(JProgressBar.HORIZONTAL, 0, 100); - result.setStringPainted(true); - progress.put(id, result); - } - return result; - } - - /* (non-Javadoc) - * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) - */ - public void propertyChange(PropertyChangeEvent evt) { - SimulationControl control = (SimulationControl) evt.getSource(); - int row = getSimulationIndex(control.getId()); - fireTableRowsUpdated(row, row); - } - - ///////////////////////////////////////////// - // SimulationQueueListener implementation - ///////////////////////////////////////////// - - /* (non-Javadoc) - * @see SimulationQueueListener#simulationStart(fr.ifremer.isisfish.simulator.SimulationQueueEvent) - */ - public void simulationStart(SimulationQueueEvent e) { - // nothing to do - } - - /* (non-Javadoc) - * @see SimulationQueueListener#simulationStop(fr.ifremer.isisfish.simulator.SimulationQueueEvent) - */ - public void simulationStop(SimulationQueueEvent e) { - // nothing to do - } - - ///////////////////////////////////////////// - // TableModel implementation - ///////////////////////////////////////////// - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getRowCount() - */ - - public int getRowCount() { - return getSimulationIds().size(); - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getColumnCount() - */ - public int getColumnCount() { - return header.length; - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getColumnName(int) - */ - public String getColumnName(int column) { - return header[column]; - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getColumnClass(int) - */ - public Class<?> getColumnClass(int columnIndex) { - return columnClass[columnIndex]; - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#isCellEditable(int, int) - */ - public boolean isCellEditable(int rowIndex, int columnIndex) { - return false; - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#getValueAt(int, int) - */ - public Object getValueAt(int rowIndex, int columnIndex) { - if (rowIndex >= getSimulationIds().size()) { - return "error"; - } - - String id = getSimulationId(rowIndex); - - SimulationControl control = getSimulationControl(id); - - SimulationParameter param = getSimulationParameter(id); - - Object result = ""; - - switch (columnIndex) { - case 0: - result = id; - break; - case 1: - int number = param.getAnalysePlanNumber(); - if (number >= 0) { - result = number; - } else { - result = _("isisfish.common.no"); - } - break; - case 2: - result = param.getInQueue(); - break; - case 3: - if (param.getLocal()) { - if (param.isSubProcess()) { - result = "batch"; - } else { - result = "local"; - } - } else { - result = "remote"; - } - break; - case 4: - if (control != null) { - if (control.isStopSimulationRequest()) { - result = _("isisfish.launch.stop"); - } else { - result = control.getText(); - } - } - break; - case 5: - JProgressBar pb = getProgressBar(id); - if (control != null) { - pb.setMaximum(control.getProgressMax()); - pb.setValue(control.getProgress()); - pb.setString(control.date.getMonth() + "/" + control.date.getYear()); - } - result = pb; - break; - } - return result; - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int) - */ - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - // table is not editable - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#addTableModelListener(javax.swing.event.TableModelListener) - */ - public void addTableModelListener(TableModelListener l) { - listenerList.add(TableModelListener.class, l); - if (l instanceof JTable) { - ((JTable) l).setDefaultRenderer(JProgressBar.class, new JProgressBarTableCellRenderer()); - } - - } - - /* (non-Javadoc) - * @see javax.swing.table.TableModel#removeTableModelListener(javax.swing.event.TableModelListener) - */ - public void removeTableModelListener(TableModelListener l) { - listenerList.remove(TableModelListener.class, l); - } - - /** - * Notifies all listeners that all cell values in the table's - * rows may have changed. The number of rows may also have changed - * and the <code>JTable</code> should redraw the - * table from scratch. The structure of the table (as in the order of the - * columns) is assumed to be the same. - * - * @see TableModelEvent - * @see EventListenerList - * @see JTable#tableChanged(TableModelEvent) - */ - public void fireTableDataChanged() { - fireTableChanged(new TableModelEvent(this)); - } - - /** - * Notifies all listeners that the table's structure has changed. - * The number of columns in the table, and the names and types of - * the new columns may be different from the previous state. - * If the <code>JTable</code> receives this event and its - * <code>autoCreateColumnsFromModel</code> - * flag is set it discards any table columns that it had and reallocates - * default columns in the order they appear in the model. This is the - * same as calling <code>setModel(TableModel)</code> on the - * <code>JTable</code>. - * - * @see TableModelEvent - * @see EventListenerList - */ - public void fireTableStructureChanged() { - fireTableChanged(new TableModelEvent(this, TableModelEvent.HEADER_ROW)); - } - - /** - * Notifies all listeners that rows in the range - * <code>[firstRow, lastRow]</code>, inclusive, have been inserted. - * - * @param firstRow the first row - * @param lastRow the last row - * @see TableModelEvent - * @see EventListenerList - */ - public void fireTableRowsInserted(int firstRow, int lastRow) { - fireTableChanged(new TableModelEvent(this, firstRow, lastRow, - TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT)); - } - - /** - * Notifies all listeners that rows in the range - * <code>[firstRow, lastRow]</code>, inclusive, have been updated. - * - * @param firstRow the first row - * @param lastRow the last row - * @see TableModelEvent - * @see EventListenerList - */ - public void fireTableRowsUpdated(int firstRow, int lastRow) { - fireTableChanged(new TableModelEvent(this, firstRow, lastRow, - TableModelEvent.ALL_COLUMNS, TableModelEvent.UPDATE)); - } - - /** - * Notifies all listeners that rows in the range - * <code>[firstRow, lastRow]</code>, inclusive, have been deleted. - * - * @param firstRow the first row - * @param lastRow the last row - * @see TableModelEvent - * @see EventListenerList - */ - public void fireTableRowsDeleted(int firstRow, int lastRow) { - fireTableChanged(new TableModelEvent(this, firstRow, lastRow, - TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE)); - } - - /** - * Notifies all listeners that the value of the cell at - * <code>[row, column]</code> has been updated. - * - * @param row row of cell which has been updated - * @param column column of cell which has been updated - * @see TableModelEvent - * @see EventListenerList - */ - public void fireTableCellUpdated(int row, int column) { - fireTableChanged(new TableModelEvent(this, row, row, column)); - } - - /** - * Forwards the given notification event to all - * <code>TableModelListeners</code> that registered - * themselves as listeners for this table model. - * - * @param e the event to be forwarded - * @see #addTableModelListener - * @see TableModelEvent - * @see EventListenerList - */ - public void fireTableChanged(TableModelEvent e) { - // Guaranteed to return a non-null array - Object[] listeners = listenerList.getListenerList(); - // Process the listeners last to first, notifying - // those that are interested in this event - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == TableModelListener.class) { - ((TableModelListener) listeners[i + 1]).tableChanged(e); - } - } - } - - public class JProgressBarTableCellRenderer implements TableCellRenderer { - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - return (JProgressBar) value; - } - }// JProgressBarTableCellRenderer -}// AbstractSimulationQueueModel Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/PlanGenerator.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/PlanGenerator.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/PlanGenerator.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,171 +0,0 @@ -/* *##% - * Copyright (C) 2007 - * Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -/* * - * PlanManager.java - * - * Created: 5 janv. 07 12:39:28 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ - -package fr.ifremer.isisfish.simulator; - -import static org.codelutin.i18n.I18nf._; - -import java.io.File; -import java.util.Collection; -import java.util.Iterator; - -import bsh.Interpreter; -import fr.ifremer.isisfish.IsisFishRuntimeException; -import fr.ifremer.isisfish.datastore.SimulationStorage; - - -/** - * Permet de generer les parametres des simulations utilisant une plan d'analyse - * - * La methode hasNext appelle toutes les methodes beforeSimulation des plans - * d'analyse. Apres une simulation il faut aussi appeler setLastSimulation - * pour que les méthodes afterSimulation des plans d'analyses soit executes. - * - * Si une des methodes afterSimulation retourne false alors il n'y aura - * pas de prochaine simulation. - * - * @author poussin - */ -public class PlanGenerator implements Iterable<SimulationStorage>, Iterator<SimulationStorage> { - - protected String id = null; - protected SimulationControl control = null; - protected SimulationParameter param = null; - protected File zip = null; - protected AnalysePlanContext planContext = null; - protected SimulationStorage nextSimulation = null; - protected int lastSimulationNumber = -1; - /** contient la valeur retourne par les methodes afterSimulation de tous les plans */ - protected boolean doNext = true; - - public PlanGenerator(String id, SimulationControl control, SimulationParameter param) { - this.id = id; - this.control = control; - this.param = param; - this.planContext = new AnalysePlanContext(id, param); - try { - // appel de init sur chaque plan - for (AnalysePlan plan : param.getAnalysePlans()) { - plan.init(planContext); - } - } catch (Exception eee) { - throw new IsisFishRuntimeException(_("isisfish.error.evaluate.preplan.script"), eee); - } - } - - /** - * @param zip The zip to set. - */ - public void setZip(File zip) { - this.zip = zip; - } - - /* (non-Javadoc) - * @see java.lang.Iterable#iterator() - */ - public Iterator<SimulationStorage> iterator() { - return this; - } - - /* (non-Javadoc) - * @see java.util.Iterator#hasNext() - */ - public boolean hasNext() { - try { - // if user request stop simulation, stop all futur planned simulation - // and if last doNext is false not do next simulation - boolean result = !control.isStopSimulationRequest() && doNext; - if (result) { - // si deja creer on ne le refet pas - if (nextSimulation == null) { - // Prepration de la simulation a faire - // create next id simulation - int number = param.getAnalysePlanNumber() + 1; - String simId = id + "_" + number; - param.setAnalysePlanNumber(number); - - nextSimulation = SimulationStorage.importAndRenameZip(zip, simId); - nextSimulation.getParameter().setAnalysePlanNumber(number); - - // appel de tous les plans pour modifier la simulation - for (AnalysePlan plan : param.getAnalysePlans()) { - result = result && plan.beforeSimulation(planContext, nextSimulation); - if (!result) { - // delete created simulation, that don't be done - nextSimulation.delete(false); - nextSimulation = null; - break; - } - } - doNext = result; - } - } - return result; - } catch (Exception eee) { - throw new IsisFishRuntimeException(_("isisfish.error.evalute.plan.script"), eee); - } - } - - public void setLastSimulation(SimulationStorage lastSimulation) { - try { - doNext = true; - boolean result = true; - - // appel de tous les plans pour modifier la simulation - for (AnalysePlan plan : param.getAnalysePlans()) { - result = plan.afterSimulation(planContext, lastSimulation); - doNext = doNext && result; - } - } catch (Exception eee) { - throw new IsisFishRuntimeException(_("isisfish.error.evaluate.plan.script"), eee); - } - - } - - /* (non-Javadoc) - * @see java.util.Iterator#next() - */ - public SimulationStorage next() { - hasNext(); // pour etre sur qu'il a ete appele au moins une fois - SimulationStorage result = nextSimulation; - nextSimulation = null; - return result; - } - - /* (non-Javadoc) - * @see java.util.Iterator#remove() - */ - public void remove() { - throw new UnsupportedOperationException(); - } -} - - Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointExternalProcessThread.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointExternalProcessThread.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointExternalProcessThread.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,81 +0,0 @@ -/** -* SimulationCheckpointThread.java -* -* Created: Wed Aug 28 2002 -* -* @author <poussin at codelutin.com> -* Copyright Code Lutin -* @version $Revision: 1187 $ -* -* Mise a jour: $Date: 2008-03-19 01:26:10 +0100 (mer, 19 mar 2008) $ -* par : $Author: tchemit $ -*/ - -package fr.ifremer.isisfish.simulator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import fr.ifremer.isisfish.datastore.SimulationStorage; - -import java.io.InputStream; - -/** - * This thread is responsable to synchronized SimulationControl used localy with - * remote simulation control for remote simulation. - * - * This thread dead when {@link SimulationControl#isRunning()} is false - * - * @author poussin - */ -public class SimulationCheckpointExternalProcessThread extends Thread { // SimulationCheckpointThread - - /** - * Logger for this class - */ - private static final Log log = LogFactory - .getLog(SimulationCheckpointExternalProcessThread.class); - - protected SimulationControl control = null; - protected SimulationStorage simulation = null; - protected Process process = null; - // on l'appel plutot out que in, car c le output du process lance - protected InputStream out = null; - - public SimulationCheckpointExternalProcessThread(SimulationControl control, - SimulationStorage simulation, Process process) { - this.control = control; - this.simulation = simulation; - this.process = process; - out = process.getInputStream(); - - } - - public void run(){ - int sleepTime = 2000; - int error = 0; - while(true){ - try{ - out.skip(out.available()); - Thread.sleep(sleepTime); - // on ne lit pas le stop, car le stop ne peut-etre appeler - // que par l'utilisateur qui est de ce cote de la machine - simulation.readControl(control, "stop"); - - if (control.isStopSimulationRequest()) { - // FIXME, un destroy du process est peut-etre un peu violent ? - process.destroy(); - // passe artificiellement le control a fini - control.stopSimulation(); - } - if (!control.isRunning()) { - return; - } - } catch (Exception eee) { - log.debug("Can't update control for " + control.getId(), eee); - } - } - - } - -} // SimulationCheckpointThread Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointRemoteThread.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointRemoteThread.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationCheckpointRemoteThread.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,92 +0,0 @@ -/** -* SimulationCheckpointRemoteThread.java -* -* Created: Wed Aug 28 2002 -* -* @author <poussin at codelutin.com> -* Copyright Code Lutin -* @version $Revision$ -* -* Mise a jour: $Date$ -* par : $Author$ -*/ - -package fr.ifremer.isisfish.simulator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.Hashtable; -import java.util.Vector; - -import org.apache.xmlrpc.XmlRpcClient; - -import fr.ifremer.isisfish.IsisConfig; -import fr.ifremer.isisfish.IsisFish; - -/** - * This thread is responsable to synchronized SimulationControl used localy with - * remote simulation control for remote simulation. - * - * This thread dead when {@link SimulationControl#isRunning()} is false - * - * @author poussin - */ -public class SimulationCheckpointRemoteThread extends Thread { // SimulationCheckpointRemoteThread - - /** - * Logger for this class - */ - private static final Log log = LogFactory - .getLog(SimulationCheckpointRemoteThread.class); - - protected SimulationControl control = null; - int badId = 0; - - public SimulationCheckpointRemoteThread(SimulationControl control) { - this.control = control; - } - - public void run(){ - int sleepTime = 2000; - while(true){ - try{ - Thread.sleep(sleepTime); - - updateControl(control); - // on remet de le temps normal, vu que la connexion a reussi - sleepTime = 2000; - - if (!control.isRunning()) { - return; - } - - } catch (Exception eee) { - // on supporte 10 erreurs puis ensuite on quitte le thread. - if ( badId++ > 10){ - log.error("Error !!! ", eee); - break; - }else{ - // on a echouer sur une tentative, on allonge un - // peu le temps - sleepTime += 2000; - } - } - } - - } - - public void updateControl(SimulationControl control) throws Exception { - // essai l'ancienne etait en dur: "http://localhost:9090" - IsisConfig config = IsisFish.config; - XmlRpcClient c = new XmlRpcClient(config.getSimulatorServer()); - c.setBasicAuthentication(config.getSimulatorUsername(), config.getSimulatorPassword()); - - Vector a = new Vector(); - a.add(control.getUpdateHashtable()); - Hashtable<String, Object> result = (Hashtable<String, Object>)c.execute("checkPoint", a); - // on remet de le temps normal, vu que la connexion a reussi - control.updateFromHashtable(result); - } - -} // SimulationCheckpointRemoteThread Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationContext.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationContext.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationContext.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -117,6 +117,31 @@ getResultManager().addSimulationResultListener((SimulationResultListener)l); } } + + public void closeDB() { + if (db != null) { + try { + db.closeContext(); + } catch (TopiaException eee) { + if (log.isDebugEnabled()) { + log.debug("Can't close simulation topia context", eee); + } + } + } + } + + public void closeDBResult() { + if (dbResult != null) { + try { + dbResult.commitTransaction(); + dbResult.closeContext(); + } catch (TopiaException eee) { + if (log.isDebugEnabled()) { + log.debug("Can't close simulation result topia context", eee); + } + } + } + } /** * Remove simulation listener, if listener is {@link SimulationResultListener}, it's @@ -130,12 +155,12 @@ } } - protected void fireBeforeSimulation() { + public void fireBeforeSimulation() { for(SimulationListener l : simulationListeners) { l.beforeSimulation(this); } } - protected void fireAfterSimulation() { + public void fireAfterSimulation() { for(SimulationListener l : simulationListeners) { l.afterSimulation(this); } Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationDoneQueueModel.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationDoneQueueModel.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationDoneQueueModel.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,120 +0,0 @@ -/* *##% - * Copyright (C) 2006 - * Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -/* * - * SimulationQueueModel.java - * - * Created: 18 août 2006 00:05:41 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ - -package fr.ifremer.isisfish.simulator; - -import fr.ifremer.isisfish.datastore.SimulationInformation; -import fr.ifremer.isisfish.datastore.SimulationStorage; - -import static org.codelutin.i18n.I18nf._; - -/** - * Model that represents a set of done or stopped simulations - * - * @author tchemit - */ - -public class SimulationDoneQueueModel extends AbstractSimulationQueueModel { - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel() - */ - public SimulationDoneQueueModel() { - super(); - } - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel(SimulationManager) - */ - public SimulationDoneQueueModel(SimulationManager queue) { - super(queue); - } - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel at getSimulationIds() - */ - protected java.util.List<String> getSimulationIds() { - return getQueue().getDoneIds(); - } - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel at getQueueItemsAsMap() - */ - protected java.util.Map<String, SimulationManager.SimulationItem> getQueueItemsAsMap() { - return getQueue().mapDones; - } - - /* (non-Javadoc) - * @see SimulationQueueListener#simulationAdded(SimulationQueueEvent) - */ - public void simulationAdded(SimulationQueueEvent e) { - // nothing to do - } - - /* (non-Javadoc) - * @see SimulationQueueListener#simulationRemoved(SimulationQueueEvent) - */ - public void simulationWillBeRemoved(SimulationQueueEvent e) { - // when a simulation is removed from first model - // it could appear here (if it checks certain conditions : see - // the options dedicated to done simulation in - // IsisConfig.SIMULATION_SHOW_ONLY_XXX properties) - int pos = getSimulationIndex(e.getId()); - if (isRowIndexValid(pos)) { - log.info(" in done model for " + e.getId() + " pos " + pos); - fireTableRowsInserted(pos, pos); - - // on indique si la simulation a ete annulee - SimulationControl control = getSimulationControl(e.getId()); - log.info("isStopSimulationRequest : "+control.isStopSimulationRequest()); - if (control.isStopSimulationRequest()) { - control.setText(_("isisfish.queue.cancelled")); - } - - // on change le message pour dire qu'il y a eu une erreur - try { - SimulationManager.SimulationItem item = getQueueItemsAsMap().get(e.getId()); - if (!item.hasSimulation()) { - SimulationInformation infos = item.getSimulation().getInformation(); - if (infos.hasError()) { - log.error(_("isisfish.error.while.simulation", infos.getException())); - control.setText(_("isisfish.message.stop.with.error")); - } - } - } catch (Exception eee) { - log.warn(_("isisfish.error.obtain.information.file", e.getId()), eee); - } - control.addPropertyChangeListener(this); - } - - } - -}// SimulationDoneQueueModel Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,730 +0,0 @@ -/* - * *##% Copyright (C) 2002-2005 Code Lutin, Cédric Pineau, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307, USA. ##% - */ - -/******************************************************************************* - * SimulatorHelper.java - * - * Created: Wed Aug 14 2002 - * - * @author <poussin at codelutin.com> Copyright Code Lutin - * - * @version $Revision$ - * - * Mise a jour: $Date$ par : $Author$ - */ - -package fr.ifremer.isisfish.simulator; - -import static org.codelutin.i18n.I18nf._; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Properties; -import java.util.Vector; - -import org.apache.commons.lang.time.DurationFormatUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.xmlrpc.XmlRpcClient; -import org.codelutin.profiling.LutinTrace; -import org.codelutin.topia.TopiaContext; -import org.codelutin.topia.TopiaException; -import org.codelutin.topia.event.TopiaTransactionEvent; -import org.codelutin.topia.event.TopiaTransactionListener; -import org.codelutin.topia.persistence.TopiaEntity; -import org.codelutin.util.FileUtil; -import org.codelutin.util.ObjectUtil; -import org.codelutin.util.StringUtil; -import org.codelutin.util.ZipUtil; - -import fr.ifremer.isisfish.IsisFish; -import fr.ifremer.isisfish.IsisFishRuntimeException; -import fr.ifremer.isisfish.IsisFish; -import fr.ifremer.isisfish.aspect.AspectClassLoader; -import fr.ifremer.isisfish.aspect.Cache; -import fr.ifremer.isisfish.aspect.Trace; -import fr.ifremer.isisfish.datastore.AnalysePlanStorage; -import fr.ifremer.isisfish.datastore.ExportStorage; -import fr.ifremer.isisfish.datastore.RegionStorage; -import fr.ifremer.isisfish.datastore.RuleStorage; -import fr.ifremer.isisfish.datastore.ScriptStorage; -import fr.ifremer.isisfish.datastore.SimulationStorage; -import fr.ifremer.isisfish.datastore.SimulatorStorage; -import fr.ifremer.isisfish.rule.Rule; -import fr.ifremer.isisfish.util.CompileHelper; - -/** - * <p> - * Objet permettant de faire une simulation. Pour l'utiliser il faut creer une - * instance de l'objet, puis appeler la methode simulate avec tous les - * arguements qu'elle attend. - * - */ -public class SimulationHelper { // SimulatorHelper - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(SimulationHelper.class); - - static private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm"); - - static public void message(SimulationControl control, String message) { - log.info(message); - if (control != null) { - control.setText(message); - } - } - - /** - * Prepare les fichiers qui seront utils à la simulation: - * <li> scripts - * <li> rules - * <li> exports - * <li> simulators - * <li> export de la database de la region - * <p> - * Le tout est zippé et le zip est retourné, il peut-être directement - * importé dans le SimulationStorage (en le renomant comme il faut - * importAndRenameZip). - * <p> - * Ce zip est automatiquement supprimé a la fin de l'application. - * - * @param control le controleur - * @param param les parametre de la simulation - * @param compile si vrai la version compile des fichiers Java est aussi - * mise dans le fichier zip. Cela peut servir pour les simulations locales - * pour ne pas recompiler pour chaque simulation avec plan d'analyse - * @return un zip de simulation pour une simulation pret a être faite - * @throws SimulationException pour tout problème rencontré (IO,Topia...) - */ - static public File prepareSimulationZipFile(SimulationControl control, - SimulationParameter param, boolean compile) throws SimulationException { - try { - File tmpDirectory = FileUtil.createTempDirectory("isisfish-simultation-", "-preparation"); - //File regionXML = IsisConfig.getDataBackupFile(tmpDirectory); - File regionXML = new File(tmpDirectory, SimulationStorage.DATA_BACKUP_FILENAME); - - // sauvegarde des parametres - Properties prop = param.toProperties(); - //File f = IsisConfig.getSimulationParametersFile(tmpDirectory); - File f = new File(tmpDirectory, SimulationStorage.PARAMETERS_FILENAME); - FileOutputStream out = new FileOutputStream(f); - //FileOutputStream out = new FileOutputStream(new File(tmpDirectory, IsisConfig.SIMULATION_PARAMETERS)); - prop.store(out, "Parameters"); - out.close(); - - // backup pour toutes les simulations, pour eviter que l'utilisateur - // ne puisse le modifier en meme temps - message(control, _("isisfish.message.backup.database.progress")); - RegionStorage region = RegionStorage.getRegion(param.getRegionName()); - TopiaContext tc = region.getStorage().beginTransaction(); - tc.backup(regionXML, true); - tc.closeContext(); - message(control, _("isisfish.message.backup.database.finished")); - - // copie de toutes regles a utiliser - List<Rule> rules = param.getRules(); - for (Rule rule : rules) { - String name = RuleStorage.getName(rule); - FileUtil.copy(new File(RuleStorage.getRuleDirectory(), name + ".java"), - new File(tmpDirectory, RuleStorage.RULE_PATH + File.separator + name + ".java")); - } - // copie des regles reclamées par les plans d'analyse - for(String name : param.getExtraRules()) { - FileUtil.copy(new File(RuleStorage.getRuleDirectory(), name + ".java"), - new File(tmpDirectory, RuleStorage.RULE_PATH + File.separator + name + ".java")); - } - - // copie de toutes regles a utiliser - List<AnalysePlan> plans = param.getAnalysePlans(); - for (AnalysePlan plan : plans) { - String name = AnalysePlanStorage.getName(plan); - FileUtil.copy(new File(AnalysePlanStorage.getAnalysePlanDirectory(), name + ".java"), - new File(tmpDirectory, AnalysePlanStorage.ANALYSE_PLAN_PATH + File.separator + name + ".java")); - } - - // copie de tous les exports a utiliser - for (String name : param.getExportNames()) { - name = name.endsWith(".java")?name:name + ".java"; - FileUtil.copy(new File(ExportStorage.getExportDirectory(), name), - new File(tmpDirectory, ExportStorage.EXPORT_PATH + File.separator + name)); - } - - // copie de tous les scripts a utiliser - FileUtil.copyRecursively(ScriptStorage.getScriptDirectory(), tmpDirectory, ".*\\.java$"); - - // copie de tous les simulateurs a utiliser - FileUtil.copy(new File(SimulatorStorage.getSimulatorDirectory(), param.getSimulatorName()), - new File(tmpDirectory, SimulatorStorage.SIMULATOR_PATH + File.separator + param.getSimulatorName())); - - if (compile) { - compileAllFile(control, tmpDirectory); - } - - // creation du zip - File result = new File(tmpDirectory.getPath() + ".zip"); - result.deleteOnExit(); - ZipUtil.compress(result, tmpDirectory, null); - - // poussin 20071015: remove temp directory - if (!FileUtil.deleteRecursively(tmpDirectory)) { - log.warn(_("isisfish.error.remove.directory", tmpDirectory)); - } - - return result; - } catch (IOException eee) { - throw new SimulationException(_("isisfish.error.prepare.information.simulation"), eee); - } catch (TopiaException eee) { - throw new SimulationException(_("isisfish.error.prepare.information.simulation"), eee); - } - - } - - /** - * Compile les fichiers présent dans le répertoire passé en - * parametre, ce répertoire est hiérarchisé en: rules, exports, simulators - * et scripts. Seul les fichiers des 3 premiers répertoire sont compilé - * les fichiers du dernier sont compilé par les dépendances qu'on les autres - * <p> - * Il permet donc de compiler facilement tous les fichiers pour une - * simulation - * - * @param control le controleur - * @param directory le répertoire où compiler - */ - static public void compileAllFile(SimulationControl control, File directory) { - - message(control, "Scripts and rules Compilation"); - long currentTime = System.nanoTime(); - - // - // Recherche des fichiers a compiler - // On ne prend pas les scripts, car ils sont tous copiés mais pas - // forcément util. Lors de la compilation des autres fichiers, les - // script servant réellement seront automatiquement compilé - - List<File> fileToCompile = new ArrayList<File>(); - - List<File> tmp = FileUtil.find(new File(directory, ExportStorage.EXPORT_PATH), ".*\\.java$", true); - fileToCompile.addAll(tmp); - - tmp = FileUtil.find(new File(directory, RuleStorage.RULE_PATH), ".*\\.java$", true); - fileToCompile.addAll(tmp); - - tmp = FileUtil.find(new File(directory, AnalysePlanStorage.ANALYSE_PLAN_PATH), ".*\\.java$", true); - fileToCompile.addAll(tmp); - - tmp = FileUtil.find(new File(directory, SimulatorStorage.SIMULATOR_PATH), ".*\\.java$", true); - fileToCompile.addAll(tmp); - - // - // Compilation - // - - CompileHelper.compile(directory, fileToCompile, directory, null); - long time = System.nanoTime() - currentTime; - message(control, _("isisfish.message.compilation.time", DurationFormatUtils.formatDuration(time / 1000000, "s'.'S"))); - - } - - /** - * Modifie le classloader du thread passé en paramètre. - * <p> - * Sert pour les simulations pour qu'elles puissent trouver les - * script, rule et export - * - * @param thread le thread dont on souhaite modifier le classloader ou null - * @param directory le répertoire qui servira pour le classloader - * @return le classe loader modifié - */ - static public AspectClassLoader changeClassLoader(Thread thread, File directory) { - try { -// String [] urls = System.getProperty("java.class.path","").split(File.pathSeparator); -// URL [] classpath = new URL[urls.length + 1]; -// for (int i=0; i<urls.length; i++) { -// classpath[i] = new File(urls[i]).toURL(); -// } -// classpath[classpath.length - 1] = directory.toURL(); -// URLClassLoader loader = new URLClassLoader(classpath, null); - URL [] classpath = new URL[]{directory.toURI().toURL(), - // poussin 20080821 - // il semble ne plus trouve les formules, est-ce mieux avec le compile dir ? - IsisFish.config.getCompileDirectory().toURI().toURL() - }; - //URL [] classpath = new URL[]{directory.toURL()}; - AspectClassLoader loader = new AspectClassLoader(classpath, ClassLoader.getSystemClassLoader()); //new URLClassLoader(classpath); - thread.setContextClassLoader(loader); - log.info("Classloader used for simulation: " + loader + " " + Arrays.toString(loader.getURLs())); - return loader; - } catch (MalformedURLException eee) { - // on leve un runtime, car normalement cette erreur est pratiquement - // impossible car on creer l'url a partir d'un File ce qui ne pose - // noralement pas de probleme - throw new IsisFishRuntimeException(_("isisfish.error.change.classloader", directory), eee); - } - } - - /** - * Ajoute dans le Simulation manager une nouvelle simulation avec les - * elements passes en parametre - * @param simulId l'id de la simulation (la date est automatiquement ajoutee) - * @param param les parametres de la simulation - * @param inQueue si la simulation doit etre faite en queue - * @throws SimulationException si l'identifiant n'est pas correct - */ - static public void simulate(String simulId, SimulationParameter param, - boolean inQueue) throws SimulationException { - try { - simulId += " " + dateFormat.format(new java.util.Date()); - - if (simulId == null || "".equals(simulId) || SimulationStorage.localyExists(simulId) || SimulationManager.getInstance().exists(simulId)) { - log.error("Can't start simulation, bad id: " + simulId); - throw new SimulationException(_("isisfish.error.start")); - } - SimulationParameter p = param.copy(); - p.setInQueue(inQueue); - - SimulationManager.getInstance().addSimulation(simulId, p); - } catch (Exception eee) { - throw new SimulationException("Can't add simulation", eee); - } - } - - static public SimulationStorage simulate(SimulationControl control, SimulationStorage simulation) throws Exception { - SimulationStorage result; - if (simulation.getParameter().getLocal()) { - if (simulation.getParameter().isSubProcess()) { - result = subProcessSimulate(control, simulation); - } else { - result = localSimulate(control, simulation); - } - } else { - result = remoteSimulate(control, simulation); - } - return result; - } - - /** - * execute la simulation en remote - * - * @param control le controleur de simulation, peut-etre null si on ne - * souhaite pas controler la simulation - * @param simulation la simulation a faire - * - * @return le storage après simulation - * @throws Exception pour toute erreur - */ - static public SimulationStorage remoteSimulate(SimulationControl control, - SimulationStorage simulation) throws Exception { - // export en zip du storage - File zip = simulation.createZip(); - - if (control != null) { - // creation du thread de surveillance de la simulation distante - // qui sert a mettre a jour les valeurs de control - new SimulationCheckpointRemoteThread(control).start(); - } - - // envoie le zip au serveur de simulation - // appel synchrone pour attendre la fin de la simulation - // recuperation du zip de la simulation terminé - Vector<Object> a = new Vector<Object>(); - //fixme : on peut avori control à null ? - a.add(control.getId()); - a.add(FileUtil.fileToByte(zip)); - - // lancement de la simulation - XmlRpcClient c = new XmlRpcClient(IsisFish.config.getSimulatorServer()); - c.setBasicAuthentication(IsisFish.config.getSimulatorUsername(), - IsisFish.config.getSimulatorPassword()); - byte[] callResult = (byte[])c.execute("simulate", a); - - // ecriture du resultat dans un fichier - File tmpzip = FileUtil.byteToFile(callResult); - - // remplacement du storage local par le storage recu - simulation.closeStorage(); - simulation.delete(false); - SimulationStorage result; - result = SimulationStorage.importAndRenameZip(tmpzip, control.getId()); - return result; - } - - static public SimulationStorage subProcessSimulate(SimulationControl control, - SimulationStorage simulation) throws Exception { - - String simulationId = simulation.getName(); - - // on ferme le SimulationStorage pour ne pas interferer avec le process - simulation.closeStorage(); - - String java = System.getProperty("java.home") + - File.separator + "bin" + File.separator + "java"; - String classpath = System.getProperty("java.class.path"); - - // prepare le process - ProcessBuilder processBuilder = new ProcessBuilder(java, "-classpath", classpath, - IsisFish.class.getName(), - "--simulate", simulationId); - processBuilder.redirectErrorStream(true); - - // demarrage du process - Process process = processBuilder.start(); - - if (control != null) { - // prepare de thread de surveillance du process si control n'est pas null - Thread monitor = new SimulationCheckpointExternalProcessThread(control, simulation, process); - } - - // on attend que la simulation soit fini - process.waitFor(); - - // on retourne directement le simulation storage passe en argument - // car la simulation a ete faite avec - return simulation; - } - - /** - * fait la simulation en local dans un nouveau thread, cela permet - * pour chaque simulation d'avoir les bons scripts dans le classloader - * et non pas d'utiliser les scripts d'une autre simulation - * - * @param control le controleur de simulation, peut-etre null si on ne - * souhaite pas controler la simulation - * @param simulation la simulation a faire - * @return le storage après simulation en locale - */ - static public SimulationStorage localSimulate(SimulationControl control, SimulationStorage simulation) { - SimThread simThread = new SimThread(control, simulation); - // add simulation logger, we can't make it before since we need thread name - // anyway since if accept only log from simThread, no need to init it before - String simulLogLevel = simulation.getParameter().getSimulLogLevel(); - String scriptLogLevel = simulation.getParameter().getScriptLogLevel(); - String libLogLevel = simulation.getParameter().getLibLogLevel(); - try { - simulation.addSimulationLogger(simulLogLevel,scriptLogLevel,libLogLevel,simThread.getName()); - } catch (Exception e) { - if (log.isWarnEnabled()) { - log.warn(_("isisfish.error.add.logger.simulation ", e)); - } - } - try { - simThread.start(); - try { - simThread.join(); - } catch (InterruptedException eee) { - if (log.isWarnEnabled()) { - log.warn(_("isisfish.error.wait.simThread"), eee); - } - } - } finally { - // remove simulation logger (no more need since thread is dead) - simulation.removeSimulationLogger(); - } - return simulation; - } - - static public class SimThread extends Thread { - protected SimulationControl control; - protected SimulationStorage simulation; - - public SimThread(SimulationControl control, SimulationStorage simulation) { - super("SimThread " + (control!=null?control.getId():"")); - this.control = control; - this.simulation = simulation; - } - @Override - public void run() { - simulation = localSimulateSameThread(control, simulation); - } - } - - /** - * Cree le simulation context, creer le ClassLoader, met en place les AOP, - * met a jour des informations sur la simulation et lance la simulation en - * local - * - * @param control le controleur de simulation, peut-etre null si on ne - * souhaite pas controler la simulation - * @param simulation la simulation a faire - * @return le storage après simulation en locale - */ - static public SimulationStorage localSimulateSameThread(SimulationControl control, SimulationStorage simulation) { - SimulationStorage result = null; - String jvmVersion = System.getProperty("java.runtime.version"); - log.info(SimpleDateFormat.getInstance().format(new java.util.Date()) - + " Java version: " + jvmVersion + " Isis-fish version: " - + IsisFish.config.getVersion()); - long start = System.nanoTime(); - simulation.getInformation().setSimulationStart(new java.util.Date()); - AspectClassLoader classLoader; -// DeploymentHandle traceHandle = null; -// DeploymentHandle cacheHandle = null; - try { - File rootDirectory = simulation.getDirectory(); - - // - // changement de classloader - // - classLoader = changeClassLoader(Thread.currentThread(), rootDirectory); - - // - // Creation et initialisation du context de simulation - // - SimulationContext context = SimulationContext.get(); - context.setClassLoader(classLoader); - context.setScriptDirectory(rootDirectory); - context.setSimulationStorage(simulation); - context.setSimulationControl(control!=null?control:new SimulationControl(simulation.getName())); - - SimulationParameter parameters = simulation.getParameter(); - parameters.setIsisFishVersion(IsisFish.config.getVersion()); - // forceReload, save all modification in parameter and reread it - parameters = simulation.getForceReloadParameter(); - - // - // Activation de l'OAP demandée - // - if (parameters.getUseStatistic()) { - message(control, _("isisfish.message.setting.trace.aspects")); -//// SystemDefinition def = SystemDefinitionContainer.getDefinitionFor( -//// Thread.currentThread().getContextClassLoader(), "tests" -//// ); -//// DeploymentScope deploymentScope = def.getDeploymentScope("deployUndeployUsingPreparedPointcut"); -// -// traceHandle = Deployer.deploy(Trace.class, classLoader); - classLoader.deploy(Trace.class); - } - if (parameters.getUseOptimization()) { - message(control, _("isisfish.message.setting.cache.aspects")); -// cacheHandle = Deployer.deploy(Cache.class, classLoader); - classLoader.deploy(Cache.class); - } - - // recherche du simulateur a utiliser - String simulatorName = parameters.getSimulatorName(); - SimulatorStorage simulator = SimulatorStorage - .getSimulator(simulatorName); - Simulator simulatorObject = simulator.getNewSimulatorInstance(); - - // on se met listener sur tc pour connaitre tous les nouveaux objets - ObjectCreationListener objectCreationListener = new ObjectCreationListener(); - context.getDB().addTopiaTransactionListener(objectCreationListener); - - // - // Ajout des listeners pour la simulation - // - initSimulationListener(context); - - // - // Lancement du script de simulation selectionné - // - message(control, _("isisfish.message.simulation.execution")); - - // - // Call listener simulation (used per example for prescript) - // - context.fireBeforeSimulation(); - simulatorObject.simulate(context); - - // - // Ajout des nouveaux objets créées durant la simulation - // - message(control, _("isisfish.message.add.objets.simulation")); - // on ajoute sur le DBResult car pour les exports peut-etre auront - // nous besoin de ces nouveaux objets, et durant la simulation - // les resultats sont recuperer dans le DBResult - TopiaContext add = context.getDbResult(); - for (TopiaEntity e : objectCreationListener.getNewObjects()) { - log.debug("Add new object: " + e + "(" + e.getClass().getName() + ")"); - add.add(e); - } - add.commitTransaction(); - - // - // Call listener simulation (used per example for export) - // - context.fireAfterSimulation(); - - message(control, _("isisfish.message.simulation.ended")); - - simulation.getInformation().setSimulationEnd(new java.util.Date()); - - } catch (OutOfMemoryError eee) { - log.error(_("isisfish.error.during.simulation"),eee); - simulation.getInformation().setException(eee); - throw new SimulationException(_("isisfish.error.out.memory"), eee); - } catch (Exception eee) { - log.error(_("isisfish.error.during.simulation"),eee); - simulation.getInformation().setException(eee); - throw new SimulationException(_("isisfish.error.during.simulation"), eee); - } finally { - // - // Finaly close all TopiaContext used during simulation - // - - SimulationContext context = SimulationContext.get(); - TopiaContext tx; - - tx = context.db; - if (tx != null) { - try { - tx.closeContext(); - } catch (TopiaException eee) { - if (log.isDebugEnabled()) { - log.debug("Can't close simulation topia context", eee); - } - } - } - tx = context.dbResult; - if (tx != null) { - try { - tx.commitTransaction(); - tx.closeContext(); - } catch (TopiaException eee) { - if (log.isDebugEnabled()) { - log.debug("Can't close simulation result topia context", eee); - } - } - } - - try { - // close all transaction - if (context != null && context.getSimulationStorage() != null) { - context.getSimulationStorage().closeMemStorage(); - context.getSimulationStorage().closeStorage(); - } - } catch (TopiaException eee) { - if (log.isWarnEnabled()) { - log.warn("Can't close all transaction", eee); - } - } - -// // -// // disassociate SimulationContext -// // -// if (cacheHandle != null) { -// try { -// Deployer.undeploy(cacheHandle); -// } catch (Exception eee) { -// log.warn("Can't undeploy Cache", eee); -// } -// } -// // undeploy trace after cache, because is registered before -// if (traceHandle != null) { -// try { -// Deployer.undeploy(traceHandle); -// } catch (Exception eee) { -// log.warn("Can't undeploy Trace", eee); -// } -// } - SimulationContext.remove(); - - // - // Affichage des statistiques - // - long end = System.nanoTime(); - log.info("Simulation time: " + DurationFormatUtils.formatDuration((end-start)/1000000, "s'.'S")); - SimulationParameter param = simulation.getParameter(); - if (param.getUseStatistic()) { - String trace = Trace.printStatistiqueAndClear(); - simulation.getInformation().setStatistic(trace); - } - if (param.getUseOptimization()) { - String cache = Cache.printStatistiqueAndClear(); - simulation.getInformation().setOptimizationUsage(cache); - } - - LutinTrace.printStatistiqueAndClear(); - - } - return result; - } - - - static public void initSimulationListener(SimulationContext context) throws Exception { - SimulationStorage simulation = context.getSimulationStorage(); - // enregistrement des listeners de resultat - // - ResultStorage - context.addSimulationListener(simulation.getResultStorage()); - - // - TODO: mexico xml result - // - TODO: vle result - String simListener = context.getSimulationStorage().getParameter().getTagValue().get("SimulationListener"); - if (simListener != null) { - String [] simListeners = StringUtil.split(simListener, ","); - for (String l : simListeners) { - context.addSimulationListener((SimulationListener)ObjectUtil.create(l)); - } - } - - // enregistrement des listeners de simulation - // - prescript (before simulation) - // - export (after simulation) - context.addSimulationListener(new SimulationPreScript()); - // si le simulateur est de type SimulationStep il faut ajouter les regles - context.addSimulationListener(new SimulationExportResultWrapper()); - } - - static public class ObjectCreationListener implements TopiaTransactionListener { - - /** List qui contient tous les objets creer durant la simulation */ - protected List<TopiaEntity> newObjects = new ArrayList<TopiaEntity>(); - - /** - * @return Returns the newObjects. - */ - public List<TopiaEntity> getNewObjects() { - return this.newObjects; - } - - /* (non-Javadoc) - * @see org.codelutin.topia.event.TopiaTransactionListener#commit(org.codelutin.topia.event.TopiaTransactionEvent) - */ - public void commit(TopiaTransactionEvent event) { - // TODO Auto-generated method stub - - } - - /* (non-Javadoc) - * @see org.codelutin.topia.event.TopiaTransactionListener#rollback(org.codelutin.topia.event.TopiaTransactionEvent) - */ - public void rollback(TopiaTransactionEvent event) { - log.debug("Transaction rollback " + event.getEntities().size() + " object(s)"); - // FIXME le jour ou on aura l'isolation on pourra directement - // ajouter dans un autre TopiaContext les objets ajouté durant la - // simulation de cette maniere les objets creer au pas de temps - // N seront dispo pour etre utilisé au pas de temps N+1 - // Sinon une autre methode est de faire cette ajout - // dans l'event rollback qui est leve a la fin de chaque pas de temps - for (TopiaEntity entity : event.getEntities()) { - if (event.isCreate(entity)) { - log.debug("New object detected during simulation: " + entity + "(" + entity.getClass().getName() + ")"); - newObjects.add(entity); - } - } - } - } - -} // SimulatorHelper Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,1110 +0,0 @@ -/* *##% - * Copyright (C) 2007 - * Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -/* * - * SimulationManager.java - * - * Created: 5 janv. 07 11:12:41 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ - -package fr.ifremer.isisfish.simulator; - -import fr.ifremer.isisfish.IsisConfig; -import fr.ifremer.isisfish.IsisFish; -import fr.ifremer.isisfish.datastore.SimulationStorage; -import fr.ifremer.isisfish.types.Date; -import java.beans.PropertyChangeEvent; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import static org.codelutin.i18n.I18nf._; -import org.codelutin.util.FileUtil; -import org.codelutin.util.ListenerSet; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.io.File; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - - -/** - * Singleton servant a lancer les simulations au travers d'un thread unique - * - * @author poussin - */ -public class SimulationManager { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(SimulationManager.class); - - static protected SimulationManager instance = null; - - // FIXME pouvoir configurer ceci en fichier de config - // FIXME ainsi que la mise a false, lors de la simulation de la derniere - // (sans doute ajoute un boolean, simulationListAsQueue = true|false) - protected boolean autoLaunch = true; - - protected ListenerSet<SimulationQueueListener> listeners = new ListenerSet<SimulationQueueListener>(); - protected PropertyChangeSupport propertyListeners = new PropertyChangeSupport(this); - -// protected SimulationThread localThread; -// protected SimulationThread remoteThread; - - protected ExecutorService localExecutor; - protected ExecutorService remoteExecutor; - -// /** La queue, bloquante lorsqu'elle est vide, utilisé par le thread de simulation local*/ -// protected PriorityBlockingQueue<QueueItem> localQueue = new PriorityBlockingQueue<QueueItem>(); -// /** La queue, bloquante lorsqu'elle est vide, utilisé par le thread de simulation remote*/ -// protected PriorityBlockingQueue<QueueItem> remoteQueue = new PriorityBlockingQueue<QueueItem>(); -// /** La liste des simulations terminées */ -// protected LinkedHashSet<SimulationItem> dones = new LinkedHashSet<SimulationItem>(); - -// /** une liste des id (local et remote) */ -// protected ArrayList<String> ids = new ArrayList<String>(); - /** une map id->simItem pour accelerer les acces */ - protected Map<String, SimulationItem> map = new LinkedHashMap<String, SimulationItem>(); - -// /** une liste des id des simulations terminées */ -// protected ArrayList<String> idDones = new ArrayList<String>(); - /** une map id->simItem pour accelerer les acces aux simulation terminées */ - protected Map<String, SimulationItem> mapDones = new LinkedHashMap<String, SimulationItem>(); - - static public SimulationManager getInstance() { - if (instance == null) { - instance = new SimulationManager(); - } - return instance; - } - - /** - * Cree l'objet et lance les deux threads de simulation (local/remote) - */ - protected SimulationManager() { -// localThread = new SimulationThread("local", this, localQueue); -// remoteThread = new SimulationThread("remote", this, remoteQueue); -// -// localThread.start(); -// remoteThread.start(); - - // TODO passer ces valeurs en valeur configurable - int cpus = 1; // FIXME les logs ne sont pas multi-thread (il se melange a priori) -// int cpus = Runtime.getRuntime().availableProcessors(); - int MAX_REMOTE_SIMULATION = 1; - log.info(_("Launch Simulation executor with %s cpu(s) for local, and %s" + - " process for remote", cpus, MAX_REMOTE_SIMULATION)); - localExecutor = Executors.newFixedThreadPool(cpus); - remoteExecutor = Executors.newFixedThreadPool(MAX_REMOTE_SIMULATION); - } - - - /** - * @return Returns the autoLaunch. - */ - public boolean isAutoLaunch() { - return this.autoLaunch; - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - propertyListeners.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - propertyListeners.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - propertyListeners.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - propertyListeners.removePropertyChangeListener(propertyName, listener); - } - - /** - * @param autoLaunch The autoLaunch to set. - */ - public void setAutoLaunch(boolean autoLaunch) { - synchronized (this) { - boolean oldValue = this.autoLaunch; - this.autoLaunch = autoLaunch; - if (this.autoLaunch) { - this.notifyAll(); - } - propertyListeners.firePropertyChange("autoLaunch", oldValue, autoLaunch); - } - } - - public void waitAutoLaunch() { - synchronized(this) { - while (!isAutoLaunch()) { - try { - log.info("autoLaunch is false waiting queue start"); - this.wait(); - } catch (InterruptedException eee) { - log.warn("Error during wait autoLaunch flag", eee); - } - } - } - } - - /** - * Cree l'objet de gestion de la simulation en interne et le place dans la - * bonne queue de simulation (local/remote). Appel le - * {@link #fireAddEvent(String, SimulationItem)} - * @param id l'id de simulation - * @param param les paramètres de la simulation - */ - public void addSimulation(String id, SimulationParameter param) throws Exception { - ExecutorService executor = null; - Runnable job = null; - if (param.getLocal()) { - executor = localExecutor; - log.debug(_("isisfish.message.add.queue", id)); - } else { - executor = remoteExecutor; - log.debug(_("isisfish.message.add.queue.remote", id)); - } - - - - // on construit le bon type de SimulationItem pour le job - SimulationItem item = null; - if (param.getUseAnalysePlan()) { - // c un plan d'analyse, il peut etre independant ou dependant - if (!param.isIndependentPlan()) { - item = new SimulationItemPlan(id, param); - job = new SimulationJob(this, item); - } else { - // on met dans la queue local le process de generation de toutes - // les simus - item = new SimulationItemPlanIndependent(id, param); - job = new PrepareIndependentSimulationJob(this, executor, item); - executor = localExecutor; // change after job creation, because job need reel executor - } - } else { - // une simulation normal - item = new SimulationItem(id, param); - log.info("Simulation added to executor: " + executor.isShutdown() + ", " + executor.isTerminated()); - job = new SimulationJob(this, item); - } - fireAddEvent(id, item); // must be before thread notification because thread look in map - executor.execute(job); - } - - /** - * Envoie le signal stop a la simulation et la supprime de la liste des - * simulation disponible en appelant {@link #fireRemoveEvent(String)} - * - * @param id l'id de simulation - */ - public void removeSimulation(String id) { - SimulationItem item = map.get(id); - if (item != null) { - item.control.setStopSimulationRequest(true); - } - fireRemoveEvent(id); - } - - /** - * Retourne une liste toujours dans le meme ordre des ids de simulation - * a faire - * @return - */ - public List<String> getIds() { - List<String> result = new ArrayList<String>(map.keySet()); - return result; - } - - /** - * Retourne une liste toujours dans le meme ordre des ids de simulation - * a faire - * @return - */ - public List<String> getDoneIds() { - List<String> result = new ArrayList<String>(mapDones.keySet()); - return result; - } - - /** - * @param id l'id de simulation - * @return <code>true</code> si un identifiant est utilisé pour une simulation - */ - public boolean exists(String id) { - //TODO Doit-on tenir compte des simulations terminées ? - boolean result; - result = map.containsKey(id); - return result; - } - /** - * @param id l'id de simulation - * @return <code>true</code> si l'identifiant est utilisé pour une simulation terminée - */ - public boolean existsDone(String id) { - boolean result; - result = mapDones.containsKey(id); - return result; - } - - - public void addSimulationQueueListener(SimulationQueueListener l) { - listeners.add(l); - } - - public void removeSimulationQueueListener(SimulationQueueListener l) { - listeners.remove(l); - } - - protected void fireAddEvent(String id, SimulationItem item) { -// ids.add(id); - map.put(id, item); - SimulationQueueEvent e = new SimulationQueueEvent(this, id); - for (SimulationQueueListener l : listeners) { - l.simulationAdded(e); - } - } - - protected void fireRemoveEvent(String id) { - if (map.containsKey(id)) { - // add the simulation in done model - // check if we should keep the simulation in done model - if (mustShowSimulationDone(id)) { -// idDones.add(id); - SimulationItem queueItem = map.get(id); -// dones.add(queueItem); - mapDones.put(id, queueItem); - } - SimulationQueueEvent e = new SimulationQueueEvent(this, id); - for (SimulationQueueListener l : listeners) { - l.simulationWillBeRemoved(e); - } -// ids.remove(id); - map.remove(id); - } - } - - protected void fireStartEvent(String id, SimulationItem item) { - if (!exists(id) && item.isIndependent()) { - // la simulation qui vient d'etre lancee n'existe pas, c parce qu'il - // s'agit d'une simulation de plan, on l'ajoute a la liste pour que - // l'utilisateur puisse la visualiser. On ne le fait pas pour les - // plan dependant car, il partage le meme controleur, donc - // l'utilisateur voit deja ce qui se passe - fireAddEvent(id, item); - } - SimulationQueueEvent e = new SimulationQueueEvent(this, id); - for (SimulationQueueListener l : listeners) { - l.simulationStart(e); - } - } - - protected void fireStopEvent(String id) { - SimulationQueueEvent e = new SimulationQueueEvent(this, id); - for (SimulationQueueListener l : listeners) { - l.simulationStop(e); - } - } - - /** - * @param id id of simulation - * @return Returns the parameters. - */ - public SimulationParameter getParameter(String id) { - return map.get(id).param; - } - - /** - * @param id id of simulation - * @return Returns the controls. - */ - public SimulationControl getControl(String id) { - SimulationControl result = null; - SimulationItem item = map.get(id); - if (item == null) { - // try to find it in done simulation - item = mapDones.get(id); - } - if (item != null) { - result = item.control; - } - return result; - } - - /** - * @param id simulation id - * @return <code>tru</code> if we should add in simulation done model - * the corresponding simulation - */ - protected boolean mustShowSimulationDone(String id) { - IsisConfig config = IsisFish.config; - - boolean result = !config.isSimulationShowOnlyError(); - try { - - SimulationItem item = map.get(id); - - if (result || (!(item instanceof SimulationItemPlan) && - item.getSimulation().getInformation().hasError())) { - result = true; - } - -// if (item.hasPlanItem() && !item.getSimulation().getInformation().hasError()) { -// // on ne met jamais dans la queue done les simulations de plan -// // sauf si elle echoue -// result = false; -//// FIXME a revoir la condition avec showOnly error et showOnly queue (qui ne sert plus) -// } else if (!(config.isSimulationShowOnlyError() && -// !(item instanceof SimulationItemPlan) && -// item.getSimulation().getInformation().hasError())) { -// result = false; -// } - } catch (Exception eee) { - log.debug("Ne devrait pas arriver", eee); - // I don't known how it could appear, but in doubt, show it! - } - return result; - } - -// /** -// * Thread permettant de faire les simulations se trouvant dans la queue -// * passée en parametre. -// * <p> -// * Si la simulation prise dans la queue n'existe plus, au moment ou on -// * souhaite l'utiliser dans le {@link SimulationManager} alors elle est -// * passée et on en recherche une autre. -// * -// * @author poussin -// */ -// static class SimulationThread extends Thread { -// protected SimulationManager simulationManager; -// protected BlockingQueue<QueueItem> queue; -// -// /** -// * -// * @param name just small name to differenciate thread (local/remote) -// * @param simulationManager le manager de simulation -// * @param queue la queue de simulations -// */ -// public SimulationThread(String name, SimulationManager simulationManager, BlockingQueue<QueueItem> queue) { -// super("Simulation Thread " + name); -// this.simulationManager = simulationManager; -// this.queue = queue; -// } -// -// /* (non-Javadoc) -// * @see java.lang.Thread#run() -// */ -// @Override -// public void run() { -// log.info("Start simulation thread"); -// while (true) { -// // simItem qui sert a faire la simulation courante -// QueueItem simItem = null; -// try { -// // -// // recheche d'une simulation -// // -// while (simItem == null) { -// log.debug("try to take simulation"); -// simItem = queue.take(); -// log.debug("Just take " + simItem.id); -// if (!simulationManager.exists(simItem.id)) { -// // on ne le retrouve pas dans la map, la simulation -// // a donc ete supprimée par l'utilisateur on passe a la -// // suivante -// simItem = null; -// } else if (!simulationManager.isAutoLaunch() && simItem.param.getInQueue()) { -// // don't use simItem, because is queue and queue is not launched -// queue.add(simItem); -// simItem = null; -// // sleep 1s. Because all other simItem is in queue too -// // this sleep permit to user to put not queue simItem, -// // with out eat cpu -// sleep(1000); -// } -// } -// -// log.debug("use if has next simulation: " + simItem.id); -// if (simItem.hasNext()) { -// SimulationStorage sim = simItem.getSimulation(); -// String simId = sim.getName(); -// log.debug("Start simulation: " + simId); -// SimulationControl control = simItem.control; -// // set date to 0 at beginning of simulation -// control.setDate(new Date()); -// control.setProgress(0); -// control.setStarted(true); -// -// simulationManager.fireStartEvent(simItem.id); -// try { -// sim = SimulationHelper.simulate(control, sim); -// simItem.setLastSimulation(sim); -// } finally { -// simulationManager.fireStopEvent(simItem.id); -// } -// // copie les exports de simulation dans le repertoire -// // souhaiter par l'utilisateur -// SimulationParameter param = sim.getParameter(); -// if (param.getExportNames() != null && param.getExportNames().size() > 0) { -// File exportDir = IsisConfig.getResultExportDirectory(sim.getDirectory()); -// FileUtil.copyAndRenameRecursively( -// exportDir, -// new File(param.getExportDirectory()), -// exportDir.getName(), simItem.id); -//// FileUtil.copyAndRenameRecursively( -//// exportDir, -//// new File(sim.getDirectory(), IsisConfig.RESULT_EXPORT), -//// IsisConfig.RESULT_EXPORT, simItem.id); -// } -// -// if (simItem.hasNext() && simulationManager.exists(simItem.id)) { -// // il y a encore des simulations a faire pour cet simItem -// // on le remet dans la queue (on ne fait pas les autres -// // simulations de cet simItem -// // tout de suite car l'simItem peut-etre un simItem de queue -// // moins prioritaire que les autres simulations -// // il faut donc qu'il reprenne sa place dans l'ordre) -// -// queue.add(simItem); -// } else { -// // Si l'utilisateur souhaite seulement les exports -// // on supprimer la/les simulations. Il faut le faire -// // lorsqu'il n'y a plus de next car le calcul des plans -// // peut avoir besoin des simulations precedentes -// if (param.getOnlyExport()) { -// if (param.getUseAnalysePlan()) { -// for(File file : FileUtil.find( -// IsisConfig.getSimulationDirectory(), -// simItem.id + "_[0-9]+$", false)) { -// log.debug("Delete simulation " + file); -// FileUtil.deleteRecursively(file); -// } -// } else { -// sim.delete(false); -// } -// } -// simulationManager.fireRemoveEvent(simItem.id); -// -// if (simulationManager.isAutoLaunch() && simItem.param.getInQueue()) { -// // if simItem is last in queue, stop the queue after that -// QueueItem [] items = queue.toArray(new QueueItem[queue.size()]); -// if (items.length > 0) { -// QueueItem last = items[items.length-1]; -// if (!last.param.getInQueue()) { -// // la derniere n'est pas en queue, donc plus de simulation en queue -// simulationManager.setAutoLaunch(false); -// } -// } else { -// // aucun simulation, donc forcement plus en queue non plus -// simulationManager.setAutoLaunch(false); -// } -// } -// } -// } -// -//// } catch (Exception eee) { -// } catch (Throwable eee) { -// try { -// // on sauvegarde l'erreur rencontrée, elle sera traité lors -// // du fireRemoveEvent -// simItem.lastSimulation.getInformation().setException(eee); -// } catch (Exception e) { -// if (log.isWarnEnabled()) { -// log.warn(_("isisfish.error.during.simulation.information.file", simItem.id), eee); -// } -// } finally { -// // error during simulation, remove bad simulation -// simulationManager.fireRemoveEvent(simItem.id); -// if (log.isWarnEnabled()) { -// log.warn(_("isisfish.error.during.simulation", simItem.id), eee); -// } -// } -// -// } finally { -// simItem = null; -// } -// } -// } -// } - -// /** -// * Utilise pour les simulations avec plan d'analyse dependant -// */ -// static class SimulationPlanJob implements Runnable { -// -// protected SimulationManager simulationManager; -// protected SimulationItemPlan item; -// -// public SimulationPlanJob(SimulationManager simulationManager, SimulationItemPlan item) { -// this.simulationManager = simulationManager; -// this.item = item; -// } -// -// public void run() { -// try { -// log.debug("use if has next simulation: " + item.id); -// // on traite tout l'simItem dans le meme thread -// while (simulationManager.exists(item.id) && item.hasNext()) { -// SimulationStorage sim = item.getSimulation(); -// String simId = sim.getName(); -// log.debug("Start simulation: " + simId); -// SimulationControl control = item.control; -// // set date to 0 at beginning of simulation -// control.setDate(new Date()); -// control.setProgress(0); -// control.setStarted(true); -// -// simulationManager.fireStartEvent(item.id); -// try { -// sim = SimulationHelper.simulate(control, sim); -// item.setLastSimulation(sim); -// } finally { -// simulationManager.fireStopEvent(item.id); -// } -// // copie les exports de simulation dans le repertoire -// // souhaiter par l'utilisateur -// SimulationParameter param = sim.getParameter(); -// if (param.getExportNames() != null && -// param.getExportNames().size() > 0) { -// File exportDir = IsisConfig.getResultExportDirectory( -// sim.getDirectory()); -// FileUtil.copyAndRenameRecursively( -// -// exportDir, -// new File(param.getExportDirectory()), -// exportDir.getName(), item.id); -//// FileUtil.copyAndRenameRecursively( -//// exportDir, -//// new File(sim.getDirectory(), IsisConfig.RESULT_EXPORT), -//// IsisConfig.RESULT_EXPORT, simItem.id); -// } -// } -// -// if (item.lastSimulation != null) { -// SimulationParameter param = item.param; -// // Si l'utilisateur souhaite seulement les exports -// // on supprimer la/les simulations. Il faut le faire -// // lorsqu'il n'y a plus de next car le calcul des plans -// // peut avoir besoin des simulations precedentes -// if (param.getOnlyExport()) { -// if (param.getUseAnalysePlan()) { -// for (File file : FileUtil.find( -// IsisConfig.getSimulationDirectory(), -// item.id + "_[0-9]+$", false)) { -// log.debug("Delete simulation " + file); -// FileUtil.deleteRecursively(file); -// } -// } else { -// item.lastSimulation.delete(false); -// } -// } -// } -// // on previent que c la fin de la simulation -// simulationManager.fireRemoveEvent(item.id); -// } catch (Throwable eee) { -// try { -// // on sauvegarde l'erreur rencontrée, elle sera traité lors -// // du fireRemoveEvent -// if (item.lastSimulation != null) { -// item.lastSimulation.getInformation().setException(eee); -// } -// } catch (Exception e) { -// if (log.isWarnEnabled()) { -// log.warn(_("isisfish.error.during.simulation.information.file", item.id), eee); -// } -// } finally { -// // error during simulation, remove bad simulation -// simulationManager.fireRemoveEvent(item.id); -// if (log.isWarnEnabled()) { -// log.warn(_("isisfish.error.during.simulation", item.id), eee); -// } -// } -// -// } finally { -// item = null; -// } -// } -// -// } - - class PrepareIndependentSimulationJob implements Runnable { - - protected SimulationManager simulationManager; - protected ExecutorService executor; - protected SimulationItem item; - - public PrepareIndependentSimulationJob(SimulationManager simulationManager, - ExecutorService executor, - SimulationItem item) { - this.simulationManager = simulationManager; - this.executor = executor; - this.item = item; - } - - public void run() { - simulationManager.waitAutoLaunch(); - // l'item est independant, on ajoute toutes ces simulations en plus - // mais pas dans la map pour qu'il n'y ait bien que l'initiale - // plus celles en cours d'affichees - while (item.hasNext()) { - try { - executor.execute(new SimulationJob(simulationManager, item.next())); - } catch (Exception eee) { - log.error("Can't add simulation: " + item, eee); - } - } - - } - - } - - /** - * Utilise pour les simulations sans plan d'analyse ou des plans independant - */ - class SimulationJob implements Runnable { - - protected SimulationManager simulationManager; - protected SimulationItem simItem; - - /** - * - * @param simulationManager - * @param parentId si ce job est le resulat d'un plan d'analyse - * independant, sinon null ou la meme valeur que id - * @param id l'identifiant de la simulation (avec _N pour ceux qui - * proviennent d'un plan d'analyse) - * @param zip le zip contenant la simulation - */ - public SimulationJob(SimulationManager simulationManager, - SimulationItem item) { - this.simulationManager = simulationManager; - this.simItem = item; - } - - public void run() { - log.info("Start simulation : " + simItem.id); - simulationManager.waitAutoLaunch(); - try { - // si l'simItem exist encore (que l'utilisateur ne la pas retire) - log.info("id: " + simItem.getPlanIdOrId() + " exists ? " + - simulationManager.exists(simItem.getPlanIdOrId()) + - " hasNext ? " + simItem.hasNext()); - while (simulationManager.exists(simItem.getPlanIdOrId()) && - simItem.hasNext()) { - SimulationItem item = simItem.next(); - try { - String id = item.id; - - log.debug("Start simulation: " + id); - SimulationStorage simulation = item.getSimulation(); - SimulationControl control = item.control; - // set date to 0 at beginning of simulation - control.setDate(new Date()); - control.setProgress(0); - control.setStarted(true); - - simulationManager.fireStartEvent(id, item); - try { - simulation = SimulationHelper.simulate(control, simulation); - item.setLastSimulation(simulation); - } finally { - simulationManager.fireStopEvent(id); - } - // copie les exports de simulation dans le repertoire - // souhaiter par l'utilisateur - SimulationParameter param = simulation.getParameter(); - if (param.getExportNames() != null && - param.getExportNames().size() > 0) { - File exportDir = SimulationStorage.getResultExportDirectory( - simulation.getDirectory()); - FileUtil.copyAndRenameRecursively( - exportDir, - new File(param.getExportDirectory()), - // FIXME, est-ce bien parentId et pas id ? - exportDir.getName(), id); -// FileUtil.copyAndRenameRecursively( -// exportDir, -// new File(sim.getDirectory(), IsisConfig.RESULT_EXPORT), -// IsisConfig.RESULT_EXPORT, simItem.id); - } - // Si l'utilisateur souhaite seulement les exports - // on supprimer la/les simulations. - // pour les plan dependant il faut le faire apres toutes - // les simulations - if (simItem.isIndependent() && param.getOnlyExport()) { - simulation.delete(false); - } - // on previent que c la fin de la simulation - simulationManager.fireRemoveEvent(id); - } catch (Throwable eee) { - try { - // on sauvegarde l'erreur rencontrée, elle sera traité lors - // du fireRemoveEvent - item.getSimulation().getInformation().setException(eee); - } catch (Exception e) { - if (log.isWarnEnabled()) { - log.warn(_("isisfish.error.during.simulation.information.file", item.id), eee); - } - } finally { - // error during simulation, remove bad simulation - simulationManager.fireRemoveEvent(item.id); - if (log.isWarnEnabled()) { - log.warn(_("isisfish.error.during.simulation", item.id), eee); - } - } - } - } - } catch (Exception eee) { - log.error("Can't take next simulation: " + simItem.id, eee); - } - // suppression des simulations pour les plans dependants - // Si l'utilisateur souhaite seulement les exports - // on supprimer la/les simulations. Il faut le faire - // lorsqu'il n'y a plus de next car le calcul des plans - // peut avoir besoin des simulations precedentes - if (!simItem.isIndependent() && simItem.param.getOnlyExport()) { - for (File file : FileUtil.find( - SimulationStorage.getSimulationDirectory(), - simItem.id + "_[0-9]+$", false)) { - log.debug("Delete simulation " + file); - FileUtil.deleteRecursively(file); - } - } - - if (!simItem.control.isRunning() && simItem.hasSimulation()) { - // c'etait la derniere simulation du plan, on arrete le plan - simulationManager.fireStopEvent(simItem.id); - simulationManager.fireRemoveEvent(simItem.id); - } - } - } - - /** - * Une simulation a faire sans plan d'experience - */ - public class SimulationItem { - - protected String id; - protected SimulationParameter param; - protected SimulationItemPlan planItem = null; - protected File zip; - protected SimulationControl control; - protected SimulationStorage lastSimulation = null; - - protected SimulationItem() { - } - - public boolean isIndependent() { - return true; - } - - /** - * Utilise pour servir sous simItem pour les items de plan d'experience - * @param id - * @param control - * @param sim - */ - public SimulationItem(SimulationItemPlan planItem, SimulationControl control, - SimulationStorage sim) { - this.planItem = planItem; - this.id = sim.getName(); - param = sim.getParameter(); - this.control = control; - lastSimulation = sim; - } - - /** - * Retourne l'id du plan qui a genere cet item, si cet item n'est - * pas genere par un plan, retourne directement l'id - * @return - */ - public String getPlanIdOrId() { - String result = id; - if (hasPlanItem()) { - result = getPlanItem().id; - } - return result; - } - - public SimulationItemPlan getPlanItem() { - return planItem; - } - - /** - * Si renvoi vrai, cela veut dire que cette simulation a ete generee - * par un plan d'experience - * - * @return - */ - public boolean hasPlanItem() { - boolean result = planItem != null; - return result; - } - - /** - * creer un simItem de simulation et prepare le zip - * @param id - * @param param - */ - public SimulationItem(String id, SimulationParameter param) { - this.id = id; - this.param = param; - this.control = new SimulationControl(id); - zip = SimulationHelper.prepareSimulationZipFile(control, param, true); - } - - public boolean hasSimulation() { - boolean result = lastSimulation != null; - return result; - } - - /** - * Retourne la simulation qu'il faut faire - * @return le storage de simulation - * @throws Exception si problème pendant l'import de la simulation - */ - public SimulationStorage getSimulation() throws Exception { - if (lastSimulation == null) { - lastSimulation = SimulationStorage.importAndRenameZip(zip, id); - } - return lastSimulation; - } - - /** - * Appelé apres que la simulation est vraiment eu lieu. On en a besoin - * car pour une simulation distante apres la simulation le storage - * a ete changé par rapport au storage initialement cree pour la - * simulation - * - * @param lastSimulation The lastSimulation to set. - */ - public void setLastSimulation(SimulationStorage lastSimulation) { - this.lastSimulation = lastSimulation; - if (hasPlanItem()) { - getPlanItem().setLastSimulation(lastSimulation); - } - } - - /** - * @return <code>true</code> s'il y a encore une simulation si on - * utilise un plan et qu'il dit qu'il y en a encore, ou si la simulation - * n'a pas encore ete faite. - */ - public boolean hasNext() { - boolean result; - result = !control.isStarted(); - return result; - } - - /** - * Ce retourne lui meme, car il n'y a pas de plan - * @return - */ - public SimulationItem next() throws Exception { - return this; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - boolean result = false; - if (obj instanceof SimulationItem) { - result = param.equals(((SimulationItem)obj).param); - } - return result; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 53 * hash + (this.param != null ? this.param.hashCode() : 0); - return hash; - } - - } - - /** - * Une simulation a faire qui contient un plan d'experience dependant - */ - public class SimulationItemPlan extends SimulationItem - implements PropertyChangeListener { - // FIXME a mettre en config MAX_SIMULATION_PLAN - // nombre maximal de simulation de plan par simulation - // (pour eviter les plans qui ne retroune jamais faux - protected static final int MAX_SIMULATION_PLAN = 10000; - - protected int simulationNumber = 0; - protected int simulationFinished = 0; - protected PlanGenerator plan = null; - - public SimulationItemPlan(String id, SimulationParameter param) { - this.id = id; - this.param = param; - this.control = new SimulationControl(id); - // ne pas inverser la creation de PlanGenerator et du zip. - // car le init des plans est fait dans le constructeur de - // PlanGenerator, et le init peut modifier les parametres - // de simulation - if (!param.getUseAnalysePlan()) { - throw new SimulationException("Your simulation is not a plan:" + id); - } - - plan = new PlanGenerator(id, control, param); - zip = SimulationHelper.prepareSimulationZipFile(control, param, true); - plan.setZip(zip); - } - - @Override - public boolean isIndependent() { - return false; - } - - /** - * Retourne la simulation qu'il faut faire - * @return le storage de simulation - * @throws Exception si problème pendant l'import de la simulation - */ - @Override - public SimulationStorage getSimulation() throws Exception { - throw new UnsupportedOperationException("Plan item don't have simulation"); - } - - /** - * Retourne la simulation qu'il faut faire - * @return le storage de simulation - * @throws Exception si problème pendant l'import de la simulation - */ - public SimulationStorage getNextSimulation() throws Exception { - SimulationStorage result; - result = plan.next(); - simulationNumber++; - lastSimulation = result; - return result; - } - - /** - * Appelé apres que la simulation est vraiment eu lieu. On en a besoin - * car pour une simulation distante apres la simulation le storage - * a ete changé par rapport au storage initialement cree pour la - * simulation - * - * @param lastSimulation The lastSimulation to set. - */ - @Override - public void setLastSimulation(SimulationStorage lastSimulation) { - this.lastSimulation = lastSimulation; - plan.setLastSimulation(lastSimulation); - } - - /** - * @return <code>true</code> s'il y a encore une simulation si on - * utilise un plan et qu'il dit qu'il y en a encore, ou si la simulation - * n'a pas encore ete faite. - */ - @Override - public boolean hasNext() { - boolean result; - result = simulationNumber < MAX_SIMULATION_PLAN && - ((plan != null && plan.hasNext()) || lastSimulation == null); - return result; - } - - /** - * On utilise le meme control pour les plans dependants - * @return - */ - @Override - public SimulationItem next() throws Exception { - SimulationStorage sim = getNextSimulation(); - SimulationItem result = new SimulationItem(this, control, sim); - return result; - } - - public void propertyChange(PropertyChangeEvent evt) { - // Attention il faut bien que toutes les simultions soit - // genere (ou qu'il en reste au moins une en cours - // sinon, la condition est tout de suite vrai et la simulation - // s'arrete. Ce qui est normalement le cas ici, car on utilise - // le meme executor pour genere les simultions que pour les faire - // et les generes est mis en premier dans l'executor, mais si - // on est multi cpu, et que le temps de simulation est inferieur - // au temps de generation des simulations, on pourrai finir par - // avoir un probleme. - - if (Boolean.FALSE.equals(evt.getNewValue())) { - simulationFinished++; - control.setProgress(simulationFinished); - control.setText(simulationFinished + " / " + simulationNumber); - if (simulationFinished >= simulationNumber) { - log.info("All simulations have been executed: " + simulationFinished); - control.stopSimulation(); - String id = control.getId(); - SimulationManager.this.fireStopEvent(id); - SimulationManager.this.fireRemoveEvent(id); - } - } - } - - } - - /** - * Une simulation a faire qui contient un plan d'experience independant - */ - public class SimulationItemPlanIndependent extends SimulationItemPlan { - - public SimulationItemPlanIndependent(String id, SimulationParameter param) { - super(id, param); - } - - @Override - public boolean isIndependent() { - return true; - } - - /** - * On utilise un nouveau control pour les plans independants - * @return - */ - @Override - public SimulationItem next() throws Exception { - SimulationStorage sim = getNextSimulation(); - control.setProgressMax(simulationNumber); - SimulationControl control = new SimulationControl(sim.getName()); - control.addPropertyChangeListener("running", this); - SimulationItem result = new SimulationItem(this, control, sim); - return result; - } - - } - -} - - Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationParameter.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationParameter.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationParameter.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -124,15 +124,6 @@ protected String exportDirectory = "/tmp"; - /** La simulation doit etre faite en local */ - protected boolean local = true; - - /** La simulation doit etre faite dans un sous process */ - protected boolean subProcess = false; - - /** La simulation doit etre lancé dans la queue de simulation (non prioritaire)*/ - protected boolean inQueue = false; - /** utilisation du script de pre simulation */ protected boolean usePreScript = false; @@ -275,9 +266,6 @@ } result.setProperty("exports", exportList); - result.setProperty("local", String.valueOf(local)); - result.setProperty("subProcess", String.valueOf(subProcess)); - result.setProperty("inQueue", String.valueOf(inQueue)); result.setProperty("usePreScript", String.valueOf(usePreScript)); result.setProperty("preScript", preScript); result.setProperty("useAnalysePlan", String.valueOf(useAnalysePlan)); @@ -418,9 +406,6 @@ } } - local = Boolean.parseBoolean(props.getProperty("local", "true")); - subProcess = Boolean.parseBoolean(props.getProperty("subProcess", "false")); - inQueue = Boolean.parseBoolean(props.getProperty("inQueue", "false")); usePreScript = Boolean.parseBoolean(props.getProperty("usePreScript", "false")); preScript = props.getProperty("preScript"); @@ -672,42 +657,6 @@ } /** - * @return Returns the local. - */ - public boolean getLocal() { - return this.local; - } - - /** - * @param local The local to set. - */ - public void setlocal(boolean local) { - this.local = local; - } - - public void setSubProcess(boolean subProcess) { - this.subProcess = subProcess; - } - - public boolean isSubProcess() { - return subProcess; - } - - /** - * @return Returns the inQueue. - */ - public boolean getInQueue() { - return this.inQueue; - } - - /** - * @param inQueue The inQueue to set. - */ - public void setInQueue(boolean inQueue) { - this.inQueue = inQueue; - } - - /** * @return Returns the useOptimization. */ public boolean getUseOptimization() { @@ -972,8 +921,6 @@ result.simulatorName = simulatorName; result.useOptimization = useOptimization; result.useStatistic = useStatistic; - result.local = local; - result.inQueue = inQueue; result.usePreScript = usePreScript; result.preScript = preScript; result.useAnalysePlan = useAnalysePlan; Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueEvent.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueEvent.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueEvent.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,64 +0,0 @@ -/* *##% - * Copyright (C) 2006 - * Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -/* * - * SimulationQueueEvent.java - * - * Created: 17 août 2006 22:00:41 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ - -package fr.ifremer.isisfish.simulator; - -import java.util.EventObject; - - -/** - * @author poussin - * - */ - -public class SimulationQueueEvent extends EventObject { - - /** simulation id */ - protected String id; - - /** - * @param source - */ - public SimulationQueueEvent(Object source, String id) { - super(source); - this.id = id; - } - - /** - * @return Returns the id. - */ - public String getId() { - return this.id; - } - -} - - Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueListener.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueListener.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueListener.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,55 +0,0 @@ -/* *##% - * Copyright (C) 2006 - * Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -/* * - * SimulationQueueListener.java - * - * Created: 17 août 2006 21:59:02 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ - -package fr.ifremer.isisfish.simulator; - -import java.util.EventListener; - - -/** - * @author poussin - * - */ - -public interface SimulationQueueListener extends EventListener { - - /** call when one simulation is added to the queue */ - public void simulationAdded(SimulationQueueEvent e); - /** call when one simulation will be removed from the queue */ - public void simulationWillBeRemoved(SimulationQueueEvent e); - /** call when one simulation begin */ - public void simulationStart(SimulationQueueEvent e); - /** call when one simulation stop */ - public void simulationStop(SimulationQueueEvent e); - -} - - Deleted: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,99 +0,0 @@ -/* *##% - * Copyright (C) 2006 - * Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *##%*/ - -/* * - * SimulationQueueModel.java - * - * Created: 18 août 2006 00:05:41 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ - -package fr.ifremer.isisfish.simulator; - -import java.util.ArrayList; -import java.util.List; - -/** @author poussin */ - -public class SimulationQueueModel extends AbstractSimulationQueueModel { - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel() - */ - public SimulationQueueModel() { - super(); - } - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel(SimulationManager) - */ - public SimulationQueueModel(SimulationManager queue) { - super(queue); - } - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel at getSimulationIds() - */ - protected java.util.List<String> getSimulationIds() { - return getQueue().getIds(); - } - - /* (non-Javadoc) - * @see AbstractSimulationQueueModel at getQueueItemsAsMap() - */ - protected java.util.Map<String, SimulationManager.SimulationItem> getQueueItemsAsMap() { - return getQueue().map; - } - - /* (non-Javadoc) - * @see SimulationQueueListener#simulationAdded(fr.ifremer.isisfish.simulator.SimulationQueueEvent) - */ - public void simulationAdded(SimulationQueueEvent e) { - int row = getRowCount(); - fireTableRowsInserted(row, row); - SimulationControl control = getSimulationControl(e.getId()); - if (control != null) { - control.addPropertyChangeListener(this); - } else { - log.warn("Simulation without controler: " + e.getId()); - } - } - - /* (non-Javadoc) - * @see SimulationQueueListener#simulationRemoved(fr.ifremer.isisfish.simulator.SimulationQueueEvent) - */ - public void simulationWillBeRemoved(SimulationQueueEvent e) { - String id = e.getId(); - SimulationControl control = getSimulationControl(e.getId()); - if (control != null) { - control.removePropertyChangeListener(this); - } - int row = getSimulationIndex(id); - if (isRowIndexValid(row)) { - fireTableRowsDeleted(row, row); - } - progress.remove(id); - } - -} // SimulationQueueModel \ No newline at end of file Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/Simulator.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/Simulator.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/Simulator.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -34,8 +34,6 @@ /** * This interface is used when simulator have all code for simulation. - * This is the old interface for simulator, now we prefer to used - * {@link SimulatorStep} * * @author poussin */ Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulatorServer.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulatorServer.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/SimulatorServer.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -44,6 +44,8 @@ import org.codelutin.util.FileUtil; import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.launcher.InProcessSimulatorLauncher; +import fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher; /** * Cette classe permet de lancer un serveur XML-RPC qui attend des demandes @@ -121,12 +123,13 @@ String id = (String) params.get(0); File zip = FileUtil.byteToFile((byte[]) params.get(1)); - SimulationStorage simulation = SimulationStorage.importAndRenameZip(zip, id); SimulationControl control = new SimulationControl(id); + SimulationStorage simulation = null; simulationControls.put(id, control); try { - simulation = SimulationHelper.localSimulate(control, simulation); + SimulatorLauncher launcher = new InProcessSimulatorLauncher(); + simulation = launcher.simulate(null, control, zip); zip = simulation.createZip(); byte [] result = FileUtil.fileToByte(zip); Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,413 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.simulator.launcher; + +import static org.codelutin.i18n.I18nf._; + +import fr.ifremer.isisfish.IsisConfig; +import fr.ifremer.isisfish.IsisFish; +import fr.ifremer.isisfish.IsisFishRuntimeException; +import fr.ifremer.isisfish.aspect.AspectClassLoader; +import fr.ifremer.isisfish.aspect.Cache; +import fr.ifremer.isisfish.aspect.Trace; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.datastore.SimulatorStorage; +import fr.ifremer.isisfish.simulator.SimulationContext; +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationException; +import fr.ifremer.isisfish.simulator.SimulationExportResultWrapper; +import fr.ifremer.isisfish.simulator.SimulationListener; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import fr.ifremer.isisfish.simulator.SimulationPreScript; +import fr.ifremer.isisfish.simulator.Simulator; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.rmi.RemoteException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.profiling.LutinTrace; +import org.codelutin.topia.TopiaContext; +import org.codelutin.topia.TopiaException; +import org.codelutin.topia.event.TopiaTransactionEvent; +import org.codelutin.topia.event.TopiaTransactionListener; +import org.codelutin.topia.persistence.TopiaEntity; +import org.codelutin.util.ObjectUtil; +import org.codelutin.util.StringUtil; + +/** + * Fait une simulation dans la meme jvm + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class InProcessSimulatorLauncher implements SimulatorLauncher { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(InProcessSimulatorLauncher.class); + + public SimulationStorage simulate(SimulationService simulationService, + SimulationControl control, File simulationZip) + throws RemoteException{ + String id = control.getId(); + + SimulationStorage simulation = null; + try { + simulation = SimulationStorage.importAndRenameZip(simulationZip, id); + simulation = localSimulate(control, simulation); + } catch (Exception eee) { + log.error(_("Can't do simulation %s", id), eee); + simulation.getInformation().setException(eee); + } + return simulation; + } + + public int maxSimulationThread() { + return 1; + } + + @Override + public String toString() { + return _("in Process"); + } + + protected void message(SimulationControl control, String message) { + log.info(message); + if (control != null) { + control.setText(message); + } + } + + /** + * fait la simulation en local dans un nouveau thread, cela permet + * pour chaque simulation d'avoir les bons scripts dans le classloader + * et non pas d'utiliser les scripts d'une autre simulation + * + * @param control le controleur de simulation, peut-etre null si on ne + * souhaite pas controler la simulation + * @param simulation la simulation a faire + * @return le storage après simulation en locale + */ + protected SimulationStorage localSimulate(SimulationControl control, SimulationStorage simulation) { + SimThread simThread = new SimThread(control, simulation); + // add simulation logger, we can't make it before since we need thread name + // anyway since if accept only log from simThread, no need to init it before + String simulLogLevel = simulation.getParameter().getSimulLogLevel(); + String scriptLogLevel = simulation.getParameter().getScriptLogLevel(); + String libLogLevel = simulation.getParameter().getLibLogLevel(); + try { + simulation.addSimulationLogger(simulLogLevel,scriptLogLevel,libLogLevel,simThread.getName()); + } catch (Exception e) { + if (log.isWarnEnabled()) { + log.warn(_("isisfish.error.add.logger.simulation ", e)); + } + } + try { + simThread.start(); + try { + simThread.join(); + } catch (InterruptedException eee) { + if (log.isWarnEnabled()) { + log.warn(_("isisfish.error.wait.simThread"), eee); + } + } + } finally { + // remove simulation logger (no more need since thread is dead) + simulation.removeSimulationLogger(); + } + return simulation; + } + + protected class SimThread extends Thread { + protected SimulationControl control; + protected SimulationStorage simulation; + + public SimThread(SimulationControl control, SimulationStorage simulation) { + super("SimThread " + (control!=null?control.getId():"")); + this.control = control; + this.simulation = simulation; + } + @Override + public void run() { + simulation = localSimulateSameThread(control, simulation); + } + } + + /** + * Modifie le classloader du thread passé en paramètre. + * <p> + * Sert pour les simulations pour qu'elles puissent trouver les + * script, rule et export + * + * @param thread le thread dont on souhaite modifier le classloader ou null + * @param directory le répertoire qui servira pour le classloader + * @return le classe loader modifié + */ + protected AspectClassLoader changeClassLoader(Thread thread, File directory) { + try { + URL [] classpath = new URL[]{directory.toURI().toURL(), + // poussin 20080821 + // il semble ne plus trouve les formules, est-ce mieux avec le compile dir ? + IsisFish.config.getCompileDirectory().toURI().toURL() + }; + //URL [] classpath = new URL[]{directory.toURL()}; + AspectClassLoader loader = new AspectClassLoader(classpath, ClassLoader.getSystemClassLoader()); //new URLClassLoader(classpath); + thread.setContextClassLoader(loader); + log.info("Classloader used for simulation: " + loader + " " + + Arrays.toString(loader.getURLs())); + return loader; + } catch (MalformedURLException eee) { + // on leve un runtime, car normalement cette erreur est pratiquement + // impossible car on creer l'url a partir d'un File ce qui ne pose + // noralement pas de probleme + throw new IsisFishRuntimeException(_("isisfish.error.change.classloader", directory), eee); + } + } + + /** + * Cree le simulation context, creer le ClassLoader, met en place les AOP, + * met a jour des informations sur la simulation et lance la simulation en + * local + * + * @param control le controleur de simulation, peut-etre null si on ne + * souhaite pas controler la simulation + * @param simulation la simulation a faire + * @return le storage après simulation en locale + */ + protected SimulationStorage localSimulateSameThread(SimulationControl control, SimulationStorage simulation) { + SimulationStorage result = null; + String jvmVersion = System.getProperty("java.runtime.version"); + log.info(SimpleDateFormat.getInstance().format(new java.util.Date()) + + " Java version: " + jvmVersion + " Isis-fish version: " + + IsisConfig.getVersion()); + long start = System.nanoTime(); + simulation.getInformation().setSimulationStart(new java.util.Date()); + AspectClassLoader classLoader; + try { + File rootDirectory = simulation.getDirectory(); + + // + // changement de classloader + // + classLoader = changeClassLoader(Thread.currentThread(), rootDirectory); + + // + // Creation et initialisation du context de simulation + // + SimulationContext context = SimulationContext.get(); + context.setClassLoader(classLoader); + context.setScriptDirectory(rootDirectory); + context.setSimulationStorage(simulation); + context.setSimulationControl(control!=null?control:new SimulationControl(simulation.getName())); + + SimulationParameter parameters = simulation.getParameter(); + parameters.setIsisFishVersion(IsisConfig.getVersion()); + // forceReload, save all modification in parameter and reread it + parameters = simulation.getForceReloadParameter(); + + // + // Activation de l'OAP demandée + // + if (parameters.getUseStatistic()) { + message(control, _("isisfish.message.setting.trace.aspects")); + classLoader.deploy(Trace.class); + } + if (parameters.getUseOptimization()) { + message(control, _("isisfish.message.setting.cache.aspects")); + classLoader.deploy(Cache.class); + } + + // recherche du simulateur a utiliser + String simulatorName = parameters.getSimulatorName(); + SimulatorStorage simulator = SimulatorStorage + .getSimulator(simulatorName); + Simulator simulatorObject = simulator.getNewSimulatorInstance(); + + // on se met listener sur tc pour connaitre tous les nouveaux objets + ObjectCreationListener objectCreationListener = new ObjectCreationListener(); + context.getDB().addTopiaTransactionListener(objectCreationListener); + + // + // Ajout des listeners pour la simulation + // + initSimulationListener(context); + + // + // Lancement du script de simulation selectionné + // + message(control, _("isisfish.message.simulation.execution")); + + // + // Call listener simulation (used per example for prescript) + // + context.fireBeforeSimulation(); + simulatorObject.simulate(context); + + // + // Ajout des nouveaux objets créées durant la simulation + // + message(control, _("isisfish.message.add.objets.simulation")); + // on ajoute sur le DBResult car pour les exports peut-etre auront + // nous besoin de ces nouveaux objets, et durant la simulation + // les resultats sont recuperer dans le DBResult + TopiaContext add = context.getDbResult(); + for (TopiaEntity e : objectCreationListener.getNewObjects()) { + log.debug("Add new object: " + e + "(" + e.getClass().getName() + ")"); + add.add(e); + } + add.commitTransaction(); + + // + // Call listener simulation (used per example for export) + // + context.fireAfterSimulation(); + + message(control, _("isisfish.message.simulation.ended")); + + simulation.getInformation().setSimulationEnd(new java.util.Date()); + + } catch (OutOfMemoryError eee) { + log.error(_("isisfish.error.during.simulation"),eee); + simulation.getInformation().setException(eee); + throw new SimulationException(_("isisfish.error.out.memory"), eee); + } catch (Exception eee) { + log.error(_("isisfish.error.during.simulation"),eee); + simulation.getInformation().setException(eee); + throw new SimulationException(_("isisfish.error.during.simulation"), eee); + } finally { + // + // Finaly close all TopiaContext used during simulation + // + + SimulationContext context = SimulationContext.get(); + TopiaContext tx; + + context.closeDB(); + context.closeDBResult(); + + try { + // close all transaction + if (context != null && context.getSimulationStorage() != null) { + context.getSimulationStorage().closeMemStorage(); + context.getSimulationStorage().closeStorage(); + } + } catch (TopiaException eee) { + if (log.isWarnEnabled()) { + log.warn("Can't close all transaction", eee); + } + } + + SimulationContext.remove(); + + // + // Affichage des statistiques + // + long end = System.nanoTime(); + log.info("Simulation time: " + DurationFormatUtils.formatDuration( + (end-start)/1000000, "s'.'S")); + SimulationParameter param = simulation.getParameter(); + if (param.getUseStatistic()) { + String trace = Trace.printStatistiqueAndClear(); + simulation.getInformation().setStatistic(trace); + } + if (param.getUseOptimization()) { + String cache = Cache.printStatistiqueAndClear(); + simulation.getInformation().setOptimizationUsage(cache); + } + + LutinTrace.printStatistiqueAndClear(); + + } + return result; + } + + protected void initSimulationListener(SimulationContext context) throws Exception { + SimulationStorage simulation = context.getSimulationStorage(); + // enregistrement des listeners de resultat + // - ResultStorage + context.addSimulationListener(simulation.getResultStorage()); + + // - TODO: mexico xml result + // - TODO: vle result + String simListener = context.getSimulationStorage().getParameter().getTagValue().get("SimulationListener"); + if (simListener != null) { + String [] simListeners = StringUtil.split(simListener, ","); + for (String l : simListeners) { + context.addSimulationListener((SimulationListener)ObjectUtil.create(l)); + } + } + + // enregistrement des listeners de simulation + // - prescript (before simulation) + // - export (after simulation) + context.addSimulationListener(new SimulationPreScript()); + // si le simulateur est de type SimulationStep il faut ajouter les regles + context.addSimulationListener(new SimulationExportResultWrapper()); + } + + protected class ObjectCreationListener implements TopiaTransactionListener { + + /** List qui contient tous les objets creer durant la simulation */ + protected List<TopiaEntity> newObjects = new ArrayList<TopiaEntity>(); + + /** + * @return Returns the newObjects. + */ + public List<TopiaEntity> getNewObjects() { + return this.newObjects; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.event.TopiaTransactionListener#commit(org.codelutin.topia.event.TopiaTransactionEvent) + */ + public void commit(TopiaTransactionEvent event) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.codelutin.topia.event.TopiaTransactionListener#rollback(org.codelutin.topia.event.TopiaTransactionEvent) + */ + public void rollback(TopiaTransactionEvent event) { + log.debug("Transaction rollback " + event.getEntities().size() + " object(s)"); + // FIXME le jour ou on aura l'isolation on pourra directement + // ajouter dans un autre TopiaContext les objets ajouté durant la + // simulation de cette maniere les objets creer au pas de temps + // N seront dispo pour etre utilisé au pas de temps N+1 + // Sinon une autre methode est de faire cette ajout + // dans l'event rollback qui est leve a la fin de chaque pas de temps + for (TopiaEntity entity : event.getEntities()) { + if (event.isCreate(entity)) { + log.debug("New object detected during simulation: " + entity + "(" + entity.getClass().getName() + ")"); + newObjects.add(entity); + } + } + } + } + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,179 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.simulator.launcher; + +import static org.codelutin.i18n.I18nf._; + +import fr.ifremer.isisfish.IsisConfig; +import fr.ifremer.isisfish.IsisFish; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.SimulationControl; +import java.io.File; +import java.rmi.RemoteException; +import java.util.Hashtable; +import java.util.Vector; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.xmlrpc.XmlRpcClient; +import org.codelutin.util.FileUtil; + +/** + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class IsisFishServerSimulationLauncher implements SimulatorLauncher { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(IsisFishServerSimulationLauncher.class); + + public SimulationStorage simulate(SimulationService simulationService, SimulationControl control, File simulationZip) throws RemoteException { + String simulationId = control.getId(); + SimulationStorage simulation = null; + try { + simulation = SimulationStorage.importAndRenameZip( + simulationZip, simulationId); + simulation = remoteSimulate(control, simulation); + } catch (Exception eee) { + log.error(_("Can't do simulation %s", simulationId), eee); + simulation.getInformation().setException(eee); + } + + // on retourne directement le simulation storage passe en argument + // car la simulation a ete faite avec + return simulation; + + } + + public int maxSimulationThread() { + // FIXME a rendre configurable + return 1; + } + + /** + * execute la simulation en remote + * + * @param control le controleur de simulation, peut-etre null si on ne + * souhaite pas controler la simulation + * @param simulation la simulation a faire + * + * @return le storage après simulation + * @throws Exception pour toute erreur + */ + public SimulationStorage remoteSimulate(SimulationControl control, + SimulationStorage simulation) throws Exception { + // export en zip du storage + File zip = simulation.createZip(); + + if (control != null) { + // creation du thread de surveillance de la simulation distante + // qui sert a mettre a jour les valeurs de control + new SimulationCheckpointRemoteThread(control).start(); + } + + // envoie le zip au serveur de simulation + // appel synchrone pour attendre la fin de la simulation + // recuperation du zip de la simulation terminé + Vector<Object> a = new Vector<Object>(); + //fixme : on peut avori control à null ? + a.add(control.getId()); + a.add(FileUtil.fileToByte(zip)); + + // lancement de la simulation + XmlRpcClient c = new XmlRpcClient(IsisFish.config.getSimulatorServer()); + c.setBasicAuthentication(IsisFish.config.getSimulatorUsername(), + IsisFish.config.getSimulatorPassword()); + byte[] callResult = (byte[])c.execute("simulate", a); + + // ecriture du resultat dans un fichier + File tmpzip = FileUtil.byteToFile(callResult); + + // remplacement du storage local par le storage recu + simulation.closeStorage(); + simulation.delete(false); + SimulationStorage result; + result = SimulationStorage.importAndRenameZip(tmpzip, control.getId()); + return result; + } + + /** + * This thread is responsable to synchronized SimulationControl used localy with + * remote simulation control for remote simulation. + * + * This thread dead when {@link SimulationControl#isRunning()} is false + * + * @author poussin + */ + protected class SimulationCheckpointRemoteThread extends Thread { // SimulationCheckpointRemoteThread + + protected SimulationControl control = null; + int badId = 0; + + public SimulationCheckpointRemoteThread(SimulationControl control) { + this.control = control; + } + + public void run() { + int sleepTime = 2000; + while (true) { + try { + Thread.sleep(sleepTime); + + updateControl(control); + // on remet de le temps normal, vu que la connexion a reussi + sleepTime = 2000; + + if (!control.isRunning()) { + return; + } + + } catch (Exception eee) { + // on supporte 10 erreurs puis ensuite on quitte le thread. + if (badId++ > 10) { + log.error("Error !!! ", eee); + break; + } else { + // on a echouer sur une tentative, on allonge un + // peu le temps + sleepTime += 2000; + } + } + } + + } + + public void updateControl(SimulationControl control) throws Exception { + // essai l'ancienne etait en dur: "http://localhost:9090" + IsisConfig config = IsisFish.config; + XmlRpcClient c = new XmlRpcClient(config.getSimulatorServer()); + c.setBasicAuthentication(config.getSimulatorUsername(), config.getSimulatorPassword()); + + Vector a = new Vector(); + a.add(control.getUpdateHashtable()); + Hashtable<String, Object> result = (Hashtable<String, Object>) c.execute("checkPoint", a); + // on remet de le temps normal, vu que la connexion a reussi + control.updateFromHashtable(result); + } + } // SimulationCheckpointRemoteThread + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package fr.ifremer.isisfish.simulator.launcher; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import static org.codelutin.i18n.I18nf._; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Un executor qui utilise un certain type de {@link SimulatorLauncher} pour + * executer les jobs soumis dans la queue de {@link SimulationService} + * <p> + * Les fonctionnalites en plus par rapport a un {@link ThreadPoolExecutor} sont: + * <li> la possibilite de suspendre l'executor puis ensuite de le relancer + * <li> l'utilisation de beforeExecute pour fixer le {@link SimulationLauncher} + * du job + * <p> + * Il est aussi possible d'ecoute l'etat de l'attribut pause + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class SimulationExecutor extends ThreadPoolExecutor { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(SimulationExecutor.class); + + protected PropertyChangeSupport propertyListeners = new PropertyChangeSupport(this); + /** vrai si cet executor est en pause */ + protected boolean pause = false; + /** le nombre de thread utilise avant la pause */ + protected int lastCorePoolSize; + /** le simulation service qui a cree cet executor */ + protected SimulationService simulationService; + /** le launcher a utilise pour les simulations */ + protected SimulatorLauncher launcher; + + public SimulationExecutor(SimulationService simulationService, SimulatorLauncher launcher, + BlockingQueue<Runnable> workQueue) { + super(launcher.maxSimulationThread(), launcher.maxSimulationThread(), + 0L, TimeUnit.MILLISECONDS, workQueue); + this.simulationService = simulationService; + this.launcher = launcher; + lastCorePoolSize = prestartAllCoreThreads(); + log.info(_("SimulationExecutor started with %s thread for %s", lastCorePoolSize, launcher)); + } + + public SimulationService getSimulationService() { + return simulationService; + } + + public SimulatorLauncher getLauncher() { + return launcher; + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertyListeners.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyListeners.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertyListeners.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyListeners.removePropertyChangeListener(propertyName, listener); + } + + /** + * Met les threads en attente si pause est vrai, et fixe le + * {@link SimulatorLauncher} a utiliser pour par la tache. + * Si la tache a deja un {@link SimulatorLauncher} d'assigne, on ne fait + * pas la tache + * + * @param t le thread qui va executer la tache + * @param r + */ + @Override + protected void beforeExecute(Thread t, Runnable r) { + super.beforeExecute(t, r); + + // en premier lieu il faut que SimulationService autorise le lancement + getSimulationService().waitAutoLaunch(); + + // ensuite si cet executor est en pause, on tu le thread apres avoir + // resoumis la simulation + if (isPause()) { + // on est en pause, il faut remettre la tache et tuer le thread + // un simple suspend du thread n'est pas bon, car la tache ne + // serait alors jamais executer et ce n'est pas forcement ce que + // l'on souhaite + if (r instanceof SimulationItem) { + SimulationService.getService().resubmit((SimulationJob)r); + } + throw new RuntimeException(_("Normal stop thread, this is not an error")); + } + if (r instanceof SimulationJob) { + SimulationJob job = (SimulationJob)r; + if (job.getLauncher() == null) { + // si la tache a deja un launcher, on l'utilise sinon on lui + // indique d'utilise le notre. C'est seul facon propre et sans + // risque de pouvoir choisir un launcher (en l'assignant au job + // avant d'arriver ici). Car l'autre solution serait de remettre + // la tache dans la queue et d'attendre que le bon executor + // la prenne, mais en fait cela impliquerait que dans le + // launcher on puisse refaire un test pour savoir si on doit + // reellement faire la tache ou non (trop compliquer pour + // l'implantation de launcher). et surtout on risquerait de + // boucler sans jamais executer la tache, s'il n'existe pas + // d'executor avec ce launcher ou qu'il est arrete. Dans ce + // dernier cas s'etait a l'utilisateur d'etre coherant, c-a-d + // de ne pas arreter un executor puis ensuite de demander + // explicitement a l'utiliser + job.setLauncher(launcher); + } + } else { + log.warn(_("Jobs submited is not ItemSimulation but was %s", r.getClass().getName())); + } + } + + public boolean isPause() { + return pause; + } + + /** + * demande au thread d'arreter de prendre de nouvelle tache + */ + public void pause() { + setPause(true); + } + + /** + * indique au thread de recommencer a prendre de nouvelle tache + */ + public void resume() { + setPause(false); + } + + /** + * Change la valeur de la variable pause, si pause est alors vrai + * notifie tous les threads en attente + * @param autoLaunch The autoLaunch to set. + */ + public void setPause(boolean pause) { + boolean oldValue = this.pause; + synchronized (this) { + this.pause = pause; + if (this.pause) { + lastCorePoolSize = getCorePoolSize(); + setCorePoolSize(0); + } else { + setCorePoolSize(lastCorePoolSize); + // on recree tous les threads qui avait ete tue par la pause + prestartAllCoreThreads(); + } + } + propertyListeners.firePropertyChange("pause", oldValue, this.pause); + } + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,83 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.simulator.launcher; + + +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import java.io.File; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Objet representant un simulation qui doit etre faite + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class SimulationItem { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(SimulationItem.class); + + /** le control pour la simulation */ + protected SimulationControl control; + protected SimulationParameter parameter; + /** le zip contenant la simulation prete a etre executee */ + protected File simulationZip; + + public SimulationItem(SimulationControl control, SimulationParameter param, + File simulationZip) { + this.control = control; + this.parameter = param; + this.simulationZip = simulationZip; + } + + public SimulationControl getControl() { + return control; + } + + /** + * Permet de mettre le zip apres construction de l'objet. Cela est util + * car la construction du zip prend du temps, et on souhaite pouvoir le + * monitorer et donc il faut que l'item exist pour etre vu dans la console + * de queue de simulation. + * <p> + * Normalement seul l'objet SimulationService doit pouvoir appeler cette + * method, elle est donc protected + * + * @param simulationZip + */ + protected void setSimulationZip(File simulationZip) { + this.simulationZip = simulationZip; + } + + public SimulationParameter getParameter() { + return parameter; + } + + public File getSimulationZip() { + return simulationZip; + } + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,254 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.simulator.launcher; + +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import fr.ifremer.isisfish.types.Date; +import java.io.File; +import static org.codelutin.i18n.I18nf._; + +import java.rmi.RemoteException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.util.FileUtil; + +/** + * Classe responsable de la simulation d'un {@link SimulationItem}. Pour cela + * il utilise le {@link SimulatorLauncher}. Si la simulation echoue + * a cause d'une RemoteException alors le job est resoumis dans la queue + * de simulation par l'appel de la methode + * {@link SimulationService#reportError}. + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class SimulationJob implements Runnable, Comparable<SimulationJob> { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(SimulationJob.class); + + /** l'ensemble des post actions a effectuer pour ce job */ + protected Set<PostAction> postActions = new HashSet<PostAction>(); + /** Le {@link SimulationService} dans lequel a ete cree ce job */ + protected SimulationService simulationService; + /** si non null contient le {@link SimulationJob} qui a genere ce job, ca + * veut dire que ce job est du a un plan d'analyse*/ + protected SimulationJob parentJob; + /** item contenant les infos de la simulation */ + protected SimulationItem item; + /** la priorite de cet item dans la queue */ + protected int priority; + /** Le launcher a utiliser pour simuler cet item */ + protected SimulatorLauncher launcher; + + public SimulationJob(SimulationService simulationService, SimulationItem item, int priority) { + this(simulationService, null, item, priority); + } + + public SimulationJob(SimulationService simulationService, SimulationJob parentJob, SimulationItem item, int priority) { + this.simulationService = simulationService; + this.parentJob = parentJob; + this.item = item; + this.priority = priority; + } + + public void addPostAction(PostAction postAction) { + this.postActions.add(postAction); + } + + public void removePostAction(PostAction postAction) { + this.postActions.remove(postAction); + } + + /** + * demande l'annulation/arret de ce job. Si ce job n'etait pas encore actif + * un {@link SimulationServiceListener#simulationStop} est leve. Sinon + * il le sera lorsque la simulation se sera convenablement arretee. + * <p> + * Dans tous les cas une demande d'arret sur le control de la simulation + * est fait. + */ + public void stop() { + // on essaie d'enlever ce job de la queue, au cas ou il ne serait pas + // encore lance + if (simulationService.cancel(this)) { + // on a pu annuler avec le lancement, on notify un stop puisqu'on + // ne passera jamais dans le run() + simulationService.fireStopEvent(this); + } + item.getControl().stopSimulation(); + } + + public SimulationJob getParentJob() { + return parentJob; + } + + public SimulationItem getItem() { + return item; + } + + public void setLauncher(SimulatorLauncher launcher) { + this.launcher = launcher; + } + + public SimulatorLauncher getLauncher() { + return launcher; + } + + public int getPriority() { + return priority; + } + + public int compareTo(SimulationJob o) { + return this.priority - o.priority; + } + + /** + * Fait la simulation. La simulation en elle meme est delegue au + * {@link SimulatorLauncher}. Le travail restant ici est le nettoyage, + * la gestion des erreurs ou l'iteration s'il sagit de plan d'analyse + * dependant. + */ + public void run() { + try { + SimulationControl control = item.getControl(); + SimulationParameter param = item.getParameter(); + String id = control.getId(); + log.debug("Start simulation: " + id); + simulationService.fireStartEvent(this); + + if (getParentJob() == null && param.getUseAnalysePlan() && !param.isIndependentPlan()) { + // on est sur un plan d'analyse dependant, il faut generer les + // simulation les unes apres les autres + Iterator<SimulationJob> i = + new SimulationService.PrepareSimulationJob(simulationService, this); + while (i.hasNext()) { + log.info(_("Generate next simulation")); + SimulationJob subjob = i.next(); + subjob.setLauncher(getLauncher()); + subjob.run(); + } + + // nettoyage si besoin apres toutes les simulations + if (param.getOnlyExport()) { + for (File file : FileUtil.find( + SimulationStorage.getSimulationDirectory(), + id + "_[0-9]+$", false)) { + log.debug("Delete simulation " + file); + FileUtil.deleteRecursively(file); + } + } + } else { + // on est sur une simple simulation, ou le resultat d'un plan + + // set date to 0 at beginning of simulation + control.setDate(new Date()); + control.setProgress(0); + control.setStarted(true); + + File zip = item.getSimulationZip(); + SimulationStorage simulation = launcher.simulate(simulationService, control, zip); + + try { + // copie les exports de simulation dans le repertoire + // souhaiter par l'utilisateur + if (param.getExportNames() != null && + param.getExportNames().size() > 0) { + File exportDir = SimulationStorage.getResultExportDirectory( + simulation.getDirectory()); + // FIXME verifier que pour les plans on a bien tous les + // export, c-a-d que les export son fait dans un sous rep + // portant le nom de la simu + FileUtil.copyAndRenameRecursively(exportDir, + new File(param.getExportDirectory()), + exportDir.getName(), id); + } + } catch (Exception eee) { + log.error(_("Can't export simulation %s", id), eee); + } + + try { + // Si l'utilisateur souhaite seulement les exports + // on supprimer la/les simulations. + if (param.getOnlyExport()) { + // pour les plan dependant il faut le faire apres toutes + // les simulations donc pas ici + if (getParentJob() == null || + param.getUseAnalysePlan() && param.isIndependentPlan()) { + simulation.delete(false); + } + } + } catch (Exception eee) { + log.error(_("Can't delete simulation %s ", id), eee); + } + + for (PostAction action : postActions) { + try { + action.finished(this, simulation); + } catch (Exception eee) { + log.error(_("Can't do post action %s", action), eee); + } + } + } + + } catch (Throwable eee) { + log.warn(_("Can't simulate %s", item.getControl().getId()), eee); + if (eee instanceof RemoteException) { + simulationService.reportError(getLauncher(), this); + } else { + // on ne le fait pas pour RemoteException, car la simulation + // va etre resoumise + for (PostAction action : postActions) { + action.exception(this, eee); + } + } + } finally { + simulationService.fireStopEvent(this); + } + } + + /** + * Interface permettant d'implanter des actions a faire apres la simulation, + * Ces action ne se declenche pas pour les job de plan d'analyse pere + */ + public static interface PostAction { + /** + * appeler lorsque la simulation s'arrete normalement + * @param job le job qui a fait la simulation + * @param sim la simulation qui vient d'etre faite + */ + public void finished(SimulationJob job, SimulationStorage sim); + /** + * appeler lorsque la simulation a echouee + * @param job le job qui a fait la simulation + * @param eee l'exception qui a ete levee + */ + public void exception(SimulationJob job, Throwable eee); + } + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,688 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.simulator.launcher; + +import static org.codelutin.i18n.I18nf._; + +import fr.ifremer.isisfish.IsisFish; +import fr.ifremer.isisfish.IsisFishRuntimeException; +import fr.ifremer.isisfish.datastore.AnalysePlanStorage; +import fr.ifremer.isisfish.datastore.ExportStorage; +import fr.ifremer.isisfish.datastore.RegionStorage; +import fr.ifremer.isisfish.datastore.RuleStorage; +import fr.ifremer.isisfish.datastore.ScriptStorage; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.datastore.SimulatorStorage; +import fr.ifremer.isisfish.rule.Rule; +import fr.ifremer.isisfish.simulator.AnalysePlan; +import fr.ifremer.isisfish.simulator.AnalysePlanContext; +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationException; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import fr.ifremer.isisfish.util.CompileHelper; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.PriorityBlockingQueue; +import org.apache.commons.lang.mutable.MutableInt; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.TopiaContext; +import org.codelutin.topia.TopiaException; +import org.codelutin.util.FileUtil; +import org.codelutin.util.ListenerSet; +import org.codelutin.util.ObjectUtil; +import org.codelutin.util.ZipUtil; + +/** + * Cette classe est responsable de conservation de toutes les simulations faites + * ou a faire. Pour ajouter une nouvelle simulation on appelle la methode + * {@link #submit}. + * <p> + * Cette classe sert aussi de modele pour le moniteur de queue + * <p> + * Il existe une instance unique pour toute l'application + * <p> + * Lors de l'instanciation de la classe, l'ensemble des + * {@link SimulationLauncher} disponible est recherche dans la configuration + * et un executor est cree pour chaque. + * <p> + * Si un {@link SimulationLauncher} genere trop d'erreur (RemoteException) + * Il est alors suspendu pour ne plus etre utilise pour les simulations. + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class SimulationService { + + static final public String SIMULATION_LAUNCHER = "simulation.launcher"; + /** nombre maximal de simulation autoriser pour un plan */ + // FIXME a rendre configurable MAX_PLAN_SIMULATION + static final public int MAX_PLAN_SIMULATION = 20000; + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(SimulationService.class); + + static protected SimulationService instance = new SimulationService(); + + /** + * Retourne l'instance du SimulationService a utiliser + * @return + */ + static public SimulationService getService() { + return instance; + } + + protected PropertyChangeSupport propertyListeners = new PropertyChangeSupport(this); + protected ListenerSet<SimulationServiceListener> listeners = new ListenerSet<SimulationServiceListener>(); + + // FIXME pouvoir configurer ceci en fichier de config + // FIXME ainsi que la mise a false, lors de la simulation de la derniere + // (sans doute ajoute un boolean, simulationListAsQueue = true|false) + protected boolean autoLaunch = true; + + /** L'executor utilise pour creer toutes les sous simulations des plans independants */ + protected ExecutorService subSimulationComputationExecutor = Executors.newSingleThreadExecutor(); + /** Tous les types de {@link SimulatorLauncher} disponibles, et leur executors associe */ + protected Map<SimulatorLauncher, SimulationExecutor> executors; + /** Le nombre d'erreur pour les SimulatorLauncher */ + protected Map<SimulatorLauncher, MutableInt> launcherError; + /** La queue contenant toutes les simulations a faire */ + protected PriorityBlockingQueue<Runnable> queue = new PriorityBlockingQueue<Runnable>(); + + /** Contient les identifiants des simulations presentes dans {@ link #jobs}*/ + protected Set<String> idJobs = new HashSet<String>(); + /** La liste des jobs existant (queue + job demarre) */ + protected Set<SimulationJob> jobs = new TreeSet<SimulationJob>(); + + /** La liste des jobs termines */ + protected Set<SimulationJob> jobDones = new TreeSet<SimulationJob>(); + + /** + * Cree une instance et initialise les executors ainsi que le launcherError + */ + protected SimulationService() { + // on cree un executor par type SimulatorLauncher + executors = new LinkedHashMap<SimulatorLauncher, SimulationExecutor>(); + launcherError = new HashMap<SimulatorLauncher, MutableInt>(); + Properties prop = IsisFish.config.getOptionStartsWith(SIMULATION_LAUNCHER); + for (String key : prop.stringPropertyNames()) { + String value = prop.getProperty(key); + try { + SimulatorLauncher sl = (SimulatorLauncher) ObjectUtil.newInstance(value); + SimulationExecutor se = new SimulationExecutor(this, sl, queue); + executors.put(sl, se); + launcherError.put(sl, new MutableInt(0)); + } catch (Exception eee) { + log.warn(_("Can't instantiate %s", value), eee); + } + } + } + + public Collection<SimulationExecutor> getSimulationExecutors() { + return executors.values(); + } + + public Set<SimulationJob> getJobs() { + return jobs; + } + + public Set<SimulationJob> getJobDones() { + return jobDones; + } + + /** + * Retourne la liste de tous les {@link SimulatorLauncher} disponible + * @return + */ + protected Set<SimulatorLauncher> getSimulatorLaunchers() { + return executors.keySet(); + } + + public void addSimulationServiceListener(SimulationServiceListener l) { + listeners.add(l); + } + + public void removeSimulationServiceListener(SimulationServiceListener l) { + listeners.remove(l); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertyListeners.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyListeners.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertyListeners.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + propertyListeners.removePropertyChangeListener(propertyName, listener); + } + + /** + * Ajoute le job au job en cours previent s'il n'etait pas deja present + * les listener {@link SimulationServiceListener#simulationStart}. + * @param job + */ + protected void fireStartEvent(SimulationJob job) { + // on ajoute au cas on il n'y serait pas + if (jobs.add(job)) { + idJobs.add(job.getItem().getControl().getId()); + for (SimulationServiceListener l : listeners) { + l.simulationStart(job); + } + } + } + + /** + * Supprime le job de la liste des jobs en cours et l'ajoute le job si + * besoin a la liste des jobs faits (s'il y a une erreur ou qu'il ne sagit + * pas d'une simulation lancer par un plan d'analyse). + * Les listener sont prevenu par la methode + * {@link SimulationServiceListener#simulationStop}. + * @param job + */ + protected void fireStopEvent(SimulationJob job) { + jobs.remove(job); + idJobs.remove(job.getItem().getControl().getId()); + + // on ajout au jobDones que les simulations avec erreur ou les + // simulation reellement demande par l'utilisateur (pas de simulation + // de plan + jobDones.add(job); + for (SimulationServiceListener l : listeners) { + l.simulationStop(job); + } + } + + /** + * Nettoie la liste des jobs faits + */ + public void clearJobDone() { + jobDones.clear(); + // FIXME prevoir quelque chose pour prevenir la console de queue + } + + /** + * @return Returns the autoLaunch. + */ + public boolean isAutoLaunch() { + return this.autoLaunch; + } + + /** + * @param autoLaunch The autoLaunch to set. + */ + public void setAutoLaunch(boolean autoLaunch) { + synchronized (this) { + boolean oldValue = this.autoLaunch; + this.autoLaunch = autoLaunch; + if (this.autoLaunch) { + this.notifyAll(); + } + propertyListeners.firePropertyChange("autoLaunch", oldValue, autoLaunch); + } + } + + /** + * Permet de mettre en attente les threads de simulation si l'utilisateur + * a suspendu la queue + */ + protected void waitAutoLaunch() { + synchronized(this) { + while (!isAutoLaunch()) { + try { + log.info("autoLaunch is false waiting queue start"); + this.wait(); + } catch (InterruptedException eee) { + log.warn("Error during wait autoLaunch flag", eee); + } + } + } + } + + /** + * Permet d'ajouter une nouvelle simulation a la queue. Si la simulation est + * simple ou avec un plan d'experience dependant, un nouveau job est cree + * et directement ajout a la queue de jobs. S'il la simulation est un plan + * ou les simulations sont independantes, toutes les simulations sont + * genere et toute ajoute a la queue de simulation. Mais dans ce cas seul + * la simulation de depart est ajoute au jobs en cours, les simulations + * generees seront ajoutees lors de leur reel execution + * + * @param id l'identifiant de la simulation + * @param param les parametres de la simulation + * @param priority la priorite de la simulation + */ + public void submit(String id, SimulationParameter param, int priority) { + // on l'ajoute tout de suite a la liste des simulations demandee + SimulationControl control = new SimulationControl(id); + SimulationItem item = new SimulationItem(control, param, null); + SimulationJob job = new SimulationJob(this, item, priority); + fireStartEvent(job); + + // on construit le zip de la simulation + File zip = prepareSimulationZipFile(control, param, true); + item.setSimulationZip(zip); + + if (param.getUseAnalysePlan() && param.isIndependentPlan()) { + // c un plan d'analyse independant, on construit toute les sous simu + Runnable task = new PrepareSimulationJob(this, job); + subSimulationComputationExecutor.execute(task); + } else { + // l'item est fini d'etre initialise, on peut l'ajouter a la queue + // sauf si c'etait un plan independant ou se seront les sous simu + // qui seront dans la queue + queue.add(job); + } + + } + + /** + * Permet de resoumettre un job qui a ete pris par un thread mais qu'il + * ne peut pas traiter. Cela arrive lorsque l'executor est en pause, ou + * que le launcher de l'executor ne fonctionne plus (il se met en pause + * tout seul) + * + * @param item l'item a resoumettre + */ + protected void resubmit(SimulationJob job) { + queue.add(job); + } + + /** + * Permet de soumettre a la queue un job provenant d'un plan. + * Ce plan ne doit pas apparaitre dans la console de queue. + * + * @param job + */ + protected void submitSubJob(SimulationJob job) { + queue.add(job); + } + + /** + * Supprime un job de la queue (annulation d'une simulation). Appele + * depuis {@link SimulationJob#stop} + * + * @param job le job a annuler + * @return vrai si la simulation a pu etre annulee avant sont lancement + * (encore presente dans la queue), faux si la simulation a deja ete + * prise par un thread de simulation ou quelle est terminee + */ + protected boolean cancel(SimulationJob job) { + boolean result = queue.remove(job); + return result; + } + + public boolean exists(String id) { + boolean result = idJobs.contains(id); + return result; + } + + /** + * Report une erreur pour un launcher, on resoumet le job en supprimant + * le launcher utilise + * + * @param launcher le launcher posant probleme + * @param job le job qui n'a pas reussi a se faire + */ + protected void reportError(SimulatorLauncher launcher, SimulationJob job) { + MutableInt i = launcherError.get(launcher); + i.setValue(i.intValue() + 1); + // si on a plus de N error, on stop l'executor associe + if (i.intValue() >= 5) { + log.error(_("Launcher %s will be stopped because there are too many error (%s)", + launcher, i.intValue())); + SimulationExecutor e = executors.get(launcher); + e.pause(); + } + // il faut bien penser a supprimer le launcher pour qu'un autre executor + // puisse y mettre le sien + job.setLauncher(null); + resubmit(job); + } + + /** + * Permet de genere les sous simulations d'un plan d'analyse. Pour les + * plan independant, on l'utilise en Runnable pour genere tous les plans + * possible et les soumettre a la queue. Pour les plans dependant + * on l'utilise seulement comme iterator. La methode afterSimulation des plans + * est appelee automatiquement a la fin de la simulation grace au mecanisme + * de PostAction sur les {@link SimulationJob}. + */ + public static class PrepareSimulationJob implements Runnable, Iterator<SimulationJob>, SimulationJob.PostAction { + + protected SimulationService simulationService; + protected AnalysePlanContext planContext; + protected SimulationJob job; + protected SimulationJob nextJob; + protected boolean doNext = true; + protected String id; + protected SimulationControl control; + protected SimulationParameter param; + protected int planNumber = 0; + + public PrepareSimulationJob(SimulationService simulationService, + SimulationJob job) { + this.simulationService = simulationService; + this.job = job; + id = job.getItem().getControl().getId(); + control = job.getItem().getControl(); + param = job.getItem().getParameter(); + this.planContext = new AnalysePlanContext(control.getId(), param); + } + + /** + * genere toutes les sous simulations et les places dans la queue + */ + public void run() { + while (hasNext()) { + try { + SimulationJob subJob = next(); + simulationService.submitSubJob(subJob); + } catch (Exception eee) { + log.error(_("Can't add simulation: ", job.getItem().getControl().getId()), eee); + } + } + + } + + /** + * Indique s'il y a encore des simulations dans le plan. Par defaut pour + * Eviter les plans sans fin, le nombre de plan genere par simulation + * est limite a {@link MAX_PLAN_SIMULATION} + * + * @return + */ + public boolean hasNext() { + try { + // if user request stop simulation, stop all futur planned simulation + // and if last doNext is false not do next simulation + boolean result = !control.isStopSimulationRequest() && doNext; + if (result) { + // si deja creer on ne le refet pas + if (nextJob == null) { + // Prepration de la simulation a faire + // create next id simulation + planNumber++; + if (planNumber > MAX_PLAN_SIMULATION) { + log.error(_("Analyse plan error, too many simulation for %s : %s", id, planNumber)); + doNext = false; + result = false; + } else { + String simId = id + "_" + planNumber; + param.setAnalysePlanNumber(planNumber); + + File tmpDirectory = FileUtil.createTempDirectory( + "isisfish-simultation-", "-preparation"); + SimulationStorage sim = SimulationStorage.importAndRenameZip( + tmpDirectory, job.getItem().getSimulationZip(), simId); + sim.getParameter().setAnalysePlanNumber(planNumber); + + // appel de tous les plans pour modifier la simulation + for (AnalysePlan plan : param.getAnalysePlans()) { + result = result && plan.beforeSimulation(planContext, sim); + if (!result) { + nextJob = null; + break; + } + } + doNext = result; + if (result) { + File zip = sim.createZip(); + SimulationItem item = new SimulationItem(control, param, zip); + nextJob = new SimulationJob(simulationService, job, item, job.getPriority()); + nextJob.addPostAction(this); // pour l'appel des after des plans + } + // quoi qu'il arrive on supprime le repertoire temporaire + if (!FileUtil.deleteRecursively(tmpDirectory)) { + log.warn(_("isisfish.error.remove.directory", tmpDirectory)); + } + } + } + } + return result; + } catch (Exception eee) { + throw new IsisFishRuntimeException(_("isisfish.error.evalute.plan.script"), eee); + } + + } + + public SimulationJob next() { + hasNext(); // pour etre sur qu'il a ete appele au moins une fois + SimulationJob result = nextJob; + nextJob = null; + return result; + + } + + public void remove() { + throw new UnsupportedOperationException("Not supported."); + } + + public void finished(SimulationJob job, SimulationStorage sim) { + doNext = true; + boolean result = true; + + // appel de tous les plans pour modifier la simulation + for (AnalysePlan plan : sim.getParameter().getAnalysePlans()) { + try { + result = plan.afterSimulation(planContext, sim); + doNext = doNext && result; + } catch (Exception eee) { + log.error(_("Stop simulation plan, because can't call afterSimulation correctly on plan %s", + plan.getClass().getName()), eee); + doNext = false; + } + } + + } + + public void exception(SimulationJob job, Throwable eee) { + // il y a une simulation d'echoue, on ne fait pas les suivantes + // cela n'impacte pas les plan independant puisque toutes les + // simulation on deja ete generee + doNext = false; + } + } + + static public void message(SimulationControl control, String message) { + log.info(message); + if (control != null) { + control.setText(message); + } + } + + /** + * Prepare les fichiers qui seront utils à la simulation: + * <li> scripts + * <li> rules + * <li> exports + * <li> simulators + * <li> export de la database de la region + * <p> + * Le tout est zippé et le zip est retourné, il peut-être directement + * importé dans le SimulationStorage (en le renomant comme il faut + * importAndRenameZip). + * <p> + * Ce zip est automatiquement supprimé a la fin de l'application. + * + * @param control le controleur + * @param param les parametre de la simulation + * @param compile si vrai la version compile des fichiers Java est aussi + * mise dans le fichier zip. Cela peut servir pour les simulations locales + * pour ne pas recompiler pour chaque simulation avec plan d'analyse + * @return un zip de simulation pour une simulation pret a être faite + * @throws SimulationException pour tout problème rencontré (IO,Topia...) + */ + protected File prepareSimulationZipFile(SimulationControl control, + SimulationParameter param, boolean compile) throws SimulationException { + try { + File tmpDirectory = FileUtil.createTempDirectory("isisfish-simultation-", "-preparation"); + //File regionXML = IsisConfig.getDataBackupFile(tmpDirectory); + File regionXML = new File(tmpDirectory, SimulationStorage.DATA_BACKUP_FILENAME); + + // sauvegarde des parametres + Properties prop = param.toProperties(); + //File f = IsisConfig.getSimulationParametersFile(tmpDirectory); + File f = new File(tmpDirectory, SimulationStorage.PARAMETERS_FILENAME); + FileOutputStream out = new FileOutputStream(f); + //FileOutputStream out = new FileOutputStream(new File(tmpDirectory, IsisConfig.SIMULATION_PARAMETERS)); + prop.store(out, "Parameters"); + out.close(); + + // backup pour toutes les simulations, pour eviter que l'utilisateur + // ne puisse le modifier en meme temps + message(control, _("isisfish.message.backup.database.progress")); + RegionStorage region = RegionStorage.getRegion(param.getRegionName()); + TopiaContext tc = region.getStorage().beginTransaction(); + tc.backup(regionXML, true); + tc.closeContext(); + message(control, _("isisfish.message.backup.database.finished")); + + // copie de toutes regles a utiliser + List<Rule> rules = param.getRules(); + for (Rule rule : rules) { + String name = RuleStorage.getName(rule); + FileUtil.copy(new File(RuleStorage.getRuleDirectory(), name + ".java"), + new File(tmpDirectory, RuleStorage.RULE_PATH + File.separator + name + ".java")); + } + // copie des regles reclamées par les plans d'analyse + for(String name : param.getExtraRules()) { + FileUtil.copy(new File(RuleStorage.getRuleDirectory(), name + ".java"), + new File(tmpDirectory, RuleStorage.RULE_PATH + File.separator + name + ".java")); + } + + // copie de toutes regles a utiliser + List<AnalysePlan> plans = param.getAnalysePlans(); + for (AnalysePlan plan : plans) { + String name = AnalysePlanStorage.getName(plan); + FileUtil.copy(new File(AnalysePlanStorage.getAnalysePlanDirectory(), name + ".java"), + new File(tmpDirectory, AnalysePlanStorage.ANALYSE_PLAN_PATH + File.separator + name + ".java")); + } + + // copie de tous les exports a utiliser + for (String name : param.getExportNames()) { + name = name.endsWith(".java")?name:name + ".java"; + FileUtil.copy(new File(ExportStorage.getExportDirectory(), name), + new File(tmpDirectory, ExportStorage.EXPORT_PATH + File.separator + name)); + } + + // copie de tous les scripts a utiliser + FileUtil.copyRecursively(ScriptStorage.getScriptDirectory(), tmpDirectory, ".*\\.java$"); + + // copie de tous les simulateurs a utiliser + FileUtil.copy(new File(SimulatorStorage.getSimulatorDirectory(), param.getSimulatorName()), + new File(tmpDirectory, SimulatorStorage.SIMULATOR_PATH + File.separator + param.getSimulatorName())); + + if (compile) { + compileAllFile(control, tmpDirectory); + } + + // creation du zip + File result = new File(tmpDirectory.getPath() + ".zip"); + result.deleteOnExit(); + ZipUtil.compress(result, tmpDirectory, null); + + // poussin 20071015: remove temp directory + if (!FileUtil.deleteRecursively(tmpDirectory)) { + log.warn(_("isisfish.error.remove.directory", tmpDirectory)); + } + + return result; + } catch (IOException eee) { + throw new SimulationException(_("isisfish.error.prepare.information.simulation"), eee); + } catch (TopiaException eee) { + throw new SimulationException(_("isisfish.error.prepare.information.simulation"), eee); + } + + } + + /** + * Compile les fichiers présent dans le répertoire passé en + * parametre, ce répertoire est hiérarchisé en: rules, exports, simulators + * et scripts. Seul les fichiers des 3 premiers répertoire sont compilé + * les fichiers du dernier sont compilé par les dépendances qu'on les autres + * <p> + * Il permet donc de compiler facilement tous les fichiers pour une + * simulation + * + * @param control le controleur + * @param directory le répertoire où compiler + */ + protected void compileAllFile(SimulationControl control, File directory) { + + message(control, "Scripts and rules Compilation"); + long currentTime = System.nanoTime(); + + // + // Recherche des fichiers a compiler + // On ne prend pas les scripts, car ils sont tous copiés mais pas + // forcément util. Lors de la compilation des autres fichiers, les + // script servant réellement seront automatiquement compilé + + List<File> fileToCompile = new ArrayList<File>(); + + List<File> tmp = FileUtil.find(new File(directory, ExportStorage.EXPORT_PATH), ".*\\.java$", true); + fileToCompile.addAll(tmp); + + tmp = FileUtil.find(new File(directory, RuleStorage.RULE_PATH), ".*\\.java$", true); + fileToCompile.addAll(tmp); + + tmp = FileUtil.find(new File(directory, AnalysePlanStorage.ANALYSE_PLAN_PATH), ".*\\.java$", true); + fileToCompile.addAll(tmp); + + tmp = FileUtil.find(new File(directory, SimulatorStorage.SIMULATOR_PATH), ".*\\.java$", true); + fileToCompile.addAll(tmp); + + // + // Compilation + // + + CompileHelper.compile(directory, fileToCompile, directory, null); + long time = System.nanoTime() - currentTime; + message(control, _("isisfish.message.compilation.time", DurationFormatUtils.formatDuration(time / 1000000, "s'.'S"))); + + } + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package fr.ifremer.isisfish.simulator.launcher; + +/** + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public interface SimulationServiceListener { + + /** + * Notifie start of simulation + * @param job job that responsable to simulation + */ + public void simulationStart(SimulationJob job); + + /** + * Notifie end of simulation + * @param job job that responsable to simulation + */ + public void simulationStop(SimulationJob job); + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,134 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.simulator.launcher; + +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import java.util.ArrayList; +import java.util.Map; +import static org.codelutin.i18n.I18nf._; + +import java.util.Set; +import java.util.WeakHashMap; +import javax.swing.JProgressBar; +import javax.swing.table.AbstractTableModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class SimulationServiceTableModel extends AbstractTableModel { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(SimulationServiceTableModel.class); + + protected final static String[] columnHeader = new String[]{ + _("isisfish.queue.id"), + _("isisfish.queue.plan"), + _("isisfish.queue.launcher"), + _("isisfish.queue.status"), + _("isisfish.queue.progression"), + }; + protected SimulationService simulationService; + protected ArrayList<SimulationJob> jobs; + /** progress bar (one for each row) */ + protected Map<SimulationJob, JProgressBar> progress = + new WeakHashMap<SimulationJob, JProgressBar>(); + + public SimulationServiceTableModel(SimulationService simulationService, Set<SimulationJob> jobs) { + this.simulationService = simulationService; + this.jobs = new ArrayList<SimulationJob>(jobs); + } + + protected JProgressBar getProgressBar(SimulationJob job) { + JProgressBar result = progress.get(job); + if (result == null) { + result = new JProgressBar(JProgressBar.HORIZONTAL, 0, 100); + result.setStringPainted(true); + progress.put(job, result); + } + return result; + } + + public SimulationJob getJob(int row) { + SimulationJob result = jobs.get(row); + return result; + } + + public int getRowCount() { + int result = jobs.size(); + return result; + } + + public int getColumnCount() { + int result = columnHeader.length; + return result; + } + + public Object getValueAt(int rowIndex, int columnIndex) { + SimulationJob job = jobs.get(rowIndex); + SimulationControl control = job.getItem().getControl(); + String id = control.getId(); + SimulationParameter param = job.getItem().getParameter(); + + Object result = ""; + + switch (columnIndex) { + case 0: + result = id; + break; + case 1: + if (param.getUseAnalysePlan()) { + int number = param.getAnalysePlanNumber(); + result = number; + } + break; + case 2: + result = job.getLauncher().toString(); + break; + case 3: + if (control != null) { + if (control.isStopSimulationRequest()) { + result = _("isisfish.launch.stop"); + } else { + result = control.getText(); + } + } + break; + case 4: + JProgressBar pb = getProgressBar(job); + if (control != null) { + pb.setMaximum(control.getProgressMax()); + pb.setValue(control.getProgress()); + pb.setString(control.getDate().getMonth() + "/" + control.getDate().getYear()); + } + result = pb; + break; + } + return result; + } + +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +package fr.ifremer.isisfish.simulator.launcher; + +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.SimulationControl; +import java.io.File; +import java.rmi.RemoteException; + +/** + * Interface devant etre implanter par les classes souhaitants etre utilisees + * comme plugin de simulation (CapArmor, SubProcess, ...) + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public interface SimulatorLauncher { + + /** + * Execute une simulation et retourne le storage ou est stocker la + * simulation + * + * @param simulationService le {@link SimulationService} qui a initie + * la simulation + * @param control le control de la simulation + * @param simulationZip le zip contenant la simulation prete a etre executee + * @return le storage contenant la simulation qui vient d'etre faite + * ou null en fait au lieu de faire une seul simulation, plusieurs ou ete + * faite par exemple tout un plan d'analyse. Cette classe est tout de meme + * responsable du stockage de chaque simulation dans des storages. + * <b>IMPORTANT</b> Quoi qu'il arrive + * + * @throws java.rmi.RemoteException Si pour l'execution de la simulation + * on utilise des resources distantes (serveurs) et que ceux si non pas pu + * etre contacte. Dans ce cas la simulation n'a pas ete faite et cette + * exception est levee. + */ + public SimulationStorage simulate(SimulationService simulationService, + SimulationControl control, File simulationZip) + throws RemoteException; + + /** + * Retourne le nombre maximal de thread de simulation simultane supporte + * @return un nombre superieur a 0 + */ + public int maxSimulationThread(); +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,158 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.simulator.launcher; + +import static org.codelutin.i18n.I18nf._; + +import fr.ifremer.isisfish.IsisFish; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.SimulationControl; +import java.io.File; +import java.io.InputStream; +import java.rmi.RemoteException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class SubProcessSimulationLauncher implements SimulatorLauncher { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(SubProcessSimulationLauncher.class); + + public SimulationStorage simulate(SimulationService simulationService, SimulationControl control, File simulationZip) throws RemoteException { + String simulationId = control.getId(); + SimulationStorage simulation = null; + try { + simulation = SimulationStorage.importAndRenameZip( + simulationZip, simulationId); + simulation = subProcessSimulate(control, simulation); + } catch (Exception eee) { + log.error(_("Can't do simulation %s", simulationId), eee); + simulation.getInformation().setException(eee); + } + + // on retourne directement le simulation storage passe en argument + // car la simulation a ete faite avec + return simulation; + + } + + public int maxSimulationThread() { + int result = Runtime.getRuntime().availableProcessors(); + return result; + } + + public SimulationStorage subProcessSimulate(SimulationControl control, + SimulationStorage simulation) throws Exception { + + String simulationId = control.getId(); + // on ferme le SimulationStorage pour ne pas interferer avec le process + simulation.closeStorage(); + + String java = System.getProperty("java.home") + + File.separator + "bin" + File.separator + "java"; + String classpath = System.getProperty("java.class.path"); + + // prepare le process + ProcessBuilder processBuilder = new ProcessBuilder( + java, "-classpath", classpath, + IsisFish.class.getName(), + "--simulate", simulationId); + processBuilder.redirectErrorStream(true); + + // demarrage du process + Process process = processBuilder.start(); + + if (control != null) { + // prepare de thread de surveillance du process si control n'est pas null + Thread monitor = new SimulationCheckpointExternalProcessThread( + control, simulation, process); + monitor.start(); + } + + // on attend que la simulation soit fini + process.waitFor(); + return simulation; + } + + /** + * This thread is responsable to synchronized SimulationControl used localy with + * remote simulation control for remote simulation. + * + * This thread dead when {@link SimulationControl#isRunning()} is false + * + * @author poussin + */ + protected class SimulationCheckpointExternalProcessThread extends Thread { // SimulationCheckpointThread + + /** + * Logger for this class + */ + protected SimulationControl control = null; + protected SimulationStorage simulation = null; + protected Process process = null; + // on l'appel plutot out que in, car c le output du process lance + protected InputStream out = null; + + public SimulationCheckpointExternalProcessThread(SimulationControl control, + SimulationStorage simulation, Process process) { + this.control = control; + this.simulation = simulation; + this.process = process; + out = process.getInputStream(); + + } + + @Override + public void run() { + int sleepTime = 2000; + int error = 0; + while (true) { + try { + out.skip(out.available()); + Thread.sleep(sleepTime); + // on ne lit pas le stop, car le stop ne peut-etre appeler + // que par l'utilisateur qui est de ce cote de la machine + simulation.readControl(control, "stop"); + + if (control.isStopSimulationRequest()) { + // FIXME, un destroy du process est peut-etre un peu violent ? + process.destroy(); + // passe artificiellement le control a fini + control.stopSimulation(); + } + if (!control.isRunning()) { + return; + } + } catch (Exception eee) { + log.debug("Can't update control for " + control.getId(), eee); + } + } + + } + } +} Added: trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/Queue.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/Queue.java (rev 0) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/Queue.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -0,0 +1,133 @@ +/* + * Queue.java + * + * Created on 22 août 2008, 23:01 + */ + +package fr.ifremer.isisfish.ui.simulator; + +import fr.ifremer.isisfish.simulator.launcher.SimulationService; +import fr.ifremer.isisfish.simulator.launcher.SimulationServiceTableModel; + +/** + * + * @author poussin + */ +public class Queue extends javax.swing.JPanel { + + /** Creates new form Queue */ + public Queue() { + initComponents(); + SimulationService ss = SimulationService.getService(); + modelJobs = new SimulationServiceTableModel(ss, ss.getJobs()); + modelJobDones = new SimulationServiceTableModel(ss, ss.getJobDones()); + tableJobs.setModel(modelJobs); + tableJobDones.setModel(modelJobDones); + } + + + private void initComponents() { + bindingGroup = new org.jdesktop.beansbinding.BindingGroup(); + + tableJobsScroll = new javax.swing.JScrollPane(); + tableJobs = new javax.swing.JTable(); + tableJobDonesScroll = new javax.swing.JScrollPane(); + tableJobDones = new javax.swing.JTable(); + autoLaunchButton = new javax.swing.JToggleButton(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + + tableJobsScroll.setViewportView(tableJobs); + + tableJobDonesScroll.setViewportView(tableJobDones); + + autoLaunchButton.setText("Auto Launch"); + + org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, jButton1, org.jdesktop.beansbinding.ELProperty.create("${action.enabled}"), autoLaunchButton, org.jdesktop.beansbinding.BeanProperty.create("selected")); + bindingGroup.addBinding(binding); + + jButton1.setText("Stop simulation"); + + binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, tableJobs, org.jdesktop.beansbinding.ELProperty.create("${selectedElement}"), jButton1, org.jdesktop.beansbinding.BeanProperty.create("enabled")); + binding.setSourceNullValue(false); + binding.setSourceUnreadableValue(false); + bindingGroup.addBinding(binding); + + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + stopSimulation(evt); + } + }); + + jButton2.setText("View log"); + + binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, tableJobDones, org.jdesktop.beansbinding.ELProperty.create("${selectedElement}"), jButton2, org.jdesktop.beansbinding.BeanProperty.create("enabled")); + binding.setSourceNullValue(false); + binding.setSourceUnreadableValue(false); + bindingGroup.addBinding(binding); + + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + viewLog(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(12, 12, 12) + .addComponent(autoLaunchButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jButton2)) + .addComponent(tableJobDonesScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE) + .addComponent(tableJobsScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(tableJobsScroll, javax.swing.GroupLayout.PREFERRED_SIZE, 139, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tableJobDonesScroll, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 7, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(autoLaunchButton) + .addComponent(jButton1) + .addComponent(jButton2)) + .addContainerGap()) + ); + + bindingGroup.bind(); + } + + private void stopSimulation(java.awt.event.ActionEvent evt) { + int i = tableJobs.getSelectedRow(); + if (i >= 0) { + modelJobs.getJob(i).stop(); + } + } + + private void viewLog(java.awt.event.ActionEvent evt) { + // TODO add your handling code here: + } + + protected SimulationServiceTableModel modelJobs; + protected SimulationServiceTableModel modelJobDones; + protected javax.swing.JToggleButton autoLaunchButton; + protected javax.swing.JButton jButton1; + protected javax.swing.JButton jButton2; + protected javax.swing.JTable tableJobDones; + protected javax.swing.JScrollPane tableJobDonesScroll; + protected javax.swing.JTable tableJobs; + protected javax.swing.JScrollPane tableJobsScroll; + private org.jdesktop.beansbinding.BindingGroup bindingGroup; + +} Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorAction.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorAction.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorAction.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -41,10 +41,10 @@ import static fr.ifremer.isisfish.datastore.SimulationStorage.getSimulation; import static fr.ifremer.isisfish.datastore.SimulationStorage.getSimulationNames; import fr.ifremer.isisfish.logging.SimulationLoggerUtil; -import fr.ifremer.isisfish.simulator.SimulationHelper; -import fr.ifremer.isisfish.simulator.SimulationManager; +import fr.ifremer.isisfish.simulator.SimulationException; import fr.ifremer.isisfish.simulator.SimulationParameter; import fr.ifremer.isisfish.simulator.SimulationProperties; +import fr.ifremer.isisfish.simulator.launcher.SimulationService; import fr.ifremer.isisfish.ui.simulator.filter.SimulationFilterUtil; import fr.ifremer.isisfish.ui.widget.filter.FilterModel; import org.apache.commons.logging.Log; @@ -58,6 +58,7 @@ import javax.swing.*; import javax.swing.table.TableModel; import java.lang.reflect.Field; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -68,6 +69,7 @@ */ public class SimulatorAction { + static private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm"); /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(SimulatorAction.class); @@ -96,9 +98,7 @@ uiContext.setData("RuleNames", RuleStorage.getRuleNames()); // put default value in param - param.setlocal(true); param.setSimulatorName(IsisFish.config.getSimulatorClassfile()); - param.setlocal(IsisFish.config.isSimulatorLocal()); param.setTagValue(IsisFish.config.getDefaultTagValueAsMap()); param.setExportDirectory(IsisFish.config.getDefaultExportDirectory().toString()); param.setExportNames(IsisFish.config.getDefaultExportNamesAsList()); @@ -261,7 +261,17 @@ try { uiContext.setData("SimulationLaunched", false); - SimulationHelper.simulate(simulId, param, inQueue); + simulId += " " + dateFormat.format(new java.util.Date()); + + if (simulId == null || "".equals(simulId) || + SimulationStorage.localyExists(simulId) || + SimulationService.getService().exists(simulId)) { + log.error("Can't start simulation, bad id: " + simulId); + throw new SimulationException(_("isisfish.error.start")); + } + SimulationParameter p = param.copy(); + + SimulationService.getService().submit(simulId, p, 0); selectTab(tabs, true, 6); //TODO Voir si cela fonctionne Modified: trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorListeners.java =================================================================== --- trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorListeners.java 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/java/fr/ifremer/isisfish/ui/simulator/SimulatorListeners.java 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,6 +1,6 @@ package fr.ifremer.isisfish.ui.simulator; -import fr.ifremer.isisfish.simulator.SimulationManager; +import fr.ifremer.isisfish.simulator.launcher.SimulationService; import fr.ifremer.isisfish.ui.widget.EnabledIfListNotEmpty; import fr.ifremer.isisfish.ui.widget.EnabledIfItemSelectedInList; @@ -48,7 +48,7 @@ final JButton start, final JButton remove, final JButton showLog, final JTable table, final JTable tableDone) { - SimulationManager.getInstance().addPropertyChangeListener("autoLaunch", + SimulationService.getService().addPropertyChangeListener("autoLaunch", new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { start.setEnabled(isSimulStartButtonEnabled(table)); @@ -114,7 +114,7 @@ * <code>false</code> otherwise */ public static boolean isSimulStartButtonEnabled(JTable table) { - return !SimulationManager.getInstance().isAutoLaunch() && + return !SimulationService.getService().isAutoLaunch() && (table.getRowCount() > 0); } Modified: trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/context.xml =================================================================== --- trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/context.xml 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/context.xml 2008-08-22 22:46:00 UTC (rev 1310) @@ -66,6 +66,7 @@ <map> <!-- Les composants ajoutés pour isis --> <!-- panel --> + <entry key="Queue"><value>fr.ifremer.isisfish.ui.simulator.Queue</value></entry> <entry key="MatrixPanel"><value>org.codelutin.math.matrix.gui.MatrixPanelEditor</value></entry> <entry key="OpenMapToolPanel"><value>fr.ifremer.isisfish.map.OpenMapToolPanel</value></entry> <entry key="SeasonIntervalPanel"><value>fr.ifremer.isisfish.ui.widget.IntervalPanel</value></entry> Modified: trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Params.xml =================================================================== --- trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Params.xml 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Params.xml 2008-08-22 22:46:00 UTC (rev 1310) @@ -144,9 +144,9 @@ <button constraints="buttonSimulParamsSimulate" id="buttonSimulParamsSimulate" text="isisfish.common.simulate" actionCommand="simulator.SimulatorAction.simulate($fieldSimulParamsName/text, $SimulationParameter, 'false', $simulTabs)"/> - +<!-- La queue n'existe plus <button constraints="buttonSimulParamsAddQueue" id="buttonSimulParamsAddQueue" text="isisfish.common.addQueue" actionCommand="simulator.SimulatorAction.simulate($fieldSimulParamsName/text, $SimulationParameter, 'true', $simulTabs)"/> - + --> </panel> Modified: trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Queue.xml =================================================================== --- trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Queue.xml 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/Queue.xml 2008-08-22 22:46:00 UTC (rev 1310) @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="ISO-8859-15"?> +<Queue/> +<!-- <panel id="simulQueue" name="isisfish.queue.title" constraints="simulQueue" layout="XMLGridLayout(fr/ifremer/isisfish/ui/simulator/Queue.xgl)"> <scrollPane constraints="queueTable"> @@ -18,13 +20,11 @@ </scrollPane> <button constraints="buttonSimulQueueStart" id="buttonSimulQueueStart" text="isisfish.queue.simulationLaunch" - actionCommand="xpath:setAutoLaunch(fr.ifremer.isisfish.simulator.SimulationManager.getInstance(), 'true')"/> - <!--TODO ne fonctionne pas init="simulator.SimulatorAction.initButtonSimulQueueStart($buttonSimulQueueStart)"--> + actionCommand="xpath:setAutoLaunch(fr.ifremer.isisfish.simulator.SimulationService.getService(), 'true')"/> <button constraints="buttonSimulQueueRemove" id="buttonSimulQueueRemove" text="isisfish.queue.stopSimulation" - actionCommand="xpath:setStopSimulationRequest(getSimulationControl($queueModel, $queueTable/selectedRow), 'true')"/> + actionCommand="xpath:stop(getJob($queueModel, $queueTable/selectedRow), 'true')"/> <button constraints="buttonSimulQueueShowLog" id="buttonSimulQueueShowLog" text="isisfish.queue.showLog" actionCommand="fr.ifremer.isisfish.ui.simulator.SimulatorAction.showLog($queueTableDone,$queueModelDone,$queueTableDone/selectedRow)"/> - <!--TODO ne fonctionne pas init="simulator.SimulatorAction.initButtonSimulQueue($buttonSimulQueueShowLog,$queueTableDone)"--> - <!--TODO ne fonctionne pas non plusorigin="$queueTableDone/selectedRow!=-1"--> </panel> +--> \ No newline at end of file Modified: trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/SimulQueue.xml =================================================================== --- trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/SimulQueue.xml 2008-08-21 16:23:06 UTC (rev 1309) +++ trunk/isis-fish/src/uimodel/fr/ifremer/isisfish/ui/simulator/SimulQueue.xml 2008-08-22 22:46:00 UTC (rev 1310) @@ -4,7 +4,9 @@ layout="BorderLayout" Maximizable="true" Closable="true" bundle="org.codelutin.i18n.I18nBundleBridge"> + <Queue/> +<!-- <xpanel xml="simulator/Queue.xml"/> - +--> </Frame>
participants (1)
-
bpoussin@users.labs.libre-entreprise.org