/// <summary> /// Writes new snapshot values to the tag. /// </summary> /// <param name="identity">The identity of the caller.</param> /// <param name="values"> /// The values to write. Values that are more recent than the current snapshot value of the /// tag will be passed into the tag's data filter to test if they should be forwarded to the /// historian archive. /// </param> /// <param name="cancellationToken">The cancellation token for the request.</param> /// <returns> /// A task that will return the write result. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="identity"/> is <see langword="null"/>.</exception> public async Task <WriteTagValuesResult> WriteSnapshotValues(ClaimsPrincipal identity, IEnumerable <TagValue> values, CancellationToken cancellationToken) { _historian.ThrowIfDisposed(); if (!this.CanWrite(identity)) { return(WriteTagValuesResult.CreateUnauthorizedResult()); } if (!values?.Any() ?? false) { return(WriteTagValuesResult.CreateEmptyResult()); } var stateSet = await GetStateSet(identity, cancellationToken).ConfigureAwait(false); var currentSnapshot = ReadSnapshotValue(identity); DateTime?earliestSampleTime = null; DateTime?latestSampleTime = null; var sampleCount = 0; var invalidSampleCount = 0; var valsToWrite = values == null ? (IEnumerable <TagValue>) new TagValue[0] : values.Where(x => x != null && (currentSnapshot == null || x.UtcSampleTime > currentSnapshot.UtcSampleTime)) .OrderBy(x => x.UtcSampleTime); foreach (var val in valsToWrite) { if (!this.TryValidateIncomingTagValue(val, stateSet, out var validatedValue)) { ++invalidSampleCount; continue; } UpdateSnapshotValue(validatedValue); ++sampleCount; if (!earliestSampleTime.HasValue) { earliestSampleTime = validatedValue.UtcSampleTime; } if (!latestSampleTime.HasValue || validatedValue.UtcSampleTime > latestSampleTime.Value) { latestSampleTime = validatedValue.UtcSampleTime; } } return(sampleCount == 0 ? invalidSampleCount > 0 ? new WriteTagValuesResult(false, 0, null, null, new[] { String.Format(CultureInfo.CurrentCulture, Resources.WriteTagValuesResult_InvalidValuesSpecified, invalidSampleCount) }) : new WriteTagValuesResult(false, 0, null, null, new[] { Resources.WriteTagValuesResult_NoValuesSpecified }) : new WriteTagValuesResult(true, sampleCount, earliestSampleTime, latestSampleTime, invalidSampleCount == 0 ? null : new[] { String.Format(CultureInfo.CurrentCulture, Resources.WriteTagValuesResult_InvalidValuesSpecified, invalidSampleCount) })); }
/// <summary> /// Inserts values into the historian archive. /// </summary> /// <param name="identity">The identity of the caller.</param> /// <param name="values">The values to insert.</param> /// <param name="cancellationToken">The cancellation token for the request.</param> /// <returns> /// A task that will return the write result. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="identity"/> is <see langword="null"/>.</exception> public async Task <WriteTagValuesResult> InsertArchiveValues(ClaimsPrincipal identity, IEnumerable <TagValue> values, CancellationToken cancellationToken) { _historian.ThrowIfDisposed(); if (!this.CanWrite(identity)) { return(WriteTagValuesResult.CreateUnauthorizedResult()); } if (!values?.Any() ?? false) { return(WriteTagValuesResult.CreateEmptyResult()); } return(await InsertArchiveValuesInternal(identity, values, null, true, cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Inserts values into the historian archive, optionally skipping value validation (e.g. if /// the insert is because of a value emitted from the compression filter). /// </summary> /// <param name="identity">The identity of the caller.</param> /// <param name="values">The values to insert.</param> /// <param name="nextArchiveCandidate">The current candidate for the next value to be inserted.</param> /// <param name="validate">Flags if the values should be validated before sending to the archive.</param> /// <param name="cancellationToken">The cancellation token for the request.</param> /// <returns> /// A task that will return the write result. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="identity"/> is <see langword="null"/>.</exception> private async Task <WriteTagValuesResult> InsertArchiveValuesInternal(ClaimsPrincipal identity, IEnumerable <TagValue> values, ArchiveCandidateValue nextArchiveCandidate, bool validate, CancellationToken cancellationToken) { if (!values?.Any() ?? false) { await InsertArchiveValues(null, nextArchiveCandidate, cancellationToken).ConfigureAwait(false); return(WriteTagValuesResult.CreateEmptyResult()); } var stateSet = await GetStateSet(identity, cancellationToken).ConfigureAwait(false); if (validate) { var vals = new List <TagValue>(); foreach (var value in values) { if (validate) { if (!this.TryValidateIncomingTagValue(value, stateSet, out var validatedValue)) { continue; } vals.Add(validatedValue); } } values = vals.ToArray(); } try { return(await InsertArchiveValues(values, nextArchiveCandidate, cancellationToken).ConfigureAwait(false)); } catch (Exception e) { return(new WriteTagValuesResult(false, 0, null, null, new[] { e.Message })); } }