Author: chatellier Date: 2009-02-17 11:43:37 +0000 (Tue, 17 Feb 2009) New Revision: 1819 Added: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationMonitor.java Modified: isis-fish/trunk/changelog.txt isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/SimulationAction.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/SimulatorServer.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/JDKPriorityBlockingQueue.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationQueue.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties Log: Change simulation monitoring Modified: isis-fish/trunk/changelog.txt =================================================================== --- isis-fish/trunk/changelog.txt 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/changelog.txt 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,6 @@ isis-fish (3.2.0.x) xxx + * Change simulation monitoring to work better with SSH launcher * Update XML-RPC launcher to xmlprc 3 * Add ssh simulation launcher * Add Jaxx UI for all interfaces Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/SimulationAction.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/SimulationAction.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/actions/SimulationAction.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -37,7 +37,6 @@ import fr.ifremer.isisfish.simulator.launcher.InProcessSimulatorLauncher; import fr.ifremer.isisfish.simulator.launcher.SimulationService; import fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher; -import fr.ifremer.isisfish.types.Month; /** * Action des simulations. @@ -112,9 +111,11 @@ // lancement de la simulation SimulatorLauncher launcher = new InProcessSimulatorLauncher(); - SimulationStorage simulation = launcher.simulate(null, control, - simulationZip); - + + //SimulationStorage simulation = launcher.simulate(null, control, simulationZip); + //simulation.getStorage().closeContext(); + launcher.simulate(null, control, simulationZip); + SimulationStorage simulation = launcher.getSimulationStorage(SimulationService.getService(), control); simulation.getStorage().closeContext(); // FIXME integrer ca dans le process normal d'init Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/SimulatorServer.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/SimulatorServer.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/SimulatorServer.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -173,7 +173,9 @@ simulationControls.put(id, control); try { SimulatorLauncher launcher = new InProcessSimulatorLauncher(); - simulation = launcher.simulate(null, control, zip); + launcher.simulate(null, control, zip); + // FIXME null + simulation = launcher.getSimulationStorage(null, control); zip = simulation.createZip(); byte[] result = FileUtil.fileToByte(zip); Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/InProcessSimulatorLauncher.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -75,22 +75,25 @@ public class InProcessSimulatorLauncher implements SimulatorLauncher { /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(InProcessSimulatorLauncher.class); - + private static Log log = LogFactory + .getLog(InProcessSimulatorLauncher.class); + + protected SimulationStorage simulation; + /* * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#simulate(fr.ifremer.isisfish.simulator.launcher.SimulationService, fr.ifremer.isisfish.simulator.SimulationControl, java.io.File) */ - public SimulationStorage simulate(SimulationService simulationService, + public void simulate(SimulationService simulationService, SimulationControl control, File simulationZip) - throws RemoteException{ - + throws RemoteException { + String id = control.getId(); log.info(_("simulate %s with file %s", id, simulationZip)); - SimulationStorage simulation = null; - + try { - simulation = SimulationStorage.importAndRenameZip(simulationZip, id); - + simulation = SimulationStorage + .importAndRenameZip(simulationZip, id); + // add missing control informations SimulationParameter param = simulation.getParameter(); control.setDate(new Date()); @@ -99,17 +102,31 @@ int lastYear = param.getNumberOfYear(); int lastDate = lastYear * Month.NUMBER_OF_MONTH; control.setProgressMax(lastDate); - + simulation = localSimulate(control, simulation); } catch (Exception eee) { log.error(_("Can't do simulation %s", id), eee); - if(simulation != null) { + if (simulation != null) { simulation.getInformation().setException(eee); } } + } + + @Override + public SimulationStorage getSimulationStorage( + SimulationService simulationService, SimulationControl control) + throws RemoteException { + return simulation; + } + @Override + public void updateControl(SimulationService simulationService, + SimulationControl control) throws RemoteException { + // in this case, control is set directly by main thread + } + /* * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#maxSimulationThread() */ @@ -117,11 +134,23 @@ return 1; } + /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#getCheckProgressionInterval() + */ @Override + public int getCheckProgressionInterval() { + + // par defaut, pour les in process 5 secondes + + int interval = 1; + return interval; + } + + @Override public String toString() { return _("isisfish.simulator.launcher.inprocess"); } - + /** * Display message both in commons-logging and control text progress. * @@ -130,7 +159,7 @@ */ protected void message(SimulationControl control, String message) { // log - if(log.isInfoEnabled()) { + if (log.isInfoEnabled()) { log.info(message); } // control @@ -149,7 +178,8 @@ * @param simulation la simulation a faire * @return le storage après simulation en locale */ - protected SimulationStorage localSimulate(SimulationControl control, SimulationStorage simulation) { + 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 @@ -157,7 +187,8 @@ String scriptLogLevel = simulation.getParameter().getScriptLogLevel(); String libLogLevel = simulation.getParameter().getLibLogLevel(); try { - simulation.addSimulationLogger(simulLogLevel,scriptLogLevel,libLogLevel,simThread.getName()); + simulation.addSimulationLogger(simulLogLevel, scriptLogLevel, + libLogLevel, simThread.getName()); } catch (Exception e) { if (log.isWarnEnabled()) { log.warn(_("isisfish.error.add.logger.simulation ", e)); @@ -174,26 +205,27 @@ } } finally { // remove simulation logger (no more need since thread is dead) - simulation.removeSimulationLogger(); + 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():"")); + 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> @@ -206,23 +238,24 @@ */ protected AspectClassLoader changeClassLoader(Thread thread, File directory) { try { - URL [] classpath = new URL[]{directory.toURI().toURL(), + 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() - }; + // 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, IsisFish.class.getClassLoader()); //new URLClassLoader(classpath); + AspectClassLoader loader = new AspectClassLoader(classpath, + IsisFish.class.getClassLoader()); //new URLClassLoader(classpath); //AspectClassLoader loader = new AspectClassLoader(classpath, ClassLoader.getSystemClassLoader()); //new URLClassLoader(classpath); thread.setContextClassLoader(loader); - log.info("Classloader used for simulation: " + loader + " " + - Arrays.toString(loader.getURLs())); + 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); + throw new IsisFishRuntimeException(_( + "isisfish.error.change.classloader", directory), eee); } } @@ -236,7 +269,8 @@ * @param simulation la simulation a faire * @return le storage après simulation en locale */ - protected SimulationStorage localSimulateSameThread(SimulationControl control, SimulationStorage simulation) { + 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()) @@ -247,12 +281,13 @@ AspectClassLoader classLoader; try { File rootDirectory = simulation.getDirectory(); - + // // changement de classloader // - classLoader = changeClassLoader(Thread.currentThread(), rootDirectory); - + classLoader = changeClassLoader(Thread.currentThread(), + rootDirectory); + // // Creation et initialisation du context de simulation // @@ -260,8 +295,9 @@ context.setClassLoader(classLoader); context.setScriptDirectory(rootDirectory); context.setSimulationStorage(simulation); - context.setSimulationControl(control!=null?control:new SimulationControl(simulation.getName())); - + 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 @@ -274,19 +310,20 @@ // org.hibernate.HibernateException: Found shared references to a collection // to not have same loaded entity into different context ! Field[] fields = rule.getClass().getFields(); - for(Field field : fields) { - if(Modifier.isPublic(field.getModifiers())) { - log.debug("change field is " + field.getName() + "(set topiaId = null)"); + for (Field field : fields) { + if (Modifier.isPublic(field.getModifiers())) { + log.debug("change field is " + field.getName() + + "(set topiaId = null)"); Object fieldValue = field.get(rule); - if(fieldValue instanceof TopiaEntity) { - TopiaEntity valueEntity = (TopiaEntity)fieldValue; + if (fieldValue instanceof TopiaEntity) { + TopiaEntity valueEntity = (TopiaEntity) fieldValue; valueEntity.setTopiaId(null); field.set(rule, valueEntity); } } } } - + // // Activation de l'OAP demandée // @@ -298,13 +335,13 @@ 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(); - + Simulator simulatorObject = simulator.getNewSimulatorInstance(); + // on se met listener sur tc pour connaitre tous les nouveaux objets ObjectCreationListener objectCreationListener = new ObjectCreationListener(); context.getDB().addTopiaTransactionListener(objectCreationListener); @@ -313,7 +350,7 @@ // Ajout des listeners pour la simulation // initSimulationListener(context); - + // // Lancement du script de simulation selectionné // @@ -323,8 +360,8 @@ // Call listener simulation (used per example for prescript) // context.fireBeforeSimulation(); - simulatorObject.simulate(context); - + simulatorObject.simulate(context); + // // Ajout des nouveaux objets créés durant la simulation // @@ -334,7 +371,8 @@ // 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() + ")"); + log.debug("Add new object: " + e + "(" + e.getClass().getName() + + ")"); add.add(e); } add.commitTransaction(); @@ -344,28 +382,34 @@ // context.fireAfterSimulation(); - message(control, _("isisfish.message.simulation.ended")); - + message(control, _("isisfish.message.simulation.ended")); + simulation.getInformation().setSimulationEnd(new java.util.Date()); - + + // la simulation est termine on avance la progress au dernier cran + // attention on utilise ca aussi pour detecer la fin d'une simulation + // quand date =progressMax + control.setProgress(control.getProgress() + 1); + } catch (OutOfMemoryError eee) { - log.error(_("isisfish.error.during.simulation"),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); + log.error(_("isisfish.error.during.simulation"), eee); simulation.getInformation().setException(eee); - throw new SimulationException(_("isisfish.error.during.simulation"), eee); + throw new SimulationException( + _("isisfish.error.during.simulation"), eee); } finally { // // Finaly close all TopiaContext used during simulation // - + SimulationContext context = SimulationContext.get(); - + context.closeDB(); context.closeDBResult(); - + try { // close all transaction if (context.getSimulationStorage() != null) { @@ -379,13 +423,14 @@ } SimulationContext.remove(); - + // // Affichage des statistiques // long end = System.nanoTime(); - log.info("Simulation time: " + DurationFormatUtils.formatDuration( - (end-start)/1000000, "s'.'S")); + log.info("Simulation time: " + + DurationFormatUtils.formatDuration( + (end - start) / 1000000, "s'.'S")); SimulationParameter param = simulation.getParameter(); if (param.getUseStatistic()) { String trace = Trace.printStatistiqueAndClear(); @@ -395,12 +440,13 @@ String cache = Cache.printStatistiqueAndClear(); simulation.getInformation().setOptimizationUsage(cache); } - + } return result; } - protected void initSimulationListener(SimulationContext context) throws Exception { + protected void initSimulationListener(SimulationContext context) + throws Exception { SimulationStorage simulation = context.getSimulationStorage(); // enregistrement des listeners de resultat // - ResultStorage @@ -408,34 +454,36 @@ // - TODO: mexico xml result // - TODO: vle result - String simListener = context.getSimulationStorage().getParameter().getTagValue().get("SimulationListener"); + String simListener = context.getSimulationStorage().getParameter() + .getTagValue().get("SimulationListener"); if (simListener != null) { - String [] simListeners = StringUtil.split(simListener, ","); + String[] simListeners = StringUtil.split(simListener, ","); for (String l : simListeners) { - context.addSimulationListener((SimulationListener)ObjectUtil.create(l)); + 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()); + 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) */ @@ -448,7 +496,8 @@ * @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)"); + 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 @@ -457,7 +506,8 @@ // 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() + ")"); + log.debug("New object detected during simulation: " + + entity + "(" + entity.getClass().getName() + ")"); newObjects.add(entity); } } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/IsisFishServerSimulationLauncher.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -52,7 +52,7 @@ private static Log log = LogFactory .getLog(IsisFishServerSimulationLauncher.class); - public SimulationStorage simulate(SimulationService simulationService, + public void simulate(SimulationService simulationService, SimulationControl control, File simulationZip) throws RemoteException { String simulationId = control.getId(); @@ -64,14 +64,14 @@ } catch (Exception eee) { log.error(_("Can't do simulation %s", simulationId), eee); // FIXME simulation allways null here - if(simulation != null) { + if (simulation != null) { simulation.getInformation().setException(eee); } } // on retourne directement le simulation storage passe en argument // car la simulation a ete faite avec - return simulation; + //return simulation; } @@ -80,6 +80,18 @@ return 1; } + /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#getCheckProgressionInterval() + */ + @Override + public int getCheckProgressionInterval() { + + // par defaut, pour les serveur xmlrpc 20 secondes + + int interval = 20; + return interval; + } + /** * execute la simulation en remote * @@ -113,15 +125,16 @@ //XmlRpcClient c = new XmlRpcClient(IsisFish.config.getSimulatorServer()); //c.setBasicAuthentication(IsisFish.config.getSimulatorUsername(), // IsisFish.config.getSimulatorPassword()); - + XmlRpcClientConfigImpl xmlrpcconfig = new XmlRpcClientConfigImpl(); - xmlrpcconfig.setServerURL(new URL(IsisFish.config.getSimulatorServer())); + xmlrpcconfig + .setServerURL(new URL(IsisFish.config.getSimulatorServer())); xmlrpcconfig.setBasicUserName(IsisFish.config.getSimulatorUsername()); xmlrpcconfig.setBasicPassword(IsisFish.config.getSimulatorPassword()); XmlRpcClient client = new XmlRpcClient(); client.setTransportFactory(new XmlRpcCommonsTransportFactory(client)); client.setConfig(xmlrpcconfig); - + byte[] callResult = (byte[]) client.execute("simulate", a); // ecriture du resultat dans un fichier @@ -183,13 +196,18 @@ public void updateControl(SimulationControl control) throws Exception { // essai l'ancienne etait en dur: "http://localhost:9090" - + XmlRpcClientConfigImpl xmlrpcconfig = new XmlRpcClientConfigImpl(); - xmlrpcconfig.setServerURL(new URL(IsisFish.config.getSimulatorServer())); - xmlrpcconfig.setBasicUserName(IsisFish.config.getSimulatorUsername()); - xmlrpcconfig.setBasicPassword(IsisFish.config.getSimulatorPassword()); + xmlrpcconfig.setServerURL(new URL(IsisFish.config + .getSimulatorServer())); + xmlrpcconfig.setBasicUserName(IsisFish.config + .getSimulatorUsername()); + xmlrpcconfig.setBasicPassword(IsisFish.config + .getSimulatorPassword()); XmlRpcClient client = new XmlRpcClient(); - client.setTransportFactory(new XmlRpcCommonsTransportFactory(client)); + client + .setTransportFactory(new XmlRpcCommonsTransportFactory( + client)); client.setConfig(xmlrpcconfig); Vector a = new Vector(); @@ -201,9 +219,29 @@ } } // SimulationCheckpointRemoteThread - @Override public String toString() { return _("Remote IsisFish server"); } + + /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#getSimulationStorage(fr.ifremer.isisfish.simulator.launcher.SimulationService, fr.ifremer.isisfish.simulator.SimulationControl) + */ + @Override + public SimulationStorage getSimulationStorage( + SimulationService simulationService, SimulationControl control) + throws RemoteException { + // TODO Auto-generated method stub + return null; + } + + /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#updateControl(fr.ifremer.isisfish.simulator.launcher.SimulationService, fr.ifremer.isisfish.simulator.SimulationControl) + */ + @Override + public void updateControl(SimulationService simulationService, + SimulationControl control) throws RemoteException { + // TODO Auto-generated method stub + + } } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/JDKPriorityBlockingQueue.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/JDKPriorityBlockingQueue.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/JDKPriorityBlockingQueue.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -19,7 +19,6 @@ package fr.ifremer.isisfish.simulator.launcher; - import java.util.AbstractQueue; import java.util.Collection; import java.util.Comparator; @@ -34,7 +33,6 @@ import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; - /////////////////////////////////////////////////////////////////////////// // // not modified code from PriorityBlockingQueue @@ -47,7 +45,8 @@ * @author poussin * @param <E> element in queue */ -public class JDKPriorityBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { +public class JDKPriorityBlockingQueue<E> extends AbstractQueue<E> implements + BlockingQueue<E>, java.io.Serializable { private static final long serialVersionUID = 5595510919245408276L; protected final PriorityQueue<E> q; @@ -492,8 +491,8 @@ private class Itr implements Iterator<E> { final Object[] array; // Array of all elements - int cursor; // index of next element to return; - int lastRet; // index of last element, or -1 if no such + int cursor; // index of next element to return; + int lastRet; // index of last element, or -1 if no such Itr(Object[] array) { lastRet = -1; @@ -532,7 +531,7 @@ lock.unlock(); } } - } + } /** * Saves the state to a stream (that is, serializes it). This @@ -551,4 +550,3 @@ } } } - Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SSHSimulatorLauncher.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -81,7 +81,7 @@ * at each connection. */ protected static Session sshSession; - + /** * Constructor. * @@ -132,14 +132,27 @@ */ @Override public int maxSimulationThread() { - + // FIXME pour toutes les envoyer // met le serveur les lance quand il veut - + return 1; } /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#getCheckProgressionInterval() + */ + @Override + public int getCheckProgressionInterval() { + + // par defaut, pour ssh, on utilise 20 secondes + + int interval = (int) IsisFish.config + .getSimulatorSshControlCheckInterval(); + return interval; + } + + /* * @see java.lang.Object#toString() */ @Override @@ -160,55 +173,61 @@ * - lance le thread de control de la simulation */ @Override - public SimulationStorage simulate(SimulationService simulationService, + public void simulate(SimulationService simulationService, SimulationControl control, File simulationZip) throws RemoteException { - SimulationStorage simulationStorage = null; - // start ssh session try { - // connection message(control, _("isisfish.simulation.remote.message.connection")); Session sshSession = getSSHSession(); //openSSHSession(); // upload simulation on server message(control, _("isisfish.simulation.remote.message.upload")); - String simulationRemotePath = uploadSimulation(sshSession, simulationZip); + String simulationRemotePath = uploadSimulation(sshSession, + simulationZip); // build du contenu du script - message(control, _("isisfish.simulation.remote.message.waitingstart")); - File simulationScript = getSimulationScriptFile(control.getId(), simulationRemotePath); - String scriptRemotePath = uploadSimulationScript(sshSession, simulationScript); + message(control, + _("isisfish.simulation.remote.message.waitingstart")); + File simulationScript = getSimulationScriptFile(control.getId(), + simulationRemotePath); + String scriptRemotePath = uploadSimulationScript(sshSession, + simulationScript); addScriptToQsubQueue(sshSession, scriptRemotePath); - // just start a thread - Thread thread = checkSimulationProgression(sshSession, simulationService, - control); - try { - thread.join(); - } catch (InterruptedException e) { - if (log.isErrorEnabled()) { - log.error(_("Control thread interrupted"), e); - } + } catch (Exception e) { + if (log.isErrorEnabled()) { + log.error(_("isisfish.error.simulation.remote.global")); } - + throw new RemoteException( + _("isisfish.error.simulation.remote.global"), e); + } + } + + /** + * {@inheritDoc} + * + * Se connecte au serveur distance et tétécharge les résultats de la simulation. + */ + @Override + public SimulationStorage getSimulationStorage( + SimulationService simulationService, SimulationControl control) + throws RemoteException { + + SimulationStorage simulationStorage = null; + + try { // recuperation des resultats message(control, _("isisfish.simulation.remote.message.downloadresults")); + downloadResults(sshSession, control.getId()); - simulationStorage = SimulationStorage.getSimulation(control.getId()); - - // force thread to stop - synchronized (control) { - control.stopSimulation(); - } - } catch (Exception e) { - if (log.isErrorEnabled()) { - log.error(_("isisfish.error.simulation.remote.global")); - } + simulationStorage = SimulationStorage + .getSimulation(control.getId()); + } catch (SSHException e) { throw new RemoteException( _("isisfish.error.simulation.remote.global"), e); } @@ -217,6 +236,50 @@ } /** + * {@inheritDoc} + * + * Se connecte au serveur distance et tétécharge le + * fichier de control. + * Injecte ensuite ce fichier dans le {@link SimulationControl}. + */ + @Override + public void updateControl(SimulationService simulationService, + SimulationControl control) throws RemoteException { + + try { + // download control file + File controlFile = downloadControlFile(control.getId()); + + if (log.isDebugEnabled()) { + log.debug("Control have been downloaded : " + + controlFile.getAbsolutePath()); + } + + synchronized (control) { + // le thread principal a pu le modifier pendant le sleep + //if (control.isRunning()) { + // 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 + SimulationStorage.readControl(controlFile, control, "stop"); + //} + } + + // deleteTempFile + controlFile.delete(); + } catch (SSHException e) { + // file doesn't exist + if (log.isDebugEnabled()) { + // not add ,e plz :) + log.debug(_("Remote control file doesn't exists %s", e + .getMessage())); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** * Get opened ssh session or try to open a new one. * * This method must synchronized. @@ -225,11 +288,11 @@ * @throws JSchException */ protected synchronized Session getSSHSession() throws JSchException { - - if(sshSession == null || !sshSession.isConnected()) { + + if (sshSession == null || !sshSession.isConnected()) { sshSession = openSSHSession(); } - + return sshSession; } @@ -364,25 +427,28 @@ * @return remote file path or <tt>null</tt> if errors * @throws SSHException if upload fail */ - protected String uploadSimulation(Session session, File simulationFile) throws SSHException { + protected String uploadSimulation(Session session, File simulationFile) + throws SSHException { String localPath = simulationFile.getAbsolutePath(); // first check that remote directory exists String remotePath = IsisFish.config.getSimulatorSshTmpPath(); - String command = "if [ ! -d \"" + remotePath +"\" ] ; then mkdir \"" + remotePath + "\"; fi"; - if(log.isInfoEnabled()) { - log.info("Creating remote temp directory (if not exists) " + remotePath); - if(log.isDebugEnabled()) { + String command = "if [ ! -d \"" + remotePath + "\" ] ; then mkdir \"" + + remotePath + "\"; fi"; + if (log.isInfoEnabled()) { + log.info("Creating remote temp directory (if not exists) " + + remotePath); + if (log.isDebugEnabled()) { log.debug("Executing command : " + command); } } int exit = SSHUtils.exec(session, command); - - if(exit != 0) { + + if (exit != 0) { throw new SSHException(_("Command '%s' fail to execute", command)); } - + // upload directory in that dir if (localPath.lastIndexOf("/") > 0) { @@ -405,7 +471,8 @@ * * @throws SSHException if download fail (can happen if remote file doesn't exist */ - protected void downloadResults(Session session, String simulationId) throws SSHException { + protected void downloadResults(Session session, String simulationId) + throws SSHException { // simulation directory File localFile = new File(IsisFish.config.getDatabaseDirectory(), @@ -423,10 +490,43 @@ remoteFile += "/" + simulationId; SSHUtils.scpFrom(session, remoteFile, localFile); - + } - + /** + * Download remote simulation control file and store + * its content into temp file. + * + * @return downloaded temp file (file have to be manually deleted) + * @throws IOException + * @throws SSHException if remote file doesn't exists + */ + protected File downloadControlFile(String simulationId) throws IOException, + SSHException { + + File localFile = null; + + // build remote file path + // FIXME this path should be given by remote IsisFish app + // TODO to change + String remoteFile = IsisFish.config.getSimulatorSshDataPath(); + remoteFile += "/" + SimulationStorage.SIMULATION_PATH; + remoteFile += "/" + simulationId; + remoteFile += "/control"; + + // local tmp file + localFile = File.createTempFile(simulationId, "control"); + + try { + SSHUtils.scpFrom(getSSHSession(), remoteFile, localFile); + } catch (JSchException e) { + throw new SSHException("Can't connect", e); + } + + return localFile; + } + + /** * Upload script on remote server. * * @param session valid opened ssh session @@ -434,8 +534,9 @@ * * @throws SSHException if upload fail */ - protected String uploadSimulationScript(Session session, File simulationScript) throws SSHException { - + protected String uploadSimulationScript(Session session, + File simulationScript) throws SSHException { + String localPath = simulationScript.getAbsolutePath(); String remotePath = IsisFish.config.getSimulatorSshTmpPath(); @@ -468,17 +569,24 @@ * * @throws IOException if can't build script */ - protected File getSimulationScriptFile(String simuationId, String simulationZip) throws IOException { - + protected File getSimulationScriptFile(String simuationId, + String simulationZip) throws IOException { + File tempScript = File.createTempFile("launch-isis", ".seq"); tempScript.deleteOnExit(); // auto delete + + // uncomment this to test on a cron server + //String scriptName = "ssh/launch-isis-cron.seq"; + // uncomment this to test on a qsub server + String scriptName = "ssh/launch-isis-qsub.seq"; - String fileContent = getSimulationScriptLaunchContent("ssh/launch-isis-qsub.seq", simuationId, simulationZip); + String fileContent = getSimulationScriptLaunchContent( + scriptName, simuationId, simulationZip); FileUtil.writeString(tempScript, fileContent); - + return tempScript; } - + /** * Utilise freemarker pour recuperer le contenu * du script. @@ -506,18 +614,18 @@ root.put("isishome", IsisFish.config.getSimulatorSshIsisHome()); root.put("simulationid", simuationId); root.put("simulationzip", simulationZip); - + // process template Writer out = new StringWriter(); template.process(root, out); out.flush(); scriptContent = out.toString(); - + } catch (TemplateException e) { if (log.isErrorEnabled()) { log.error(_("Process template error"), e); } - + throw new IOException(_("Process template error"), e); } @@ -532,156 +640,110 @@ * * @throws SSHException if call fail */ - protected void addScriptToQsubQueue(Session session, String scriptRemotePath) throws SSHException { + protected void addScriptToQsubQueue(Session session, String scriptRemotePath) + throws SSHException { // command to : // - add script in qsub queue - String command = IsisFish.config.getSimulatorSshAddToQueueCommand() + " \"" + scriptRemotePath + "\""; + String command = IsisFish.config.getSimulatorSshAddToQueueCommand() + + " \"" + scriptRemotePath + "\""; int exit = SSHUtils.exec(session, command); - - if(exit != 0) { + + if (exit != 0) { throw new SSHException(_("Command '%s' fail to execute", command)); } } - - /** - * Launch a thread to check simulation progression on remote - * server. - * - * Use IsisFish.config.SIMULATOR_SSH_DATAPATH to download - * remote simulation control file. - * - * @param sshSession - * @param simulationService - * @param control - */ - protected Thread checkSimulationProgression(Session sshSession, - SimulationService simulationService, SimulationControl control) { - Runnable controlRunnable = new RemoteSSHControlThread(sshSession, - control); - Thread controlThread = new Thread(controlRunnable); - controlThread.start(); - - return controlThread; - } - - /** - * Thread that check remote control file every 2s. - */ - protected class RemoteSSHControlThread implements Runnable { - - /** Opened ssh session */ - protected Session sshSession; - - /** Control (to update progression) */ - protected SimulationControl control; - - /** - * Constructor. - * @param sshSession - * - * @param control control - */ - protected RemoteSSHControlThread(Session sshSession, - SimulationControl control) { - this.sshSession = sshSession; - this.control = control; - } - - /* - * @see java.lang.Runnable#run() - */ - @Override - public void run() { - - long sleepTime = IsisFish.config.getSimulatorSshControlCheckInterval() * 1000; - - boolean running = true; - while (running) { - - // wait - try { - Thread.sleep(sleepTime); - - // log (to check if thread is still alive) - if (log.isDebugEnabled()) { - log.debug("Control thread wake up"); - } - - try { - // download control file - File controlFile = downloadControlFile(control.getId()); - - if (log.isDebugEnabled()) { - log.debug("Control have been downloaded : " - + controlFile.getAbsolutePath()); - } - - synchronized (control) { - // le thread principal a pu le modifier pendant le sleep - //if (control.isRunning()) { - // 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 - SimulationStorage.readControl(controlFile, - control, "stop"); - //} - } - - // deleteTempFile - controlFile.delete(); - } catch (SSHException e) { - // file doesn't exist - if(log.isDebugEnabled()) { - // not add ,e plz :) - log.debug(_("Remote control file doesn't exists %s", e.getMessage())); - } - } - - } catch (InterruptedException e) { - if (log.isErrorEnabled()) { - log.error("Thread has been interrupted", e); - } - } catch (IOException e) { - if (log.isErrorEnabled()) { - log.error("Error while reading control file", e); - } - } - - synchronized (control) { - running = control.getProgressMax() == 0 || (control.getProgress() < control.getProgressMax() - 1); - } - } - } - - /** - * Download remote simulation control file and store - * its content into temp file. - * - * @return downloaded temp file (file have to be manually deleted) - * @throws IOException - * @throws SSHException if remote file doesn't exists - */ - protected File downloadControlFile(String simulationId) - throws IOException, SSHException { - - File localFile = null; - - // build remote file path - // FIXME this path should be given by remote IsisFish app - // TODO to change - String remoteFile = IsisFish.config.getSimulatorSshDataPath(); - remoteFile += "/" + SimulationStorage.SIMULATION_PATH; - remoteFile += "/" + simulationId; - remoteFile += "/control"; - - // local tmp file - localFile = File.createTempFile(simulationId, "control"); - - SSHUtils.scpFrom(sshSession, remoteFile, localFile); - - return localFile; - } - } + // /** + // * Thread that check remote control file every 2s. + // */ + // protected class RemoteSSHControlThread implements Runnable { + // + // /** Sleep 1s */ + // protected static final int SLEEPTIME = 1000; + // + // /** Opened ssh session */ + // protected Session sshSession; + // + // /** Control (to update progression) */ + // protected SimulationControl control; + // + // /** + // * Constructor. + // * @param sshSession + // * + // * @param control control + // */ + // protected RemoteSSHControlThread(Session sshSession, + // SimulationControl control) { + // this.sshSession = sshSession; + // this.control = control; + // } + // + // /* + // * @see java.lang.Runnable#run() + // */ + // @Override + // public void run() { + // + // boolean running = true; + // while (running) { + // + // // wait + // try { + // Thread.sleep(SLEEPTIME); + // + // // log (to check if thread is still alive) + // if (log.isDebugEnabled()) { + // log.debug("Control thread wake up"); + // } + // + // try { + // // download control file + // File controlFile = downloadControlFile(control.getId()); + // + // if (log.isDebugEnabled()) { + // log.debug("Control have been downloaded : " + // + controlFile.getAbsolutePath()); + // } + // + // synchronized (control) { + // // le thread principal a pu le modifier pendant le sleep + // //if (control.isRunning()) { + // // 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 + // SimulationStorage.readControl(controlFile, + // control, "stop"); + // //} + // } + // + // // deleteTempFile + // controlFile.delete(); + // } catch (SSHException e) { + // // file doesn't exist + // if(log.isDebugEnabled()) { + // // not add ,e plz :) + // log.debug(_("Remote control file doesn't exists %s", e.getMessage())); + // } + // } + // + // } catch (InterruptedException e) { + // if (log.isErrorEnabled()) { + // log.error("Thread has been interrupted", e); + // } + // } catch (IOException e) { + // if (log.isErrorEnabled()) { + // log.error("Error while reading control file", e); + // } + // } + // + // synchronized (control) { + // running = control.getProgressMax() == 0 || (control.getProgress() < control.getProgressMax() - 1); + // } + // } + // } + // + // + // } } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationExecutor.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin +/* *##% + * Copyright (C) 2002-2009 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 @@ -15,7 +15,7 @@ * 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; @@ -47,11 +47,12 @@ * 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); + private static Log log = LogFactory.getLog(SimulationExecutor.class); - protected PropertyChangeSupport propertyListeners = new PropertyChangeSupport(this); + 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 */ @@ -62,14 +63,14 @@ protected SimulatorLauncher launcher; public SimulationExecutor(SimulationService simulationService, - SimulatorLauncher launcher, - SimulationQueue workQueue) { + SimulatorLauncher launcher, SimulationQueue workQueue) { super(launcher.maxSimulationThread(), launcher.maxSimulationThread(), - 0L, TimeUnit.MILLISECONDS, (BlockingQueue)workQueue); + 0L, TimeUnit.MILLISECONDS, (BlockingQueue) workQueue); this.simulationService = simulationService; this.launcher = launcher; lastCorePoolSize = prestartAllCoreThreads(); - log.info(_("SimulationExecutor started with %s thread for %s", lastCorePoolSize, launcher)); + log.info(_("SimulationExecutor started with %s thread for %s", + lastCorePoolSize, launcher)); } public SimulationService getSimulationService() { @@ -79,12 +80,13 @@ public SimulatorLauncher getLauncher() { return launcher; } - + public void addPropertyChangeListener(PropertyChangeListener listener) { propertyListeners.addPropertyChangeListener(listener); } - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { propertyListeners.addPropertyChangeListener(propertyName, listener); } @@ -92,7 +94,8 @@ propertyListeners.removePropertyChangeListener(listener); } - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { propertyListeners.removePropertyChangeListener(propertyName, listener); } @@ -108,10 +111,10 @@ @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()) { @@ -120,12 +123,13 @@ // serait alors jamais executer et ce n'est pas forcement ce que // l'on souhaite if (r instanceof SimulationItem) { - SimulationService.getService().resubmit((SimulationJob)r); + SimulationService.getService().resubmit((SimulationJob) r); } - throw new RuntimeException(_("Normal stop thread, this is not an error")); + throw new RuntimeException( + _("Normal stop thread, this is not an error")); } if (r instanceof SimulationJob) { - SimulationJob job = (SimulationJob)r; + 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 @@ -144,9 +148,10 @@ job.setLauncher(launcher); } } else { - log.warn(_("Jobs submited is not ItemSimulation but was %s", r.getClass().getName())); - } - } + log.warn(_("Jobs submited is not ItemSimulation but was %s", r + .getClass().getName())); + } + } public boolean isPause() { return pause; @@ -158,14 +163,14 @@ 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 @@ -186,5 +191,5 @@ } propertyListeners.firePropertyChange("pause", oldValue, this.pause); } - + } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationItem.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -19,7 +19,6 @@ package fr.ifremer.isisfish.simulator.launcher; - import fr.ifremer.isisfish.simulator.SimulationControl; import fr.ifremer.isisfish.simulator.SimulationParameter; import java.io.File; @@ -38,7 +37,7 @@ public class SimulationItem { /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(SimulationItem.class); + private static Log log = LogFactory.getLog(SimulationItem.class); /** le control pour la simulation */ protected SimulationControl control; Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationJob.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -19,22 +19,22 @@ 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 fr.ifremer.isisfish.types.Month; +import static org.codelutin.i18n.I18n._; + import java.io.File; -import static org.codelutin.i18n.I18n._; - 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; +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationParameter; + /** * Classe responsable de la simulation d'un {@link SimulationItem}. Pour cela * il utilise le {@link SimulatorLauncher}. Si la simulation echoue @@ -51,7 +51,7 @@ 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); + protected static Log log = LogFactory.getLog(SimulationJob.class); transient protected String id; /** l'ensemble des post actions a effectuer pour ce job */ @@ -67,12 +67,16 @@ protected int priority; /** Le launcher a utiliser pour simuler cet item */ protected SimulatorLauncher launcher; + /** Set it to true to restart simulation checking without restarting reel simulation */ + protected boolean onlyCheckControl; - public SimulationJob(SimulationService simulationService, SimulationItem item, int priority) { + public SimulationJob(SimulationService simulationService, + SimulationItem item, int priority) { this(simulationService, null, item, priority); } - public SimulationJob(SimulationService simulationService, SimulationJob parentJob, SimulationItem item, int priority) { + public SimulationJob(SimulationService simulationService, + SimulationJob parentJob, SimulationItem item, int priority) { this.simulationService = simulationService; this.parentJob = parentJob; this.item = item; @@ -87,6 +91,10 @@ this.postActions.remove(postAction); } + public Set<PostAction> getPostActions() { + return this.postActions; + } + public String getId() { if (id == null) { id = getItem().getControl().getId(); @@ -116,11 +124,11 @@ public SimulationJob getParentJob() { return parentJob; } - + public SimulationItem getItem() { return item; } - + public void setLauncher(SimulatorLauncher launcher) { this.launcher = launcher; } @@ -128,11 +136,18 @@ public SimulatorLauncher getLauncher() { return launcher; } - + public int getPriority() { return priority; } + /** + * @param onlyCheckControl the onlyCheckControl to set + */ + public void setOnlyCheckControl(boolean onlyCheckControl) { + this.onlyCheckControl = onlyCheckControl; + } + public int compareTo(SimulationJob o) { int result = this.priority - o.priority; if (result == 0) { @@ -140,7 +155,7 @@ } return result; } - + /** * Fait la simulation. La simulation en elle meme est delegue au * {@link SimulatorLauncher}. Le travail restant ici est le nettoyage, @@ -151,20 +166,25 @@ try { SimulationControl control = item.getControl(); String id = control.getId(); - if (control.isStopSimulationRequest() || - (getParentJob() != null && getParentJob().getItem().getControl().isStopSimulationRequest())) { - log.info(_("Not start simulation %s because user ask stop", id)); - return ; + if (control.isStopSimulationRequest() + || (getParentJob() != null && getParentJob().getItem() + .getControl().isStopSimulationRequest())) { + log + .info(_( + "Not start simulation %s because user ask stop", + id)); + return; } SimulationParameter param = item.getParameter(); log.debug("Start simulation: " + id); simulationService.fireStartEvent(this); - - if (getParentJob() == null && param.getUseAnalysePlan() && !param.isIndependentPlan()) { + + if (!onlyCheckControl && 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); + Iterator<SimulationJob> i = new SimulationService.PrepareSimulationJob( + simulationService, this); while (!control.isStopSimulationRequest() && i.hasNext()) { log.info(_("Generate next simulation")); SimulationJob subjob = i.next(); @@ -174,16 +194,21 @@ // nettoyage si besoin apres toutes les simulations if (param.getOnlyExport()) { - for (File file : FileUtil.find( - SimulationStorage.getSimulationDirectory(), - id + "_[0-9]+$", false)) { + 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 - + + // Dans le cas d'un simulation simple seulement + // on mémorise la simulation comme "lancée" et + // devant être re monitorée au lancement d'isis + // FIXME try to remove static call + SimulationMonitor.getInstance().simulationStart(this); + /* code moved to fr.ifremer.isisfish.simulator.launcher.InProcessSimulatorLauncher.simulate(SimulationService, SimulationControl, File) // set date to 0 at beginning of simulation @@ -195,35 +220,47 @@ int lastDate = lastYear * Month.NUMBER_OF_MONTH; control.setProgressMax(lastDate);*/ - File zip = item.getSimulationZip(); - SimulationStorage simulation = launcher.simulate(simulationService, control, zip); + SimulationStorage simulation = null; + if (!onlyCheckControl) { + File zip = item.getSimulationZip(); + launcher.simulate(simulationService, control, zip); + } + // simulation ended + //simulation = launcher.getSimulationStorage(simulationService, + // control); + + /* + + Code moved to {@link fr.ifremer.isisfish.simulator.launcher.SimulationMonitor#doPostSimulationOperation(SimulationJob, SimulatorLauncher)} + try { - // copie les exports de simulation dans le repertoire + // 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()); + 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); + 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()) { + if (getParentJob() == null || param.getUseAnalysePlan() + && param.isIndependentPlan()) { simulation.delete(false); } } @@ -237,13 +274,9 @@ } catch (Exception eee) { log.error(_("Can't do post action %s", action), eee); } - } - // la simulation est termine on avance la progress au dernier cran - // attention on utilise ca aussi pour detecer la fin d'une simulation - // quand date =progressMax - control.setProgress(control.getProgress()+1); + }*/ } - + } catch (Throwable eee) { log.warn(_("Can't simulate %s", item.getControl().getId()), eee); if (eee instanceof RemoteException) { @@ -255,11 +288,11 @@ action.exception(this, eee); } } - } finally { - simulationService.fireStopEvent(this); - } + } /*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 @@ -271,6 +304,7 @@ * @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 Added: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationMonitor.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationMonitor.java (rev 0) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationMonitor.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -0,0 +1,498 @@ +/* *##% + * Copyright (C) 2009 Code Lutin + * + * 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.I18n._; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.rmi.RemoteException; +import java.util.Calendar; +import java.util.Date; +import java.util.Map; +import java.util.Properties; +import java.util.SortedMap; +import java.util.Timer; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.util.FileUtil; + +import fr.ifremer.isisfish.datastore.SimulationStorage; +import fr.ifremer.isisfish.simulator.SimulationControl; +import fr.ifremer.isisfish.simulator.SimulationParameter; +import fr.ifremer.isisfish.simulator.launcher.SimulationJob.PostAction; + +/** + * Moniteur singleton pour pouvoir sauvegarder + * localement la liste des simulations démarrées et + * permettre de continuer le monitoring au relancemenent + * d'Isis. + * + * Cette classe n'implemente pas {@link SimulationServiceListener} + * car elle ne doit pas écouter toutes les simulations, mais + * seulement celle dit simple, c'est-à-dire "master plan" du plan + * d'analyse. + * + * @author chatellier + * @version $Revision: 1.0 $ + * + * Last update : $Date: 28 janv. 2009 $ + * By : $Author: chatellier $ + */ +public class SimulationMonitor extends Thread { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static Log log = LogFactory.getLog(SimulationMonitor.class); + + /** Instance. */ + protected static SimulationMonitor instance = new SimulationMonitor(); + + /** + * Simulation information saving file. + * + * Saved in $HOME/.isis-simulations-3 + */ + protected File monitorFile; + + /** + * Liste des simulations en cours, + * Le format est défini ainsi : + * id=launcher,datedelancement,export,plandependant + */ + protected Properties properties = new Properties(); + + /** + * Map to remember when a simulation have to be checked. + * + * Sorted on date ASC. + */ + protected SortedMap<Date, SimulationJob> checkMap; + + /** + * Check scheduler. + */ + protected Timer checkScheduler; + + /** + * Constructeur. + */ + protected SimulationMonitor() { + // FIXME configure this path + String monitorSaveFile = System.getProperty("user.home") + + File.separator + ".isis-simulations-3"; + monitorFile = new File(monitorSaveFile); + + // init monitor check map + checkMap = new TreeMap<Date, SimulationJob>(); + + // init timer + checkScheduler = new Timer(); + } + + /** + * Instance getter. + * + * @return instance + */ + public static SimulationMonitor getInstance() { + return instance; + } + + /** + * Reload config and read non simulation job + * into simulation service. + * + * @param service SimulationService + */ + public void reloadConfig(SimulationService service) { + + if (monitorFile.canRead()) { + try { + properties.load(new FileInputStream(monitorFile)); + + restartSimulationProgression(service); + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Can't reload monitor file", e); + } + } + } + + } + + /** + * Take all simulation in loaded file. + * And add it into simulation service. + */ + protected void restartSimulationProgression(SimulationService service) { + + for (Map.Entry<Object, Object> entry : properties.entrySet()) { + String simulationId = (String) entry.getKey(); + String simulationInfo = (String) entry.getValue(); + + // 0 = launcher + // 1 = date + // 2 = export + // 3 = plan dependent + String[] simulationInfos = simulationInfo.split(","); + String simulationLauncher = simulationInfos[0]; + String simulationDate = simulationInfos[1]; + String simulationExport = simulationInfos[2]; + String simulationPlan = simulationInfos[3]; + + if (log.isInfoEnabled()) { + log.info("Restart monitoring of " + simulationId); + if (log.isDebugEnabled()) { + log.debug(" launcher= " + simulationLauncher + ", date = " + + simulationDate); + } + } + + // FIXME date + + // re add simulation in + try { + SimulatorLauncher launcher = (SimulatorLauncher) Class.forName( + simulationLauncher).newInstance(); + + SimulationParameter params = new SimulationParameter(); + params.setUseAnalysePlan("true" + .equalsIgnoreCase(simulationPlan)); + params.setOnlyExport("true".equalsIgnoreCase(simulationExport)); + + service.submitForCheckOnly(simulationId, params, launcher, 0); + } catch (ClassNotFoundException e) { + if (log.isErrorEnabled()) { + log.error("Can't found launcher for this simulation", e); + } + } catch (InstantiationException e) { + if (log.isErrorEnabled()) { + log.error("Can't get launcher for this simulation", e); + } + } catch (IllegalAccessException e) { + if (log.isErrorEnabled()) { + log.error("Can't get launcher for this simulation", e); + } + } + } + } + + public void simulationStart(SimulationJob job) { + + String monitorKey = job.getId(); + SimulatorLauncher launcher = job.getLauncher(); + + // 0 = launcher + String monitorValue = job.getLauncher().getClass().getName(); + // 1 = date + monitorValue += "," + System.currentTimeMillis(); + // 2 = export + monitorValue += "," + job.getItem().getParameter().getOnlyExport(); + // 3 = plan dependent + monitorValue += "," + job.getItem().getParameter().getUseAnalysePlan(); + + properties.put(monitorKey, monitorValue); + try { + properties.store(new FileOutputStream(monitorFile), + "Simulation added at " + new Date()); + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Can't save monitor file", e); + } + } + + if (log.isInfoEnabled()) { + log.info("Saving simulation " + monitorKey + " as started"); + } + + // put interval in launcher ? + Date checkDate = new Date(); + // do check at start + //long intervalInSeconds = launcher.getCheckProgressionInterval(); + //checkDate.setTime(checkDate.getTime() + intervalInSeconds); + + // add simulation to check queue + checkMap.put(checkDate, job); + + // start thread if not already started + if (!this.isAlive()) { + this.start(); + } + } + + /** + * Mark a simulation as stopped. + * Remove it from save file. + * + * @param job job that control the simulation + */ + public void simulationStop(SimulationJob job) { + String monitorKey = job.getId(); + + properties.remove(monitorKey); + try { + if (properties.isEmpty()) { + monitorFile.delete(); + } else { + properties.store(new FileOutputStream(monitorFile), + "Simulation delete at " + new Date()); + } + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error("Can't save monitor file", e); + } + } + + if (log.isInfoEnabled()) { + log.info("Saving simulation " + monitorKey + " as stopped"); + } + } + + /* + * @see java.util.TimerTask#run() + */ + @Override + public void run() { + + // main loop to monitor "all" running simulation + + while (true) { + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + if (log.isErrorEnabled()) { + log.error("Monitor thread has been interrupted", e); + } + } + + // log + if (log.isDebugEnabled()) { + log.debug("Simulation monitor wake up"); + } + + // take first job in map + if (!checkMap.isEmpty()) { + Date date = checkMap.firstKey(); + Date now = new Date(); + + if (date.before(now)) { + // first key date in map is over... + // check is needed + SimulationJob job = checkMap.get(date); + SimulatorLauncher launcher = job.getLauncher(); + + boolean jobIsFinished = checkProgression(job, launcher); + + // always remove this simulation from map + checkMap.remove(date); + + // if not finished, re-add it at + if (jobIsFinished) { + doPostSimulationOperation(job, launcher); + } else { + // next check date + long nextJobTimeMs = date.getTime() + + launcher.getCheckProgressionInterval() * 1000; + Date nextJobDate = new Date(nextJobTimeMs); + checkMap.put(nextJobDate, job); + } + + // finally, schedule, next check + /*if (!checkMap.isEmpty()) { + Date nextDate = checkMap.firstKey(); + checkScheduler.schedule(this, nextDate); + }*/ + } else { + //checkScheduler.schedule(this, date); + if (log.isDebugEnabled()) { + log.debug("Time to check not reached, skip check, " + + date + " < " + now); + } + } + } + } + } + + /** + * Check progression. + * + * @param job job to check progression + * @param launcher SimulatorLauncher that manage simulation + * @return <tt>true</tt> is simulation is finished, <tt>false<tt> otherwise + */ + protected boolean checkProgression(SimulationJob job, + SimulatorLauncher launcher) { + + boolean simulationEnded = false; + + SimulationService service = SimulationService.getService(); + SimulationControl control = job.getItem().getControl(); + + // log + if (log.isInfoEnabled()) { + log.info("Checking simulation progression : " + control.getId()); + log.debug(" with launcher = " + launcher); + } + + // update + try { + launcher.updateControl(service, control); + + // by default, Progress = ProgressMax = 0 + if (control.getProgress() > 0 + && control.getProgress() >= control.getProgressMax() - 1) { + simulationEnded = true; + } + } catch (RemoteException e) { + if (log.isErrorEnabled()) { + log.error("Progression thread update error", e); + } + } + + return simulationEnded; + } + + /** + * Operation to do after simulation end. + * + * - get simulation result + * - do result export + * + * @param job job + * @param launcher {@link SimulatorLauncher} that manage simulation + */ + protected void doPostSimulationOperation(SimulationJob job, + SimulatorLauncher launcher) { + + SimulationService service = SimulationService.getService(); + SimulationControl control = job.getItem().getControl(); + + if (log.isInfoEnabled()) { + log.info("Do post simulation operation for " + control.getId()); + } + + try { + // get storage + SimulationStorage simulation = launcher.getSimulationStorage( + service, control); + + // post manage this storage + exportResult(job, simulation); + + // notify simulation ended + // to not check later... + simulationStop(job); + } catch (RemoteException e) { + if (log.isErrorEnabled()) { + log.error("Can't get simulation results after simulation end", + e); + } + } finally { + service.fireStopEvent(job); + } + + } + + /** + * Export result, and delete simulation if "onlyExport" has + * been selected. + */ + protected void exportResult(SimulationJob job, SimulationStorage simulation) { + + SimulationParameter param = job.getItem().getParameter(); + SimulationControl control = job.getItem().getControl(); + String id = control.getId(); + + try { + // copie les exports de simulation dans le repertoire + // souhaiter par l'utilisateur + if (param.getExportNames() != null + && param.getExportNames().size() > 0) { + + // log + if (log.isDebugEnabled()) { + log.debug("Export results"); + } + + 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); + } else { + // log + if (log.isDebugEnabled()) { + log.debug("Not Export results : unneeded"); + } + } + } catch (Exception eee) { + if (log.isErrorEnabled()) { + 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 + // FIXME fix parent job test + if (/*getParentJob() == null || */param.getUseAnalysePlan() + && param.isIndependentPlan()) { + + // log + if (log.isDebugEnabled()) { + log + .debug("Export \"onlyExport\" : deleting simulation"); + } + + simulation.delete(false); + } else { + // log + if (log.isDebugEnabled()) { + log + .debug("Not onlyExport options : not delete simulation"); + } + } + } + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error(_("Can't delete simulation %s ", id), eee); + } + } + + for (PostAction action : job.getPostActions()) { + try { + action.finished(job, simulation); + } catch (Exception eee) { + if (log.isErrorEnabled()) { + log.error(_("Can't do post action %s", action), eee); + } + } + } + } +} Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationQueue.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationQueue.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationQueue.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -19,7 +19,6 @@ package fr.ifremer.isisfish.simulator.launcher; - import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -38,15 +37,17 @@ */ public class SimulationQueue extends JDKPriorityBlockingQueue<SimulationJob> { + /** serialVersionUID. */ + private static final long serialVersionUID = -6130030747211387382L; + /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(SimulationQueue.class); + private static Log log = LogFactory.getLog(SimulationQueue.class); protected SimulationQueue parent = null; protected List<SimulationQueue> childs = new LinkedList<SimulationQueue>(); public SimulationQueue() { } - public SimulationQueue(SimulationQueue parent) { parent.addChild(this); } @@ -74,7 +75,6 @@ } } - @Override public boolean offer(SimulationJob e) { boolean result = super.offer(e); @@ -117,8 +117,8 @@ try { // on fait bien un poll, sur le pere, car on ne souhaite pas // rester bloquer dessus - while (q.size() == 0 && - (parent == null || null == (result = parent.poll()))) { + while (q.size() == 0 + && (parent == null || null == (result = parent.poll()))) { notEmpty.await(); } } catch (InterruptedException ie) { @@ -136,7 +136,8 @@ } @Override - public SimulationJob poll(long timeout, TimeUnit unit) throws InterruptedException { + public SimulationJob poll(long timeout, TimeUnit unit) + throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); @@ -160,6 +161,5 @@ lock.unlock(); } } - - + } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationService.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -91,25 +91,26 @@ */ public class SimulationService { - static final public String SIMULATION_LAUNCHER = "simulation.launcher"; + public static final 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; - + public static final int MAX_PLAN_SIMULATION = 20000; + /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(SimulationService.class); + private static Log log = LogFactory.getLog(SimulationService.class); - static protected SimulationService instance = new SimulationService(); + protected static SimulationService instance = new SimulationService(); /** * Retourne l'instance du SimulationService a utiliser * @return l'instance a utiliser */ - static public SimulationService getService() { + public static SimulationService getService() { return instance; } - protected PropertyChangeSupport propertyListeners = new PropertyChangeSupport(this); + protected PropertyChangeSupport propertyListeners = new PropertyChangeSupport( + this); protected ListenerSet<SimulationServiceListener> listeners = new ListenerSet<SimulationServiceListener>(); // FIXME pouvoir configurer ceci en fichier de config @@ -119,15 +120,13 @@ /** L'executor utilise pour creer toutes les sous simulations des plans * independants */ - protected ExecutorService subSimulationComputationExecutor = - Executors.newSingleThreadExecutor(); + protected ExecutorService subSimulationComputationExecutor = Executors + .newSingleThreadExecutor(); /** Tous les types de {@link SimulatorLauncher} disponibles, et leur * executors associe */ - protected Map<SimulatorLauncher, SimulationExecutor> executors = - new LinkedHashMap<SimulatorLauncher, SimulationExecutor>(); + protected Map<SimulatorLauncher, SimulationExecutor> executors = new LinkedHashMap<SimulatorLauncher, SimulationExecutor>(); /** Le nombre d'erreur pour les SimulatorLauncher */ - protected Map<SimulatorLauncher, MutableInt> launcherError = - new HashMap<SimulatorLauncher, MutableInt>(); + protected Map<SimulatorLauncher, MutableInt> launcherError = new HashMap<SimulatorLauncher, MutableInt>(); /** La queue contenant toutes les simulations a faire */ protected SimulationQueue queue = new SimulationQueue(); @@ -144,23 +143,30 @@ */ protected SimulationService() { // on cree un executor par type SimulatorLauncher - Properties prop = IsisFish.config.getOptionStartsWith(SIMULATION_LAUNCHER); + Properties prop = IsisFish.config + .getOptionStartsWith(SIMULATION_LAUNCHER); // sort simulation names by... names // this solve "local" "sub", "remote" order // default "local" is in first in UI. - List<String> simulationKeys = new ArrayList<String>(prop.stringPropertyNames()); + List<String> simulationKeys = new ArrayList<String>(prop + .stringPropertyNames()); Collections.sort(simulationKeys); - + for (String key : simulationKeys) { String value = prop.getProperty(key); try { - SimulatorLauncher sl = (SimulatorLauncher) ObjectUtil.newInstance(value); + SimulatorLauncher sl = (SimulatorLauncher) ObjectUtil + .newInstance(value); addSimulationLauncher(sl); } catch (Exception eee) { log.warn(_("Can't instantiate %s", value), eee); } } + + // fait un appel au moniteur + // pour reprendre le monitoring des simulation en cours + SimulationMonitor.getInstance().reloadConfig(this); } /** @@ -175,15 +181,16 @@ executors.put(sl, se); launcherError.put(sl, new MutableInt(0)); } - + /** * @return les SimulatorLauncher et leurs noms */ - public List<SimulatorLauncher> getSimulationLaunchers(){ - List<SimulatorLauncher> result = new ArrayList<SimulatorLauncher>(executors.keySet()); + public List<SimulatorLauncher> getSimulationLaunchers() { + List<SimulatorLauncher> result = new ArrayList<SimulatorLauncher>( + executors.keySet()); return result; } - + public Collection<SimulationExecutor> getSimulationExecutors() { return executors.values(); } @@ -195,7 +202,7 @@ public Set<SimulationJob> getJobDones() { return jobDones; } - + /** * Retourne la liste de tous les {@link SimulatorLauncher} disponible * @return @@ -216,7 +223,8 @@ propertyListeners.addPropertyChangeListener(listener); } - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { propertyListeners.addPropertyChangeListener(propertyName, listener); } @@ -224,7 +232,8 @@ propertyListeners.removePropertyChangeListener(listener); } - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { propertyListeners.removePropertyChangeListener(propertyName, listener); } @@ -273,7 +282,7 @@ l.clearJobDone(this); } } - + /** * @return Returns the autoLaunch. */ @@ -291,7 +300,8 @@ if (this.autoLaunch) { this.notifyAll(); } - propertyListeners.firePropertyChange("autoLaunch", oldValue, autoLaunch); + propertyListeners.firePropertyChange("autoLaunch", oldValue, + autoLaunch); } } @@ -300,7 +310,7 @@ * a suspendu la queue */ protected void waitAutoLaunch() { - synchronized(this) { + synchronized (this) { while (!isAutoLaunch()) { try { log.info("autoLaunch is false waiting queue start"); @@ -311,7 +321,7 @@ } } } - + /** * 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 @@ -334,11 +344,11 @@ SimulationJob job = new SimulationJob(this, item, priority); job.setLauncher(launcher); 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); @@ -351,7 +361,40 @@ } } - + + /** + * Resoumet une simulation qui a deja été démarrée, mais + * on ne faisant que du control de monitoring. + * + * @param id + * @param param + * @param launcher + * @param priority + */ + public void submitForCheckOnly(String id, SimulationParameter param, + SimulatorLauncher launcher, 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); + job.setLauncher(launcher); + fireStartEvent(job); + + job.setOnlyCheckControl(true); + + //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 + submit(job); + //} + + } + protected void submit(SimulationJob job) { SimulatorLauncher launcher = job.getLauncher(); // on ajoute a la queue qui utilise le launcher defini dans le job @@ -369,7 +412,7 @@ log.info(_("Add to default 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 @@ -381,7 +424,7 @@ protected void resubmit(SimulationJob job) { submit(job); } - + /** * Permet de soumettre a la queue un job provenant d'un plan. * Ce plan ne doit pas apparaitre dans la console de queue. @@ -391,7 +434,7 @@ protected void submitSubJob(SimulationJob job) { submit(job); } - + /** * Supprime un job de la queue (annulation d'une simulation). Appele * depuis {@link SimulationJob#stop} @@ -405,12 +448,12 @@ 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 @@ -423,8 +466,10 @@ 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())); + log + .error(_( + "Launcher %s will be stopped because there are too many error (%s)", + launcher, i.intValue())); SimulationExecutor e = executors.get(launcher); e.pause(); } @@ -443,7 +488,8 @@ * 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 { + public static class PrepareSimulationJob implements Runnable, + Iterator<SimulationJob>, SimulationJob.PostAction { protected SimulationService simulationService; protected AnalysePlanContext planContext; @@ -454,7 +500,7 @@ protected SimulationControl control; protected SimulationParameter param; protected int done = 0; - + public PrepareSimulationJob(SimulationService simulationService, SimulationJob job) { this.simulationService = simulationService; @@ -464,7 +510,7 @@ param = job.getItem().getParameter(); this.planContext = new AnalysePlanContext(control.getId(), param); } - + /** * genere toutes les sous simulations et les places dans la queue */ @@ -474,7 +520,8 @@ SimulationJob subJob = next(); simulationService.submitSubJob(subJob); } catch (Exception eee) { - log.error(_("Can't add simulation: ", job.getItem().getControl().getId()), eee); + log.error(_("Can't add simulation: ", job.getItem() + .getControl().getId()), eee); } } @@ -483,7 +530,7 @@ /** * 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 SimulationService.MAX_PLAN_SIMULATION} + * est limite a {@link SimulationService#MAX_PLAN_SIMULATION} * * @return <tt>true</tt> if has next */ @@ -500,7 +547,10 @@ planContext.incNumber(); int planNumber = planContext.getNumber(); if (planNumber > MAX_PLAN_SIMULATION) { - log.error(_("Analyse plan error, too many simulation for %s : %s", id, planNumber)); + log + .error(_( + "Analyse plan error, too many simulation for %s : %s", + id, planNumber)); doNext = false; result = false; } else { @@ -509,13 +559,17 @@ File tmpDirectory = FileUtil.createTempDirectory( "isisfish-simultation-", "-preparation"); - SimulationStorage sim = SimulationStorage.importAndRenameZip( - tmpDirectory, job.getItem().getSimulationZip(), simId); + 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); + result = result + && plan.beforeSimulation(planContext, + sim); if (!result) { nextJob = null; break; @@ -524,24 +578,29 @@ doNext = result; if (result) { File zip = sim.createZip(); - SimulationControl childControl = new SimulationControl(simId); + SimulationControl childControl = new SimulationControl( + simId); SimulationParameter childParam = param.copy(); - SimulationItem item = new SimulationItem(childControl, childParam, zip); - nextJob = new SimulationJob(simulationService, job, item, job.getPriority()); + SimulationItem item = new SimulationItem( + childControl, childParam, zip); + nextJob = new SimulationJob(simulationService, + job, item, job.getPriority()); nextJob.setLauncher(job.getLauncher()); 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)); + log.warn(_("isisfish.error.remove.directory", + tmpDirectory)); } } } } return result; } catch (Exception eee) { - throw new IsisFishRuntimeException(_("isisfish.error.evalute.plan.script"), eee); - } + throw new IsisFishRuntimeException( + _("isisfish.error.evalute.plan.script"), eee); + } } @@ -556,9 +615,9 @@ public void remove() { throw new UnsupportedOperationException("Not supported."); } - + public void finished(SimulationJob job, SimulationStorage sim) { -// doNext = true; + // doNext = true; // appel de tous les plans pour modifier la simulation for (AnalysePlan plan : sim.getParameter().getAnalysePlans()) { @@ -566,8 +625,11 @@ boolean 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); + log + .error( + _( + "Stop simulation plan, because can't call afterSimulation correctly on plan %s", + plan.getClass().getName()), eee); doNext = false; } } @@ -588,7 +650,7 @@ simulationService.fireStopEvent(this.job); } } - + /** * Prepare les fichiers qui seront utilsé à la simulation: * <li> scripts @@ -611,70 +673,86 @@ * @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 { + protected File prepareSimulationZipFile(SimulationControl control, + SimulationParameter param, boolean compile) + throws SimulationException { try { - File tmpDirectory = FileUtil.createTempDirectory("isisfish-simultation-", "-preparation"); + File tmpDirectory = FileUtil.createTempDirectory( + "isisfish-simultation-", "-preparation"); //File regionXML = IsisConfig.getDataBackupFile(tmpDirectory); - File regionXML = new File(tmpDirectory, SimulationStorage.DATA_BACKUP_FILENAME); + 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); + 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 control.setText(_("isisfish.message.backup.database.progress")); - RegionStorage region = RegionStorage.getRegion(param.getRegionName()); + RegionStorage region = RegionStorage.getRegion(param + .getRegionName()); TopiaContext tc = region.getStorage().beginTransaction(); tc.backup(regionXML, true); tc.closeContext(); control.setText(_("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")); + 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")); + 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")); + 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)); + 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$"); - + 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())); - + 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(); @@ -684,16 +762,18 @@ 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); + throw new SimulationException( + _("isisfish.error.prepare.information.simulation"), eee); } catch (TopiaException eee) { - throw new SimulationException(_("isisfish.error.prepare.information.simulation"), 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 @@ -719,16 +799,21 @@ List<File> fileToCompile = new ArrayList<File>(); - List<File> tmp = FileUtil.find(new File(directory, ExportStorage.EXPORT_PATH), ".*\\.java$", true); + 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); + 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); + 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); + tmp = FileUtil.find( + new File(directory, SimulatorStorage.SIMULATOR_PATH), + ".*\\.java$", true); fileToCompile.addAll(tmp); // @@ -737,7 +822,8 @@ CompileHelper.compile(directory, fileToCompile, directory, null); long time = System.nanoTime() - currentTime; - control.setText(_("isisfish.message.compilation.time", DurationFormatUtils.formatDuration(time / 1000000, "s'.'S"))); + control.setText(_("isisfish.message.compilation.time", + DurationFormatUtils.formatDuration(time / 1000000, "s'.'S"))); } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceListener.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ -/* - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin +/* *##% + * Copyright (C) 2002-2009 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 @@ -15,7 +15,7 @@ * 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; @@ -42,7 +42,7 @@ * @param job job that responsable to simulation */ public void simulationStop(SimulationService simService, SimulationJob job); - + /** * Previent que le simulation service a vide ca liste de simulation faites * @param simService le simulation service dont la liste des jobs finis Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulationServiceTableModel.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -54,36 +54,31 @@ private static final long serialVersionUID = 2414926794815727974L; /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(SimulationServiceTableModel.class); + private static 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 final static String[] columnHeader = new String[] { + _("isisfish.queue.id"), _("isisfish.queue.plan"), + _("isisfish.queue.launcher"), _("isisfish.queue.status"), + _("isisfish.queue.progression"), }; + /** columns types */ - protected Class<?>[] columnClass = new Class[]{ - String.class, // id - String.class, // analyse plan number - String.class, // local, remote, batch - String.class, // text - JProgressBar.class // progress + protected Class<?>[] columnClass = new Class[] { String.class, // id + String.class, // analyse plan number + String.class, // local, remote, batch + String.class, // text + JProgressBar.class // progress }; - protected SimulationService simulationService; protected ArrayList<SimulationJob> jobs; protected Map<String, SimulationJob> jobIds; /** progress bar (one for each row) */ - protected Map<SimulationJob, JProgressBar> progress = - new WeakHashMap<SimulationJob, JProgressBar>(); + protected Map<SimulationJob, JProgressBar> progress = new WeakHashMap<SimulationJob, JProgressBar>(); protected AbstractJobListener jobListener; protected ControlListener controlListener; - + public SimulationServiceTableModel(SimulationService simulationService, boolean forDoToJobs) { this.simulationService = simulationService; @@ -99,7 +94,7 @@ public void addJob(SimulationJob job) { String id = job.getItem().getControl().getId(); - synchronized(jobs) { + synchronized (jobs) { if (!contains(job)) { jobs.add(job); jobIds.put(id, job); @@ -107,9 +102,9 @@ } } } - + public void removeJob(SimulationJob job) { - synchronized(jobs) { + synchronized (jobs) { int index = jobs.indexOf(job); if (index >= 0) { jobs.remove(index); @@ -117,7 +112,7 @@ } } } - + public void clearJob() { jobs.clear(); fireTableDataChanged(); @@ -129,7 +124,7 @@ public void setJobs(ArrayList<SimulationJob> jobs) { this.jobs = jobs; - synchronized(jobs) { + synchronized (jobs) { jobIds = new HashMap<String, SimulationJob>(jobs.size()); for (SimulationJob job : jobs) { jobIds.put(job.getItem().getControl().getId(), job); @@ -137,15 +132,15 @@ fireTableDataChanged(); } } - + public boolean contains(SimulationJob job) { String id = job.getItem().getControl().getId(); synchronized (jobs) { boolean result = jobIds.containsKey(id); return result; - } + } } - + protected JProgressBar getProgressBar(SimulationJob job) { JProgressBar result = progress.get(job); if (result == null) { @@ -157,10 +152,10 @@ } public SimulationJob getJob(int row) { - SimulationJob result = jobs.get(row); + SimulationJob result = jobs.get(row); return result; } - + /* * @see javax.swing.table.TableModel#getRowCount() */ @@ -197,9 +192,9 @@ * @see javax.swing.table.TableModel#getValueAt(int, int) */ public Object getValueAt(int rowIndex, int columnIndex) { - + // FIXME ArrayIndexOutOfBoundException here - if(rowIndex >= jobs.size()) { + if (rowIndex >= jobs.size()) { return null; } @@ -210,51 +205,52 @@ Object result = ""; - if(log.isTraceEnabled()) { - log.trace("Update table model : " + - "id = " + control.getId() + ", " + - "control.getProgress() = " + control.getProgress() + ", " + - "control.getProgressMax() = " + control.getProgressMax() + ", "+ - "control.getDate() = " + control.getDate()); + if (log.isTraceEnabled()) { + log.trace("Update table model : " + "id = " + control.getId() + + ", " + "control.getProgress() = " + control.getProgress() + + ", " + "control.getProgressMax() = " + + control.getProgressMax() + ", " + "control.getDate() = " + + control.getDate()); } switch (columnIndex) { - case 0: - result = id; - break; - case 1: + case 0: + result = id; + break; + case 1: + if (param.getUseAnalysePlan()) { + int number = param.getAnalysePlanNumber(); + if (number >= 0) { + result = number; + } + } + break; + case 2: + if (job.getLauncher() == null) { if (param.getUseAnalysePlan()) { - int number = param.getAnalysePlanNumber(); - if (number >=0) { - result = number; - } - } - break; - case 2: - if (job.getLauncher() == null) { - if (param.getUseAnalysePlan()) { - result = _("Master plan"); - } else { - result = _("not started"); - } + result = _("Master plan"); } else { - result = job.getLauncher().toString(); + result = _("not started"); } - break; - case 3: - if (control.isStopSimulationRequest()) { - result = _("isisfish.launch.stop"); - } else { - result = control.getText(); - } - break; - case 4: - JProgressBar pb = getProgressBar(job); - pb.setMaximum(control.getProgressMax()); - pb.setValue(control.getProgress()); - pb.setString(control.getDate().getMonth() + "/" + control.getDate().getYear()); - result = pb; - break; + } else { + result = job.getLauncher().toString(); + } + break; + case 3: + if (control.isStopSimulationRequest()) { + result = _("isisfish.launch.stop"); + } else { + result = control.getText(); + } + break; + case 4: + JProgressBar pb = getProgressBar(job); + pb.setMaximum(control.getProgressMax()); + pb.setValue(control.getProgress()); + pb.setString(control.getDate().getMonth() + "/" + + control.getDate().getYear()); + result = pb; + break; } return result; } @@ -262,9 +258,10 @@ protected interface AbstractJobListener extends SimulationServiceListener { public void setData(); } - - class JobDoneListener implements AbstractJobListener, SimulationServiceListener { + class JobDoneListener implements AbstractJobListener, + SimulationServiceListener { + protected SimulationService simulationService; protected SimulationServiceTableModel model; @@ -274,27 +271,31 @@ this.model = model; setData(); } - + public void setData() { - model.setJobs(new ArrayList<SimulationJob>(simulationService.getJobDones())); + model.setJobs(new ArrayList<SimulationJob>(simulationService + .getJobDones())); } - - public void simulationStart(SimulationService simService, SimulationJob job) { - // nothing to do + + public void simulationStart(SimulationService simService, + SimulationJob job) { + // nothing to do } - public void simulationStop(SimulationService simService, SimulationJob job) { + public void simulationStop(SimulationService simService, + SimulationJob job) { model.addJob(job); } public void clearJobDone(SimulationService simService) { - model.clearJob(); + model.clearJob(); } - + } - - class JobToDoListener implements AbstractJobListener, SimulationServiceListener { + class JobToDoListener implements AbstractJobListener, + SimulationServiceListener { + protected SimulationService simulationService; protected SimulationServiceTableModel model; @@ -304,54 +305,58 @@ this.model = model; setData(); } - + public void setData() { - model.setJobs(new ArrayList<SimulationJob>(simulationService.getJobs())); + model.setJobs(new ArrayList<SimulationJob>(simulationService + .getJobs())); for (SimulationJob job : model.getJobs()) { job.getItem().getControl().addPropertyChangeListener( controlListener); } } - - public void simulationStart(SimulationService simService, SimulationJob job) { + + public void simulationStart(SimulationService simService, + SimulationJob job) { model.addJob(job); job.getItem().getControl().addPropertyChangeListener( model.controlListener); } - public void simulationStop(SimulationService simService, SimulationJob job) { + public void simulationStop(SimulationService simService, + SimulationJob job) { model.removeJob(job); job.getItem().getControl().removePropertyChangeListener( model.controlListener); } public void clearJobDone(SimulationService simService) { - // nothing to do + // nothing to do } - + } - + protected class ControlListener implements PropertyChangeListener { protected SimulationService simulationService; protected SimulationServiceTableModel model; - public ControlListener(SimulationService simulationService, SimulationServiceTableModel model) { + public ControlListener(SimulationService simulationService, + SimulationServiceTableModel model) { this.simulationService = simulationService; this.model = model; } public void propertyChange(PropertyChangeEvent evt) { - SimulationControl control = (SimulationControl)evt.getSource(); + SimulationControl control = (SimulationControl) evt.getSource(); String id = control.getId(); - synchronized(model.jobs) { + synchronized (model.jobs) { SimulationJob job = model.jobIds.get(id); int index = model.getJobs().indexOf(job); if (index >= 0) { fireTableRowsUpdated(index, index); } - } + } } - + } } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SimulatorLauncher.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,4 +1,4 @@ -/* +/* *##% * Copyright (C) 2002-2009 Code Lutin, Benjamin Poussin * * This program is free software; you can redistribute it and/or @@ -15,7 +15,7 @@ * 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; @@ -37,17 +37,13 @@ public interface SimulatorLauncher { /** - * Execute une simulation et retourne le storage ou est stocker la - * simulation + * Execute une 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 RemoteException Si pour l'execution de la simulation @@ -55,13 +51,57 @@ * etre contacte. Dans ce cas la simulation n'a pas ete faite et cette * exception est levee. */ - public SimulationStorage simulate(SimulationService simulationService, + public void 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(); + + /** + * Retourne l'intervalle de temps a utiliser entre deux + * verification de progresssion. + * + * @return intervalle (en secondes); + */ + public int getCheckProgressionInterval(); + + /** + * Retourne le storage où est stockée la simulation. + * + * @param simulationService le {@link SimulationService} qui a initie + * la simulation + * @param control le control de la simulation + * + * @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. + * + * @throws 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 getSimulationStorage( + SimulationService simulationService, SimulationControl control) + throws RemoteException; + + /** + * Met à jour la progression. + * + * @param simulationService le {@link SimulationService} qui a initie + * la simulation + * @param control le control de la simulation + * + * @throws 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 void updateControl(SimulationService simulationService, + SimulationControl control) throws RemoteException; } Modified: isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java =================================================================== --- isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/java/fr/ifremer/isisfish/simulator/launcher/SubProcessSimulationLauncher.java 2009-02-17 11:43:37 UTC (rev 1819) @@ -1,5 +1,5 @@ /* *##% - * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * Copyright (C) 2002-2009 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 @@ -52,18 +52,20 @@ public class SubProcessSimulationLauncher implements SimulatorLauncher { /** Class logger (protected for inner classes) */ - protected static Log log = LogFactory.getLog(SubProcessSimulationLauncher.class); + protected static Log log = LogFactory + .getLog(SubProcessSimulationLauncher.class); //protected boolean finished = false; - + @Override public String toString() { return _("isisfish.simulator.launcher.subprocess"); } @Override - public SimulationStorage simulate(SimulationService simulationService, - SimulationControl control, File simulationZip) throws RemoteException { + public void simulate(SimulationService simulationService, + SimulationControl control, File simulationZip) + throws RemoteException { String simulationId = control.getId(); SimulationStorage simulation = null; try { @@ -71,11 +73,11 @@ // simulationZip, simulationId); simulation = subProcessSimulate(control, simulationZip); } catch (Exception eee) { - if(log.isErrorEnabled()) { + if (log.isErrorEnabled()) { log.error(_("Can't do simulation %s", simulationId), eee); } // FIXME simulation is always null if exception - if(simulation != null) { + if (simulation != null) { simulation.getInformation().setException(eee); } } @@ -83,7 +85,7 @@ // FIXME comment not valid // on retourne directement le simulation storage passe en argument // car la simulation a ete faite avec - return simulation; + //return simulation; } @@ -94,6 +96,19 @@ return result; } + /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#getCheckProgressionInterval() + */ + @Override + public int getCheckProgressionInterval() { + + // par defaut, pour les subprocess 5 secondes + // FIXME rendre configurable + + int interval = 5; + return interval; + } + /** * Display both message on UI (listeners and log). * @@ -106,21 +121,21 @@ control.setText(message); } } - + public SimulationStorage subProcessSimulate(SimulationControl control, File simulationZip) throws Exception { message(control, _("isisfish.message.simulation.prepare")); - + 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 java = System.getProperty("java.home") + File.separator + "bin" + + File.separator + "java"; String classpath = System.getProperty("java.class.path"); - if (classpath==null) { + if (classpath == null) { // could not find the jvm property (jnlp context for example) // rebuild the classpath as in {@link AspectClassLoader} String pathSep = File.pathSeparator; @@ -131,41 +146,43 @@ for (URL url : urlLoader.getURLs()) { buffer.append(pathSep).append(url.getPath()); } - classpath=buffer.substring(1); + classpath = buffer.substring(1); } else { //FIXME, should do as in {@link AspectClassLoader} - } + } } if (log.isDebugEnabled()) { log.debug("classpath to use : " + classpath); } // prepare le process - ProcessBuilder processBuilder = new ProcessBuilder( - java, "-classpath", classpath, - IsisFish.class.getName(), "--option", "launch.ui", "false", - "--simulateWithSimulation", simulationId, simulationZip.getAbsolutePath()); + ProcessBuilder processBuilder = new ProcessBuilder(java, "-classpath", + classpath, IsisFish.class.getName(), "--option", "launch.ui", + "false", "--simulateWithSimulation", simulationId, + simulationZip.getAbsolutePath()); processBuilder.redirectErrorStream(true); - + // demarrage du process Process process = processBuilder.start(); - if(log.isInfoEnabled()) { - log.info(_("SubProcess start: %s %s", process, processBuilder.command())); + if (log.isInfoEnabled()) { + log.info(_("SubProcess start: %s %s", process, processBuilder + .command())); } // prepare de thread de surveillance du process si control n'est pas null - Thread monitor = new SimulationCheckpointExternalProcessThread( - control, simulationId, process); + Thread monitor = new SimulationCheckpointExternalProcessThread(control, + simulationId, process); monitor.start(); // on attend que la simulation soit fini process.waitFor(); - - if(log.isInfoEnabled()) { + + if (log.isInfoEnabled()) { log.info("SubProcess finished"); } - + //finished = true; - SimulationStorage result = SimulationStorage.getSimulation(simulationId); + SimulationStorage result = SimulationStorage + .getSimulation(simulationId); return result; } @@ -178,17 +195,18 @@ * @author poussin */ protected class SimulationCheckpointExternalProcessThread extends Thread { // SimulationCheckpointThread - + protected SimulationControl control = null; protected String simulationId = 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, - String simulationId, Process process) { - if(log.isInfoEnabled()) { - log.info("Lancement du thread de surveillance des simulations externes"); + public SimulationCheckpointExternalProcessThread( + SimulationControl control, String simulationId, Process process) { + if (log.isInfoEnabled()) { + log + .info("Lancement du thread de surveillance des simulations externes"); } this.control = control; this.simulationId = simulationId; @@ -200,25 +218,26 @@ public void run() { InputStreamReader osr = new InputStreamReader(out); BufferedReader br = new BufferedReader(osr); - + //int sleepTime = 2000; - + // use tip available at // http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4 // for reading subprocess output - String line=null; + String line = null; try { while ((line = br.readLine()) != null) { // add reading line to logging output - if(log.isInfoEnabled()) { - log.info(SubProcessSimulationLauncher.this.toString() + ">" + line); + if (log.isInfoEnabled()) { + log.info(SubProcessSimulationLauncher.this.toString() + + ">" + line); } - + //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 - SimulationStorage.readControl(simulationId, control, "stop"); + //SimulationStorage.readControl(simulationId, control, "stop"); if (control.isStopSimulationRequest()) { // FIXME, un destroy du process est peut-etre un peu violent ? @@ -226,16 +245,48 @@ // passe artificiellement le control a fini control.stopSimulation(); } - + if (!control.isRunning()) { return; } } } catch (IOException e) { - if(log.isErrorEnabled()) { - log.error(_("isisfish.simulator.subprocess.readoutput.error"), e); + if (log.isErrorEnabled()) { + log.error(_("isisfish.simulator.subprocess.readoutput.error"), + e); } } } } + + /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#getSimulationStorage(fr.ifremer.isisfish.simulator.launcher.SimulationService, fr.ifremer.isisfish.simulator.SimulationControl) + */ + @Override + public SimulationStorage getSimulationStorage( + SimulationService simulationService, SimulationControl control) + throws RemoteException { + + String simulationId = control.getId(); + + // In sub process, simulation is locally stored + SimulationStorage result = SimulationStorage + .getSimulation(simulationId); + return result; + + } + + /* + * @see fr.ifremer.isisfish.simulator.launcher.SimulatorLauncher#updateControl(fr.ifremer.isisfish.simulator.launcher.SimulationService, fr.ifremer.isisfish.simulator.SimulationControl) + */ + @Override + public void updateControl(SimulationService simulationService, + SimulationControl control) throws RemoteException { + + String simulationId = control.getId(); + // 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 + SimulationStorage.readControl(simulationId, control, "stop"); + + } } Modified: isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties =================================================================== --- isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/resources/i18n/isis-fish-en_GB.properties 2009-02-17 11:43:37 UTC (rev 1819) @@ -19,7 +19,6 @@ Check\ state\ of\ local\ repository\:\ %s= Checkout\ pom.xml\ to\ %s= Command\ '%s'\ fail\ to\ execute= -Control\ thread\ interrupted= Could\ not\ found\ formule\ type\ %s\ autorised\ type\ are\ %s= Error\ during\ vcs\ initialisation= Error\ while\ uploading\ public\ key\ to\ remote\ serveur\ authorized_keys= Modified: isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties =================================================================== --- isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties 2009-02-17 11:42:34 UTC (rev 1818) +++ isis-fish/trunk/src/main/resources/i18n/isis-fish-fr_FR.properties 2009-02-17 11:43:37 UTC (rev 1819) @@ -19,7 +19,6 @@ Check\ state\ of\ local\ repository\:\ %s= Checkout\ pom.xml\ to\ %s= Command\ '%s'\ fail\ to\ execute= -Control\ thread\ interrupted= Could\ not\ found\ formule\ type\ %s\ autorised\ type\ are\ %s= Error\ during\ vcs\ initialisation= Error\ while\ uploading\ public\ key\ to\ remote\ serveur\ authorized_keys=
participants (1)
-
chatellier@users.labs.libre-entreprise.org