/// <summary> /// Add a value and version to the list, returning the prior value of the variable. /// </summary> /// <param name="version">for the value to add</param> /// <param name="value">to add</param> /// <param name="timestamp">the time associated with the version</param> /// <returns>prior value</returns> public Object AddValue(int version, T value, long timestamp) { if (ExecutionPathDebugLog.IsEnabled && Log.IsDebugEnabled) { Log.Debug(".addValue Thread " + Thread.CurrentThread.ManagedThreadId + " for '" + _name + "' adding version " + version + " at value " + value); } // push to prior if not already used if (_currentAndPriorValue.PriorVersion.Version == -1) { _currentAndPriorValue = new CurrentValue <T>(new VersionedValue <T>(version, value, timestamp), _currentAndPriorValue.CurrentVersion); return(_currentAndPriorValue.PriorVersion.Value); } // add to list VersionedValue <T> priorVersion = _currentAndPriorValue.PriorVersion; _olderVersions.Add(priorVersion); // check watermarks if (_olderVersions.Count >= _highWatermark) { long expireBefore = timestamp - _millisecondLifetimeOldVersions; while (_olderVersions.Count > 0) { VersionedValue <T> oldestVersion = _olderVersions[0]; if (oldestVersion.Timestamp <= expireBefore) { _olderVersions.RemoveAt(0); } else { break; } } } _currentAndPriorValue = new CurrentValue <T>(new VersionedValue <T>(version, value, timestamp), _currentAndPriorValue.CurrentVersion); return(_currentAndPriorValue.PriorVersion.Value); }
/// <summary> /// Retrieve a value for the given version or older then then given version. /// <para/> /// The implementaton only locks the read lock if an older version the the prior version is requested. /// </summary> /// <param name="versionAndOlder">the version we are looking for</param> /// <returns> /// value for the version or the next older version, ignoring newer versions /// </returns> public T GetVersion(int versionAndOlder) { if (ExecutionPathDebugLog.IsEnabled && Log.IsDebugEnabled) { Log.Debug(".GetVersion Thread " + Thread.CurrentThread.ManagedThreadId + " for '" + _name + "' retrieving version " + versionAndOlder + " or older"); } T resultValue = null; CurrentValue <T> current = _currentAndPriorValue; if (current.CurrentVersion.Version <= versionAndOlder) { resultValue = current.CurrentVersion.Value; } else if ((current.PriorVersion.Version != -1) && (current.PriorVersion.Version <= versionAndOlder)) { resultValue = current.PriorVersion.Value; } else { using (_readLock.Acquire()) { current = _currentAndPriorValue; if (current.CurrentVersion.Version <= versionAndOlder) { resultValue = current.CurrentVersion.Value; } else if ((current.PriorVersion.Version != -1) && (current.PriorVersion.Version <= versionAndOlder)) { resultValue = current.PriorVersion.Value; } else { bool found = false; for (int i = _olderVersions.Count - 1; i >= 0; i--) { VersionedValue <T> entry = _olderVersions[i]; if (entry.Version <= versionAndOlder) { resultValue = entry.Value; found = true; break; } } if (!found) { int currentVersion = current.CurrentVersion.Version; int priorVersion = current.PriorVersion.Version; int?oldestVersion = null; if (_olderVersions.Count > 0) { oldestVersion = _olderVersions[0].Version; } T oldestValue = (_olderVersions.Count > 0) ? _olderVersions[0].Value : null; String text = "Variables value for version '" + versionAndOlder + "' and older could not be found" + " (currentVersion=" + currentVersion + " priorVersion=" + priorVersion + " oldestVersion=" + oldestVersion + " numOldVersions=" + _olderVersions.Count + " oldestValue=" + oldestValue + ")"; if (_errorWhenNotFound) { throw new IllegalStateException(text); } Log.Warn(text); return(current.CurrentVersion.Value); } } } } if (ExecutionPathDebugLog.IsEnabled && Log.IsDebugEnabled) { Log.Debug(".getVersion Thread " + Thread.CurrentThread.ManagedThreadId + " for '" + _name + " version " + versionAndOlder + " or older result is " + resultValue); } return(resultValue); }