diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingDecoder.java index 19d4739770..cac9de61d4 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingDecoder.java @@ -77,8 +77,7 @@ import com.raytheon.uf.edex.plugin.modelsounding.decoder.ModelSoundingDataAdapte * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Dec 02, 2013 2537 bsteffen Remove dead/deprecated code. * May 14, 2014 2536 bclement moved WMO Header to common - * - * + * Feb 09, 2015 4101 rjpeter Pass key to ModelSoundingStorageContainer. * * * @author jkorman @@ -200,7 +199,8 @@ public class ModelSoundingDecoder extends AbstractDecoder implements } container = new ModelSoundingStorageContainer( - PointDataContainer.build(pdd, PDC_SIZE)); + PointDataContainer.build(pdd, PDC_SIZE), + pdcKey); } else if (logger.isPriorityEnabled(Priority.DEBUG)) { logger.debug("Reusing Point Data Container: " + pdcKey); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java index d4a1554cd8..f74b7b1ab5 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java @@ -19,14 +19,21 @@ **/ package com.raytheon.uf.edex.plugin.modelsounding; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.util.ITimer; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.edex.core.EDEXUtil; import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.core.IContextStateProcessor; @@ -44,6 +51,7 @@ import com.raytheon.uf.edex.core.IContextStateProcessor; * ------------ ---------- ----------- -------------------------- * Jul 17, 2013 2161 bkowal Initial creation. * Mar 11, 2014 2726 rjpeter Graceful shutdown, don't forward empty pdo lists. + * Feb 09, 2015 4101 rjpeter Added MAX_CONTAINER_SIZE and changed store order to always store container with most entries first. * * * @author bkowal @@ -55,7 +63,12 @@ public class ModelSoundingPersistenceManager implements IContextStateProcessor { private final IUFStatusHandler logger = UFStatus .getHandler(ModelSoundingPersistenceManager.class); - private final LinkedHashMap containerMap; + private static final int MAX_CONTAINER_SIZE = Integer.getInteger( + "ModelSoundingPersistenceManager.maxSize", 500); + + private final Map containerMap; + + private final SortedSet sizeSet; private volatile boolean run = false; @@ -65,9 +78,19 @@ public class ModelSoundingPersistenceManager implements IContextStateProcessor { * */ public ModelSoundingPersistenceManager() { - // super("ModelSoundingStore"); - this.containerMap = new LinkedHashMap( + this.containerMap = new HashMap( 64, 1); + /* Sort descending by size */ + this.sizeSet = new TreeSet( + Collections + .reverseOrder(new Comparator() { + @Override + public int compare( + ModelSoundingStorageContainer o1, + ModelSoundingStorageContainer o2) { + return Integer.compare(o1.size(), o2.size()); + } + })); } public void run() { @@ -86,20 +109,22 @@ public class ModelSoundingPersistenceManager implements IContextStateProcessor { } } - Iterator iter = containerMap.keySet().iterator(); + /* + * Process container of next biggest size + */ + Iterator iter = sizeSet + .iterator(); if (iter.hasNext()) { - // remove first entry and process - String key = iter.next(); - container = containerMap.remove(key); - if (logger.isPriorityEnabled(Priority.DEBUG)) { - logger.debug("Persisting " - + container.getPdos().size() - + " PluginDataObject(s) for : " + key); - } + container = iter.next(); + iter.remove(); + String key = container.getKey(); + containerMap.remove(key); } } if (container != null) { + ITimer timer = TimeUtil.getTimer(); + timer.start(); List pdoList = container.getPdos(); if ((pdoList != null) && !pdoList.isEmpty()) { PluginDataObject[] pdos = pdoList @@ -107,9 +132,15 @@ public class ModelSoundingPersistenceManager implements IContextStateProcessor { try { EDEXUtil.getMessageProducer().sendSync( "modelSoundingPersistIndexAlert", pdos); + timer.stop(); + logger.info("Stored container: " + + container.getKey() + ", size: " + + container.size() + ", in " + + timer.getElapsedTime() + "ms"); } catch (EdexException e) { logger.error("Failed to persist " + pdos.length - + " PluginDataObject(s)!", e); + + " PluginDataObject(s) for key: " + + container.getKey(), e); } } } @@ -154,22 +185,33 @@ public class ModelSoundingPersistenceManager implements IContextStateProcessor { public void checkIn(String persistRecordKey, ModelSoundingStorageContainer container) { boolean storeLocal = true; - synchronized (containerMap) { - if (run) { - ModelSoundingStorageContainer prev = containerMap.put( - persistRecordKey, container); - storeLocal = false; - if (prev != null) { - // technically only possible in an environment where there - // are multiple decode threads running, just append the - // pdo's from the first, their pdc will not be used again - if (logger.isPriorityEnabled(Priority.DEBUG)) { - logger.debug("PDC for time already exists, appending previous PDC data"); - } - container.addPdos(prev.getPdos()); + /* + * Only allow further appending to container if its below max size + */ + int size = container.size(); + if ((size > 0) && (size < MAX_CONTAINER_SIZE)) { + synchronized (containerMap) { + if (run) { + ModelSoundingStorageContainer prev = containerMap.put( + persistRecordKey, container); + storeLocal = false; + if (prev != null) { + /* + * technically only possible in an environment where + * there are multiple decode threads running, just + * append the pdo's from the first, their pdc will not + * be used again + */ + if (logger.isPriorityEnabled(Priority.DEBUG)) { + logger.debug("PDC for time already exists, appending previous PDC data"); + } + + container.addPdos(prev.getPdos()); + } + sizeSet.add(container); + containerMap.notify(); } - containerMap.notify(); } } @@ -188,7 +230,12 @@ public class ModelSoundingPersistenceManager implements IContextStateProcessor { */ public ModelSoundingStorageContainer checkOut(String persistRecordKey) { synchronized (containerMap) { - return containerMap.remove(persistRecordKey); + ModelSoundingStorageContainer rval = containerMap + .remove(persistRecordKey); + if (rval != null) { + sizeSet.remove(rval); + } + return rval; } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingStorageContainer.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingStorageContainer.java index e8d783d253..9a0f08f8a4 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingStorageContainer.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingStorageContainer.java @@ -34,8 +34,8 @@ import com.raytheon.uf.common.pointdata.PointDataContainer; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jul 15, 2013 2161 bkowal Initial creation - * + * Jul 15, 2013 2161 bkowal Initial creation. + * Feb 09, 2013 4101 rjpeter Added key. * * * @author bkowal @@ -47,12 +47,15 @@ public class ModelSoundingStorageContainer { private final List pdos; + private final String key; + /** * */ - public ModelSoundingStorageContainer(PointDataContainer pdc) { + public ModelSoundingStorageContainer(PointDataContainer pdc, String key) { this.pdos = new LinkedList(); this.pdc = pdc; + this.key = key; } public PointDataContainer getPdc() { @@ -70,4 +73,12 @@ public class ModelSoundingStorageContainer { public void addPdos(List pdos) { this.pdos.addAll(pdos); } + + public String getKey() { + return this.key; + } + + public int size() { + return pdos.size(); + } } \ No newline at end of file