/** * 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; }
/** * 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; }
/** * Check a received value for basic problems before passing it on to the sample mechanism * * @param value Value as received from network layer * @return Value to be used for archive */ private VType checkReceivedValue(VType value) { if (value instanceof Time) { try { final Time time = (Time) value; // Invoke time.getTimestamp() to detect RuntimeError in VType 2013/11/01 if (time.isTimeValid() && time.getTimestamp() != null) return value; else { trouble_sample_log.log("'" + getName() + "': Invalid time stamp "); value = VTypeHelper.transformTimestamp(value, Timestamp.now()); } } catch (RuntimeException ex) { Logger.getLogger(getClass().getName()) .log(Level.WARNING, "'" + getName() + "': Exception getting time stamp", ex); value = VTypeHelper.transformTimestamp(value, Timestamp.now()); } } else trouble_sample_log.log("'" + getName() + "': Received no time information for " + value); return value; }