Author: bpoussin Date: 2008-08-11 14:36:27 +0000 (Mon, 11 Aug 2008) New Revision: 1292 Added: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitorMultiThread.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/versionning/DummyVCSHandler.java Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisConfig.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisContext.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisFish.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/CodeSourceStorage.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/VersionStorage.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/logging/SimulationLoggerUtil.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitor.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java Log: debut de debbugage de la refonte du lanceur de simulation. - SimulationLogUtil ne semble pas multi-thread support (plusieurs simulation simultanement) - ajout d'un DummyVCSHandler si le reseau est unreacheable Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisConfig.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisConfig.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisConfig.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -44,16 +44,22 @@ protected final static VersionNumber version = new VersionNumber(3, 1, 4); protected final static VersionNumber databaseVersion = new VersionNumber( - version.getNumber(0), version.getNumber(1)); + 0); +// FIXME a remettre apres les tests de simu version.getNumber(0), version.getNumber(1)); + public static VersionNumber getVersionNumber() { + return version; + } + static public String getVERSION() { - String result = getVersion().toString(); + String result = version.toString(); return result; } - static public VersionNumber getVersion() { - return version; - } +// @Override +// public VersionNumber getVersion() { +// return version; +// } public static VersionNumber getDatabaseVersion() { return databaseVersion; Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisContext.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisContext.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisContext.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -21,6 +21,7 @@ import fr.ifremer.isisfish.commandline.IsisAbstractContext; import fr.ifremer.isisfish.commandline.IsisOptionParser; import fr.ifremer.isisfish.datastore.IsisH2Config; +import fr.ifremer.isisfish.versionning.DummyVCSHandler; import fr.ifremer.isisfish.versionning.IsisVcsConfig; import org.codelutin.i18n.I18n; import org.codelutin.option.OptionKey; @@ -209,6 +210,10 @@ } public VCSHandler getVCSHanler() { + if (handler == null) { + // handler not initializer, we used dummy handler + handler = new DummyVCSHandler(); + } return handler; } Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisFish.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisFish.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/IsisFish.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -105,7 +105,7 @@ StringBuilder builder = new StringBuilder(); builder.append(java.text.SimpleDateFormat.getInstance().format(new java.util.Date())); builder.append(" Java version: ").append(System.getProperty("java.runtime.version")); - builder.append(" Isis-fish version: ").append(IsisConfig.VERSION_PROPERTY_KEY.getDefaultValue().toString()); + builder.append(" Isis-fish version: ").append(IsisConfig.getVERSION()); log.info(builder.toString()); log.debug(_("isisfish.launch.debugMode")); Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/CodeSourceStorage.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/CodeSourceStorage.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/CodeSourceStorage.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -75,7 +75,7 @@ * @param directory le repertoire ou devrait se trouver la classe. Ce * répertoire doit etre un sous répertoire de rootSrc * @param name le nom de la classe - * @param suffix TODO + * @param suffix l'extension des fichiers */ protected CodeSourceStorage(File rootSrc, File directory, String name, String suffix) { // if name end with suffix we don't add suffix to filename Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/VersionStorage.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/VersionStorage.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/datastore/VersionStorage.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -42,6 +42,7 @@ import org.apache.commons.logging.LogFactory; import java.io.File; +import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -260,10 +261,15 @@ static public List<String> getStorageNames(File directory) { List<String> result = new ArrayList<String>(); - if (directory.exists()) { - Collections.addAll(result, directory.list(getVCSHanler().getVersionnableFilenameFilter())); + try { + if (directory.exists()) { + FilenameFilter filter = getVCSHanler().getVersionnableFilenameFilter(); + String[] list = directory.list(filter); + Collections.addAll(result, list); + } + } catch (Exception eee) { + log.error("Can't get list file for " + directory, eee); } - Collections.sort(result); return result; Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/logging/SimulationLoggerUtil.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/logging/SimulationLoggerUtil.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/logging/SimulationLoggerUtil.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -39,6 +39,10 @@ import java.util.Map; /** + * FIXME poussin, a priori cette classe ne supporte pas plusieurs simulation + * en meme temps, ce qui est le cas si on a plusieurs processeurs de dispo :( + * + * * Usefull class for dealing with hot configuration of log4J. this is temporary * we must find a way to abstract this layer. * <p/> Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitor.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitor.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitor.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -55,6 +55,13 @@ /** + * Classe permettant le suivi des populations de la simulation. + * + * FIXME: certain calcul sont les memes que ceux implanter dans les scripts + * a cause du groupe des juveniles qui n'est pas un vrai groupe de population. + * Il serait bon que ce groupe deviennent un vrai groupe et que ce code specifique + * puisse etre supprimer. + * * * @author poussin */ Added: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitorMultiThread.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitorMultiThread.java (rev 0) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/PopulationMonitorMultiThread.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -0,0 +1,399 @@ +/* *##% + * Copyright (C) 2006 + * Ifremer, Code Lutin, Cédric Pineau, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * PopulationMonitor.java + * + * Created: 21 août 2006 15:41:18 + * + * @author poussin + * @version $Revision: 428 $ + * + * Last update: $Date: 2007-10-15 14:56:13 +0200 (lun, 15 oct 2007) $ + * by : $Author: bpoussin $ + */ + +package fr.ifremer.isisfish.simulator; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.math.matrix.MatrixFactory; +import org.codelutin.math.matrix.MatrixIterator; +import org.codelutin.math.matrix.MatrixND; + +import fr.ifremer.isisfish.entities.Population; +import fr.ifremer.isisfish.entities.PopulationGroup; +import fr.ifremer.isisfish.entities.PopulationSeasonInfo; +import fr.ifremer.isisfish.entities.Species; +import fr.ifremer.isisfish.entities.Zone; +import fr.ifremer.isisfish.types.Date; +import fr.ifremer.isisfish.types.Month; +import java.util.Collections; + + +/** + * Classe permettant le suivi des populations de la simulation. + * <p> + * Cette classe est normalement multi-thread safe + * <p> + * FIXME: certain calcul sont les memes que ceux implanter dans les scripts + * a cause du groupe des juveniles qui n'est pas un vrai groupe de population. + * Il serait bon que ce groupe deviennent un vrai groupe et que ce code specifique + * puisse etre supprimer. + * + * + * @author poussin + */ +public class PopulationMonitorMultiThread { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(PopulationMonitorMultiThread.class); + + /** La liste des pops monitorer par cette instance */ + protected List<Population> pops = null; + /** current number of fish by Pop */ + protected Map<Population, MatrixND> Ns = new HashMap<Population, MatrixND>(); + /** reproduction key: <date, pop> value:<MatrixND> */ + protected Map<Population, Map<Date, MatrixND>> reproductions = new HashMap<Population, Map<Date, MatrixND>>(); + /** discard key: <date, pop> value:<MatrixND> */ + protected Map<Population, Map<Date, MatrixND>> discards = new HashMap<Population, Map<Date, MatrixND>>(); + /** catch per population, only last catch is remaining */ + protected Map<Population, MatrixND> catchs = new HashMap<Population, MatrixND>(); + /** catch per population, only last catch is remaining */ + protected Map<Population, MatrixND> holdCatchs = new HashMap<Population, MatrixND>(); + protected double totalHoldCatch = 0; + + /** + * Initialise le monitor pour l'ensemble de pop passe en parametre. + * Normalement cet init est fait dans le thread principale de la simulation + * et il n'y a pas de besoin de le synchroniser. + * + * Cet init permet d'avoir ensuite le maxime de variable en lecture, et donc + * de permettre le multithreading de facon legere (pas de synchronise) et + * sur (pas de concurent modification exception) + * + * @param pops + */ + public void init(List<Population> pops) { + this.pops = Collections.unmodifiableList(new ArrayList<Population>(pops)); + for (Population pop : this.pops) { + reproductions.put(pop, new HashMap<Date, MatrixND>()); + discards.put(pop, new HashMap<Date, MatrixND>()); + } + } + + /** + * Return all population actualy in PopulationMonitor + * @return new list of Population + */ + public List<Population> getPopulations() { + return pops; + } + + /** + * Return current biomass for species + * @param species + * @return + */ + public double getBiomass(Species species) { + double result = 0; + + for (Population pop : species.getPopulation()) { + result += getBiomass(pop); + } + + return result; + } + + /** + * Return current biomass for population + * @param pop + * @return + */ + public double getBiomass(Population pop) { + double result = 0; + + MatrixND n = getN(pop); + if (n != null) { + n = n.sumOverDim(1); + for (MatrixIterator i=n.iterator(); i.next();){ + Object [] coord = i.getSemanticsCoordinates(); + PopulationGroup group = (PopulationGroup)coord[0]; + result += i.getValue() * group.getMeanWeight(); + } + } + + return result; + } + + /** + * Return current numbers for population + * @param pop + * @return + */ + public MatrixND getN(Population pop) { + MatrixND result = Ns.get(pop); + + if (result != null) { + // change semantics with list from argument to ensure that + // semantics don't used too old context + result.setSemantics(0, pop.getPopulationGroup()); + result.setSemantics(1, pop.getPopulationZone()); + } + + return result; + } + + public void setN(Population pop, MatrixND mat) { + Ns.put(pop, mat); + } + + /** + * @return Returns the reproduction. + */ + public MatrixND getReproduction(Date date, Population pop) { + return this.reproductions.get(pop).get(date); + } + + /** + * @param reproduction The reproduction to set. + */ + public void setReproduction(Date date, Population pop, MatrixND repro) { + reproductions.get(pop).put(date, repro); + } + + /** + * Applique de la mortalite naturelle aux poissons qui sont pas encore + * dans les classes de populations. (Reproduction) + * @param pop + */ + public void applyReproductionMortality(Population pop) { + for (MatrixND reproduction : reproductions.get(pop).values()) { + if (log.isTraceEnabled()) { + log.trace("Matrix repro before mortality: " + reproduction); + } + + for (MatrixIterator mi = reproduction.iterator(); mi.next();) { + Object[] sems = mi.getSemanticsCoordinates(); + Zone z = (Zone) sems[0]; + double coeff = pop.getNaturalDeathBirth(z); + if (log.isTraceEnabled()) { + log.trace("NaturalDeath zone " + z + "=" + coeff); + } + mi.setValue(mi.getValue() * Math.exp(-coeff / Month.NUMBER_OF_MONTH)); + } + if (log.isTraceEnabled()) { + log.trace("Matrix repro after mortality: " + reproduction); + } + } + } + + /** + * @todo les reproductions qui sont trop veille pour encore servir + * doivent être supprimées. c-a-d date < currentDate - etalement - gap between repro recru + * Une autre facon de faire est de supprimer les repro == 0 car normalement + * toute la repro doit etre utilisé au bout d'un certain temps + * + * @param date + * @param pop + * @return + */ + public MatrixND getRecruitment(Date date, Population pop) { + MatrixND matEtalement = pop.getRecruitmentDistribution(); + int etalement = matEtalement.getDim(0); + + MatrixND result = MatrixFactory.getInstance().create( + new List[]{pop.getPopulationGroup(), pop.getPopulationZone()}); + + // pour chaque + for(int e=0; e<etalement; e++){ + // recuperation de la reproduction stucture en zone repro + Date d = new Date(date.getDate() - e - + pop.getMonthGapBetweenReproRecrutement()); + MatrixND repro = (MatrixND)reproductions.get(pop).get(d); + + if(repro != null){ // si une repro existe pour le mois + + // on fait la correspondance entre les zones repro et + // recrutement + + PopulationGroup classe; + int indiceClasse = 0; + // si on a change d'annee le recrutement ne se fait pas en + // classe 0 mais en classe 1, si on a change 2 fois d'annee + // le recrutement se fait en age 2, etc. + classe = pop.getPopulationGroup().get(indiceClasse); + + List<Zone> zoneRepros = pop.getReproductionZone(); + + // on multiplie la repro par le coeff de recrutement + double coeff = matEtalement.getValue(e); + + MatrixND matRepro = repro.copy(); + matRepro = matRepro.mults(coeff); + + matRepro.setSemantics(0, zoneRepros); + + MatrixND mapping = pop.getMappingZoneReproZoneRecru(); + for(Zone zoneRepro : zoneRepros){ + MatrixND submapping = mapping.getSubMatrix(0, new Object[]{zoneRepro}); + for (MatrixIterator i=submapping.iterator(); i.hasNext();) { + i.next(); + Object[] sem = i.getSemanticsCoordinates(); + Zone zoneRecru = (Zone)sem[1]; + double c = i.getValue(); + result.setValue(classe, zoneRecru, c*matRepro.getValue(zoneRepro) + +result.getValue(classe, zoneRecru)); + } + } + } + } + + if(pop.getSpecies().getAgeGroupType()){ + // conversion et retour de la matrice en vecteur + MatrixND N = pop.N2DToN1D(result); + // on applique les migrations et le changement d'age sur le resultat + // on suppose que la reproduction est toujours dans une seul saison + Date dateRepro = new Date(date.getDate() - + pop.getMonthGapBetweenReproRecrutement()); + + // recherche les saisons des differents mois entre les deux dates + List<PopulationSeasonInfo> infos = pop.getPopulationSeasonInfo(); + List<PopulationSeasonInfo> usedSeasons = new ArrayList<PopulationSeasonInfo>(); + + while (date.after(dateRepro)) { + dateRepro = dateRepro.next(); + Month month = dateRepro.getMonth(); + for (PopulationSeasonInfo info : infos) { + if (month.equals(info.getFirstMonth())) { + usedSeasons.add(info); + dateRepro = new Date(dateRepro.getDate() + info.getMonths().size() - 1); // -1 because, for have next() + break; + } + } + } + + for(PopulationSeasonInfo info : usedSeasons){ + Month month = info.getFirstMonth(); + MatrixND CA = info.getGroupChangeMatrix(month); + MatrixND MI = info.getMigrationMatrix(month, result); + MatrixND tmp0 = N.mult(CA); + MatrixND tmp2 = tmp0.mult(MI); + N = tmp2; + } + result = pop.split2D(N); + } + return result; + } + + /** + * @param catchPerStrategyMet + */ + public void holdCatch(Population pop, MatrixND catchPerStrategyMet) { + catchs.put(pop, catchPerStrategyMet); + + MatrixND holdCatch = holdCatchs.get(pop); + if (holdCatch == null) { + holdCatch = MatrixFactory.getInstance().create(catchPerStrategyMet); + holdCatchs.put(pop, holdCatch); + } else { + holdCatch.add(catchPerStrategyMet); + } + + // compute total + for(MatrixIterator i=catchPerStrategyMet.iterator(); i.next();){ + this.totalHoldCatch += i.getValue(); + } + + } + + /** + * @param pop + * @return + */ + public MatrixND getCatch(Population pop) { + MatrixND result = catchs.get(pop); + return result; + } + + /** + * @param pop + * @return + */ + public MatrixND getHoldCatch(Population pop) { + MatrixND result = holdCatchs.get(pop); + return result; + } + + /** + * @param pop + * @return + */ + public double getTotalHoldCatch(Population pop) { + double result = totalHoldCatch; + return result; + } + + /** + * raz capture cumulée de toutes les pops + */ + public void clearCatch() { + catchs.clear(); + holdCatchs.clear(); + totalHoldCatch = 0; + } + + /** + * @param date + * @param pop + * @return + */ + public MatrixND getDiscard(Date date, Population pop) { + MatrixND result = discards.get(pop).get(date); + return result; + } + + /** + * FIXME: discards n'est jamais vider, on le conserve pour toutes les annees + * il serait bon de faire un peu le menage de temps en temps. + * + * @param date + * @param pop + * @param discard + */ + public void addDiscard(Date date, Population pop, MatrixND discard) { + Map<Date, MatrixND> oneDiscard = discards.get(pop); + synchronized(oneDiscard) { + MatrixND tmp = oneDiscard.get(date); + if (tmp == null) { + tmp = discard.copy(); + discards.get(pop).put(date, tmp); + } else { + tmp.add(discard); + } + } + } +} + + Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationHelper.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -30,6 +30,8 @@ package fr.ifremer.isisfish.simulator; +import java.util.logging.Level; +import java.util.logging.Logger; import static org.codelutin.i18n.I18n._; import java.io.File; @@ -291,22 +293,20 @@ */ static public void simulate(String simulId, SimulationParameter param, boolean inQueue) throws SimulationException { - // Ajout automatiquement de la date+heure a la fin de l'identifiant - // comme demandé par Steph 20070227 - simulId += " " + dateFormat.format(new java.util.Date()); + try { + simulId += " " + dateFormat.format(new java.util.Date()); - if (simulId == null || - "".equals(simulId) || - SimulationStorage.localyExists(simulId) || - SimulationManager.getInstance().exists(simulId)) { - log.error("Can't start simulation, bad id: " + simulId); - throw new SimulationException(_("isisfish.error.start" + - " simulation, bad id: {0}", "" + simulId)); + if (simulId == null || "".equals(simulId) || SimulationStorage.localyExists(simulId) || SimulationManager.getInstance().exists(simulId)) { + log.error("Can't start simulation, bad id: " + simulId); + throw new SimulationException(_("isisfish.error.start" + " simulation, bad id: {0}", "" + simulId)); + } + SimulationParameter p = param.copy(); + p.setInQueue(inQueue); + + SimulationManager.getInstance().addSimulation(simulId, p); + } catch (Exception eee) { + throw new SimulationException("Can't add simulation", eee); } - SimulationParameter p = param.copy(); - p.setInQueue(inQueue); - - SimulationManager.getInstance().addSimulation(simulId, p); } static public SimulationStorage simulate(SimulationControl control, SimulationStorage simulation) throws Exception { Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationManager.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -36,9 +36,11 @@ import fr.ifremer.isisfish.datastore.SimulationStorage; import fr.ifremer.isisfish.types.Date; import java.beans.PropertyChangeEvent; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import static org.codelutin.i18n.I18n._; +import static org.codelutin.i18n.I18nf._; import org.codelutin.util.FileUtil; import org.codelutin.util.ListenerSet; @@ -46,16 +48,11 @@ import java.beans.PropertyChangeSupport; import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.PriorityBlockingQueue; /** @@ -118,7 +115,8 @@ // TODO passer ces valeurs en valeur configurable int cpus = Runtime.getRuntime().availableProcessors(); int MAX_REMOTE_SIMULATION = 1; - + log.info(_("Launch Simulation executor with %s cpu(s) for local, and %s" + + " process for remote", cpus, MAX_REMOTE_SIMULATION)); localExecutor = Executors.newFixedThreadPool(cpus); remoteExecutor = Executors.newFixedThreadPool(MAX_REMOTE_SIMULATION); } @@ -173,26 +171,26 @@ log.debug(_("isisfish.message.add.queue.remote", id)); } + + // on construit le bon type de SimulationItem pour le job SimulationItem item = null; if (param.getUseAnalysePlan()) { if (!param.isIndependentPlan()) { item = new SimulationItemPlan(id, param); + executor.submit(new SimulationJob(this, item)); } else { + // on met dans la queue local le process de generation de toutes + // les simus item = new SimulationItemPlanIndependent(id, param); - // l'item est independant, on ajoute toutes ces simulations en plus - // mais pas dans la map pour qu'il n'y ait bien que l'initiale - // plus celles en cours d'affichees - while(item.hasNext()) { - executor.submit(new SimulationJob(this, item.next())); - } + localExecutor.submit( + new PrepareIndependentSimulationJob(this, executor, item)); } } else { item = new SimulationItem(id, param); + executor.submit(new SimulationJob(this, item)); } fireAddEvent(id, item); // must be before thread notification because thread look in map - - executor.submit(new SimulationJob(this, item)); } /** @@ -619,10 +617,40 @@ // // } + class PrepareIndependentSimulationJob implements Runnable { + + protected SimulationManager simulationManager; + protected ExecutorService executor; + protected SimulationItem item; + + public PrepareIndependentSimulationJob(SimulationManager simulationManager, + ExecutorService executor, + SimulationItem item) { + this.simulationManager = simulationManager; + this.executor = executor; + this.item = item; + } + + public void run() { + // l'item est independant, on ajoute toutes ces simulations en plus + // mais pas dans la map pour qu'il n'y ait bien que l'initiale + // plus celles en cours d'affichees + while (item.hasNext()) { + try { + executor.submit(new SimulationJob(simulationManager, item.next())); + } catch (Exception eee) { + log.error("Can't add simulation: " + item, eee); + } + } + + } + + } + /** * Utilise pour les simulations sans plan d'analyse ou des plans independant */ - static class SimulationJob implements Runnable { + class SimulationJob implements Runnable { protected SimulationManager simulationManager; protected SimulationItem simItem; @@ -739,6 +767,7 @@ * Une simulation a faire sans plan d'experience */ public class SimulationItem { + protected String id; protected SimulationParameter param; protected SimulationItemPlan planItem = null; @@ -877,7 +906,8 @@ /** * Une simulation a faire qui contient un plan d'experience dependant */ - public class SimulationItemPlan extends SimulationItem implements PropertyChangeListener { + public class SimulationItemPlan extends SimulationItem + implements PropertyChangeListener { // FIXME a mettre en config MAX_SIMULATION_PLAN // nombre maximal de simulation de plan par simulation // (pour eviter les plans qui ne retroune jamais faux @@ -971,12 +1001,26 @@ } public void propertyChange(PropertyChangeEvent evt) { + // Attention il faut bien que toutes les simultions soit + // genere (ou qu'il en reste au moins une en cours + // sinon, la condition est tout de suite vrai et la simulation + // s'arrete. Ce qui est normalement le cas ici, car on utilise + // le meme executor pour genere les simultions que pour les faire + // et les generes est mis en premier dans l'executor, mais si + // on est multi cpu, et que le temps de simulation est inferieur + // au temps de generation des simulations, on pourrai finir par + // avoir un probleme. + if (Boolean.FALSE.equals(evt.getNewValue())) { simulationFinished++; control.setProgress(simulationFinished); control.setText(simulationFinished + " / " + simulationNumber); if (simulationFinished >= simulationNumber) { + log.info("All simulations have been executed: " + simulationFinished); control.stopSimulation(); + String id = control.getId(); + SimulationManager.this.fireStopEvent(id); + SimulationManager.this.fireRemoveEvent(id); } } } Modified: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java 2008-08-07 19:38:45 UTC (rev 1291) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/simulator/SimulationQueueModel.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -73,7 +73,11 @@ int row = getRowCount(); fireTableRowsInserted(row, row); SimulationControl control = getSimulationControl(e.getId()); - control.addPropertyChangeListener(this); + if (control != null) { + control.addPropertyChangeListener(this); + } else { + log.warn("Simulation without controler: " + e.getId()); + } } /* (non-Javadoc) Added: branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/versionning/DummyVCSHandler.java =================================================================== --- branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/versionning/DummyVCSHandler.java (rev 0) +++ branches/isis-fish-3.1.4/src/java/fr/ifremer/isisfish/versionning/DummyVCSHandler.java 2008-08-11 14:36:27 UTC (rev 1292) @@ -0,0 +1,209 @@ +/* *##% + * Copyright (C) 2002-2008 Code Lutin, Benjamin Poussin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + *##%*/ + +package fr.ifremer.isisfish.versionning; + + +import java.io.File; +import java.io.FileFilter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.vcs.VCSConfig; +import org.codelutin.vcs.VCSException; +import org.codelutin.vcs.VCSHandler; +import org.codelutin.vcs.VCSState; + +/** + * Class utilisee lorsqu'aucun handler n'a ete initialise + * + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class DummyVCSHandler implements VCSHandler { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(DummyVCSHandler.class); + + protected final FilenameFilter versionnableFilenameFilter; + protected final FileFilter versionnableFileFilter; + + public DummyVCSHandler() { + this.versionnableFilenameFilter = new FilenameFilter() { + public boolean accept(File dir, String name) { + return !".svn".equals(name) && !"CVS".equals(name); + } + }; + this.versionnableFileFilter = new FileFilter() { + public boolean accept(File dir) { + return !".svn".equals(dir.getName()) && !"CVS".equals(dir.getName()); + } + }; +} + + + + public File getLocalDatabasePath() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void initWorkingCopy() throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void reinitWorkingCopy() throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void deleteWorkingCopy() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getRemoteUrl() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public VCSConfig getConfig() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public FilenameFilter getVersionnableFilenameFilter() { + return versionnableFilenameFilter; + } + + public FileFilter getVersionnableFileFilter() { + return versionnableFileFilter; + } + + public String getConfLocalDirname() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getConfLocalEntriesFilename() { + throw new UnsupportedOperationException("Not supported yet."); + } + + public VCSState getState(File fileState, Collection tmp) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public VCSState getState(File file, Collection tmp, boolean noremote) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean isOnRemote(File file) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean isUpToDate(File file) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public boolean isVersionnableFile(File file) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void makeRemoteDir(String commitMessage, String... dirNames) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void deleteRemoteDir(String commitMessage, String... dirNames) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public long add(List<File> files, String msg) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void delete(List<File> files, String msg) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void revert(List<File> files) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public long commit(List<File> files, String msg) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void update(File file, Object revision) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void update(File file) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void checkout(File destDir, String module, boolean recurse) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void checkoutFile(File destDir, String module) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public long checkoutOnlyTheDirectory(File root, Object revision) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public List<String> getRemoteStorageNames(File directory) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public List<String> getLocalStorageNames(File directory) { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object getRevision(File f) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public List getLog(Object startRevision, Object endRevision, File file) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getFileContent(File file, Object revision) throws VCSException, IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getChangeLog(File file) throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getDiff(File file) throws VCSException, IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public String getDiff(File file, Object againstRevision) throws VCSException, IOException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public void testConnection() throws VCSException { + throw new UnsupportedOperationException("Not supported yet."); + } + +}