/** * Add given sample to buffer, performing a back-in-time check, updating the sample buffer error * state. * * @param value Value to archive * @return <code>false</code> if value failed back-in-time or future check, <code>true</code> if * value was added. */ protected final boolean addValueToBuffer(final VType value) { // Suppress samples that are too far in the future final Timestamp time = VTypeHelper.getTimestamp(value); if (isFuturistic(time)) { trouble_sample_log.log("'" + getName() + "': Futuristic " + value); return false; } synchronized (this) { if (last_archived_value != null && VTypeHelper.getTimestamp(last_archived_value).compareTo(time) >= 0) { // Cannot use this sample because of back-in-time problem. // Usually this is NOT an error: // We logged an initial sample, disconnected, disabled, ..., // and now we got an update from the IOC which still // carries the old, original time stamp of the PV, // and that's back in time... trouble_sample_log.log( getName() + " skips back-in-time:\n" + "last: " + VTypeHelper.toString(last_archived_value) + "\n" + "new : " + VTypeHelper.toString(value)); return false; } // else ... last_archived_value = value; } buffer.add(value); if (SampleBuffer.isInErrorState()) need_write_error_sample = true; return true; }
@Test public void testCSVImport() throws Exception { final InputStream input = getClass().getResourceAsStream("Lakeshore_A_9_2011.xml"); final SampleImporter importer = new CSVSampleImporter(); final List<VType> values = importer.importValues(input); assertTrue(values.size() > 0); for (VType value : values) System.out.println(VTypeHelper.toString(value)); final String text = VTypeHelper.toString(values.get(values.size() - 1)); assertThat(text, containsString("2011-09-13")); assertThat(text, containsString("08:57:44.968")); assertThat(text, containsString("84.912")); }
/** * Called for each value received from PV. * * <p>Base class remembers the <code>most_recent_value</code>, and asserts that one 'first' sample * is archived. Derived class <b>must</b> call <code>super()</code>. * * @param value Value received from PV * @return true if the value was already written because it's the first value after startup or * error, so there's no need to write that sample again. */ protected boolean handleNewValue(final VType value) { synchronized (this) { ++received_value_count; most_recent_value = value; } // NaN test if (value instanceof VNumber) { if (Double.isNaN(VTypeHelper.toDouble(value))) trouble_sample_log.log("'" + getName() + "': NaN " + VTypeHelper.toString(value)); } if (!enabled) return false; // Did we recover from write errors? if (need_write_error_sample && SampleBuffer.isInErrorState() == false) { need_write_error_sample = false; Activator.getLogger().log(Level.FINE, "Wrote error sample for {0}", getName()); addInfoToBuffer(ValueButcher.createWriteError()); need_first_sample = true; } // Is this the first sample after startup or an error? if (!need_first_sample) return false; need_first_sample = false; // Try to add as-is, but time stamp will be corrected to fit in final VType added = addInfoToBuffer(value); Activator.getLogger() .log(Level.FINE, "Wrote first sample for {0}: {1}", new Object[] {getName(), added}); return true; }
/** @return Last value written to archive */ public final synchronized String getLastArchivedValue() { return VTypeHelper.toString(last_archived_value); }
/** @return Most recent value of the channel's PV */ public final synchronized String getCurrentValue() { return VTypeHelper.toString(most_recent_value); }