/// <summary> /// Creates a clone of the specified <see cref="TagSettings"/> object. /// </summary> /// <param name="other">The object to clone.</param> /// <exception cref="ArgumentNullException"><paramref name="other"/> is <see langword="null"/>.</exception> internal TagSettings(TagSettings other) : this() { if (other == null) { throw new ArgumentNullException(nameof(other)); } Name = other.Name; Description = other.Description; Units = other.Units; DataType = other.DataType; StateSet = other.StateSet; ExceptionFilterSettings = other.ExceptionFilterSettings == null ? null : new TagValueFilterSettingsUpdate() { IsEnabled = other.ExceptionFilterSettings.IsEnabled, LimitType = other.ExceptionFilterSettings.LimitType, Limit = other.ExceptionFilterSettings.Limit, WindowSize = other.ExceptionFilterSettings.WindowSize }; CompressionFilterSettings = other.CompressionFilterSettings == null ? null : new TagValueFilterSettingsUpdate() { IsEnabled = other.CompressionFilterSettings.IsEnabled, LimitType = other.CompressionFilterSettings.LimitType, Limit = other.CompressionFilterSettings.Limit, WindowSize = other.CompressionFilterSettings.WindowSize }; }
/// <summary> /// Updates the tag. /// </summary> /// <param name="update">The updated tag settings.</param> /// <param name="modifier">The tag's modifier.</param> /// <param name="description">The description of the update.</param> /// <returns> /// The new change history entry for the tag. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="update"/> is <see langword="null"/>.</exception> public virtual TagChangeHistoryEntry Update(TagSettings update, ClaimsPrincipal modifier, string description) { _historian.ThrowIfDisposed(); if (update == null) { throw new ArgumentNullException(nameof(update)); } if (!String.IsNullOrWhiteSpace(update.Name)) { Name = update.Name; } if (update.Description != null) { Description = update.Description; } if (update.Units != null) { Units = update.Units; } DataType = update.DataType; StateSet = update.StateSet; if (update.ExceptionFilterSettings != null) { DataFilter.ExceptionFilter.Settings.Update(update.ExceptionFilterSettings); } if (update.CompressionFilterSettings != null) { DataFilter.CompressionFilter.Settings.Update(update.CompressionFilterSettings); } var historyItem = TagChangeHistoryEntry.Updated(modifier, description); _changeHistory.Add(historyItem); Metadata.UtcLastModifiedAt = historyItem.UtcTime; Metadata.LastModifiedBy = historyItem.User; Updated?.Invoke(this); return(historyItem); }
/// <summary> /// Creates a new <see cref="TagDefinition"/> object. /// </summary> /// <param name="historian">The <see cref="IHistorian"/> instance that the tag belongs to.</param> /// <param name="id">The tag ID. If <see langword="null"/>, a new tag ID will ge generated automatically.</param> /// <param name="settings">The tag settings.</param> /// <param name="metadata">The tag metadata.</param> /// <param name="security">The tag security settings.</param> /// <param name="initialTagValues">The initial values to configure the tag's exception and compression filters with.</param> /// <param name="changeHistory">The change history for the tag.</param> /// <exception cref="ArgumentNullException"><paramref name="historian"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="settings"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="metadata"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="security"/> is <see langword="null"/>.</exception> /// <exception cref="ValidationException"><paramref name="settings"/> is not valid.</exception> protected TagDefinition(HistorianBase historian, string id, TagSettings settings, TagMetadata metadata, TagSecurity security, InitialTagValues initialTagValues, IEnumerable <TagChangeHistoryEntry> changeHistory) { _historian = historian ?? throw new ArgumentNullException(nameof(historian)); _historian.ThrowIfDisposed(); _logger = _historian.LoggerFactory?.CreateLogger <TagDefinition>(); if (settings == null) { throw new ArgumentNullException(nameof(settings)); } Validator.ValidateObject(settings, new ValidationContext(settings), true); Id = id ?? CreateTagId(); Name = settings.Name; Description = settings.Description; Units = settings.Units; DataType = settings.DataType; StateSet = settings.StateSet; Metadata = metadata ?? throw new ArgumentNullException(nameof(metadata)); Security = security ?? throw new ArgumentNullException(nameof(security)); var exceptionFilterSettings = settings.ExceptionFilterSettings?.ToTagValueFilterSettings() ?? new TagValueFilterSettings(false, TagValueFilterDeviationType.Absolute, 0, TimeSpan.FromDays(1)); var compressionFilterSettings = settings.CompressionFilterSettings?.ToTagValueFilterSettings() ?? new TagValueFilterSettings(false, TagValueFilterDeviationType.Absolute, 0, TimeSpan.FromDays(1)); if (changeHistory != null) { _changeHistory.AddRange(changeHistory); } _snapshotValue = initialTagValues?.SnapshotValue; DataFilter = new DataFilter(Name, new ExceptionFilterState(exceptionFilterSettings, _snapshotValue), new CompressionFilterState(compressionFilterSettings, initialTagValues?.LastArchivedValue, initialTagValues?.LastExceptionValue, initialTagValues?.CompressionAngleMinimum ?? Double.NaN, initialTagValues?.CompressionAngleMaximum ?? Double.NaN), _historian.LoggerFactory); DataFilter.Emit += (values, nextArchiveCandidate) => { if (values.Length > 0 && _logger.IsEnabled(LogLevel.Trace)) { _logger.LogTrace($"[{Name}] Archiving {values.Count()} values emitted by the compression filter."); } _pendingArchiveWrites.Enqueue(new PendingArchiveWrite() { ArchiveValues = values, NextArchiveCandidate = nextArchiveCandidate }); _historian.TaskRunner.RunBackgroundTask(async ct => { if (Interlocked.CompareExchange(ref _archiveLock, 1, 0) != 0) { return; } try { while (!ct.IsCancellationRequested && _pendingArchiveWrites.TryDequeue(out var item)) { await InsertArchiveValuesInternal(ClaimsPrincipal.Current, item.ArchiveValues, item.NextArchiveCandidate, false, ct).ConfigureAwait(false); } } catch (OperationCanceledException) { // App is shutting down... } catch (Exception e) { _logger?.LogError($"[{Name}] An error occurred while archiving values emitted by the compression filter.", e); } finally { _archiveLock = 0; } }); }; }