Added utility for truncating collected history data 29/1229/5
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Wed, 15 Nov 2017 13:21:38 +0000 (15:21 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Wed, 15 Nov 2017 14:47:57 +0000 (16:47 +0200)
The utility also supports an approximate truncation of the dynamic
CollectorState structure related to an active Collector instance.

refs #7622

Change-Id: I0041f26ca53250f3bed22f32de6c789f80a607c5

bundles/org.simantics.history/src/org/simantics/history/util/Stream.java
bundles/org.simantics.simulation/src/org/simantics/simulation/history/HistoryUtil.java

index dce3a6fc6e0941fff31590e0fd4346ce63cc7258..3366a1c26858751ef8017644b98efc28239847cc 100644 (file)
@@ -300,7 +300,16 @@ public class Stream {
                        throw new HistoryException(e);
                }
     }
-    
+
+       public Object getItemTime(Binding timeBinding, int index) throws HistoryException
+       {
+               try {
+                       return _getTime( accessor.get(index, sampleBinding), timeBinding );
+               } catch (AccessorException e) {
+                       throw new HistoryException( e );
+               }
+       }
+
     public Object getLowerTime(Binding timeBinding, Object time) throws HistoryException
     {
                try {
index 8b78fe18e50f203c13170986ce9f31045c844379..53a76d1360d783011320f451eb86838aa170d1bb 100644 (file)
@@ -12,9 +12,6 @@
  *******************************************************************************/
 package org.simantics.simulation.history;
 
-import gnu.trove.map.TObjectLongMap;
-import gnu.trove.map.hash.TObjectLongHashMap;
-
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -23,9 +20,6 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
-import net.jpountz.lz4.LZ4BlockInputStream;
-import net.jpountz.lz4.LZ4BlockOutputStream;
-
 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
 import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
@@ -41,6 +35,7 @@ import org.simantics.databoard.binding.RecordBinding;
 import org.simantics.databoard.binding.error.BindingConstructionException;
 import org.simantics.databoard.binding.error.BindingException;
 import org.simantics.databoard.binding.impl.ObjectArrayBinding;
+import org.simantics.databoard.binding.mutable.MutableVariant;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.databoard.container.DataContainer;
 import org.simantics.databoard.container.DataContainers;
@@ -57,9 +52,12 @@ import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ServiceNotFoundException;
 import org.simantics.db.request.Read;
 import org.simantics.fastlz.FastLZ;
+import org.simantics.history.Collector;
 import org.simantics.history.HistoryException;
 import org.simantics.history.HistoryManager;
 import org.simantics.history.ItemManager;
+import org.simantics.history.impl.CollectorState;
+import org.simantics.history.impl.CollectorState.VariableState;
 import org.simantics.history.util.Stream;
 import org.simantics.history.util.ValueBand;
 import org.simantics.layer0.Layer0;
@@ -68,6 +66,11 @@ import org.simantics.simulation.ontology.HistoryResource;
 import org.simantics.simulation.ontology.SimulationResource;
 import org.simantics.utils.FileUtils;
 
+import gnu.trove.map.TObjectLongMap;
+import gnu.trove.map.hash.TObjectLongHashMap;
+import net.jpountz.lz4.LZ4BlockInputStream;
+import net.jpountz.lz4.LZ4BlockOutputStream;
+
 /**
  * @author Toni Kalajainen
  * @author Tuukka Lehtonen
@@ -946,4 +949,78 @@ public class HistoryUtil {
                return 0L;
        }
 
+       public static void truncateHistory(double toBeforeTime, HistoryManager history, Collector collector) throws AccessorException, BindingException, HistoryException {
+               Double t = toBeforeTime;
+               Binding timeBinding = null;
+               CollectorState state = collector != null ? (CollectorState) collector.getState() : null;
+
+               Bean[] items = history.getItems();
+               //System.out.println("truncating all samples after t=" + toBeforeTime + " for " + items.length + " history items");
+
+               for (Bean item : items) {
+                       String id = (String) item.getField("id");
+                       StreamAccessor sa = history.openStream(id, "w");
+                       try {
+                               Stream s = new Stream(sa);
+                               timeBinding = s.timeBinding;
+                               int currentSize = sa.size();
+                               int index = s.binarySearch(timeBinding, toBeforeTime);
+                               int newSize = truncationSize(index);
+                               if (newSize < currentSize) {
+                                       //System.out.println("truncating item: " + item + " from size " + currentSize + " to " + newSize);
+                                       sa.setSize(newSize);
+
+                                       if (state != null) {
+                                               Object prevTime  = newSize > 0 ? s.getItemTime(s.timeBinding, newSize - 1) : null;
+                                               Object prevValue = newSize > 0 ? sa.get(newSize - 1, s.valueBinding) : null;
+                                               boolean isNan = isNaN(prevValue);
+
+                                               VariableState vs = state.values.get(id);
+                                               if (vs != null && vs.value != null && prevValue != null) {
+                                                       vs.value.setValue(vs.value.getBinding(), prevValue);
+                                                       vs.isValid = true;
+                                                       vs.isNan = isNan;
+                                               }
+
+                                               CollectorState.Item is = state.itemStates.get(id);
+                                               if (is != null) {
+                                                       is.firstTime = Double.NaN;
+                                                       is.firstValue = null;
+                                                       is.currentTime = toTime(prevTime);
+                                                       is.currentValue = prevValue != null ? new MutableVariant(s.valueBinding, prevValue) : null;
+                                                       is.isNaN = isNaN(is.currentValue);
+                                                       is.isValid = is.currentValue != null;
+                                                       is.sum = Double.NaN;
+                                                       is.count = 0;
+                                                       is.ooDeadband = false;
+                                                       is.firstDisabledTime = Double.NaN;
+                                                       is.lastDisabledTime = Double.NaN;
+                                                       is.median = null;
+                                               }
+                                       }
+                               }
+                       } finally {
+                               sa.close();
+                       }
+               }
+
+               if (timeBinding != null && state != null) {
+                       state.time.setValue(timeBinding, t);
+                       state.dT = 1.0;
+                       collector.setState(state);
+               }
+       }
+
+       private static double toTime(Object time) {
+               return time instanceof Number ? ((Number) time).doubleValue() : Double.NaN;
+       }
+
+       private static boolean isNaN(Object value) {
+               return value instanceof Number ? Double.isNaN(((Number) value).doubleValue()) : false;
+       }
+
+       private static int truncationSize(int binarySearchResult) {
+               return binarySearchResult >= 0 ? binarySearchResult + 1 : (-binarySearchResult - 1);
+       }
+
 }