コード例 #1
0
ファイル: RedisTagDefinition.cs プロジェクト: lulzzz/aika
        /// <summary>
        /// Enqueues the specified snapshot value for writing to Redis.
        /// </summary>
        /// <param name="tag">The tag that the value belongs to.</param>
        /// <param name="value">The value.</param>
        private static void EnqueueSnapshotValueSave(RedisTagDefinition tag, TagValue value)
        {
            // Enqueue the value.
            tag._pendingSnapshotWrites.Enqueue(value);

            // If a write task is already in progress, we'll just exit now.
            if (Interlocked.CompareExchange(ref tag._snapshotUpdateLock, 1, 0) != 0)
            {
                return;
            }

            tag._historian.RunBackgroundTask(async ct => {
                try {
                    do
                    {
                        while (tag._pendingSnapshotWrites.TryDequeue(out var val))
                        {
                            await tag.SaveSnapshotValueInternal(val, ct).ConfigureAwait(false);
                        }
                    } while (!tag._pendingSnapshotWrites.IsEmpty);
                }
                finally {
                    tag._snapshotUpdateLock = 0;
                }
            });
        }
コード例 #2
0
        /// <summary>
        /// Creates a new tag.
        /// </summary>
        /// <param name="identity">The identity of the caller.</param>
        /// <param name="tag">The tag definition.</param>
        /// <param name="cancellationToken">The cancellation token for the request.</param>
        /// <returns>
        /// The new tag definition.
        /// </returns>
        protected override async Task <TagDefinition> CreateTag(ClaimsPrincipal identity, TagSettings tag, CancellationToken cancellationToken)
        {
            var tagDefinition = await RedisTagDefinition.Create(this, tag, identity, cancellationToken).ConfigureAwait(false);

            _tags[tagDefinition.Id] = tagDefinition;

            return(tagDefinition);
        }
コード例 #3
0
ファイル: RedisTagDefinition.cs プロジェクト: lulzzz/aika
        /// <summary>
        /// Creates a new <see cref="RedisTagDefinition"/>.
        /// </summary>
        /// <param name="historian">The historian for the tag.</param>
        /// <param name="settings">The tag settings.</param>
        /// <param name="creator">The tag's creator.</param>
        /// <param name="cancellationToken">The cancellation token for the request.</param>
        /// <returns>
        /// A task that will create a new <see cref="RedisTagDefinition"/> and save it to the
        /// historian's Redis server.
        /// </returns>
        internal static async Task <RedisTagDefinition> Create(RedisHistorian historian, TagSettings settings, ClaimsPrincipal creator, CancellationToken cancellationToken)
        {
            var now    = DateTime.UtcNow;
            var result = new RedisTagDefinition(historian, null, settings, new TagMetadata(DateTime.UtcNow, creator?.Identity.Name), null, new[] { TagChangeHistoryEntry.Created(creator) });
            var key    = historian.GetKeyForTagIdsList();

            await Task.WhenAny(Task.WhenAll(result.Save(cancellationToken), historian.Connection.GetDatabase().ListRightPushAsync(key, result.Id)), Task.Delay(-1, cancellationToken)).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            return(result);
        }
コード例 #4
0
        /// <summary>
        /// Initializes the <see cref="RedisHistorian"/>.
        /// </summary>
        /// <param name="cancellationToken">A cancellation token that can be used to cancel initialization.</param>
        /// <returns>
        /// A task that will initialize the historian.
        /// </returns>
        protected override async Task Init(CancellationToken cancellationToken)
        {
            void onConnected(object sender, ConnectionFailedEventArgs args)
            {
                _logger?.LogInformation($"Redis connection established: {args.EndPoint} (Connection Type = {args.ConnectionType})");
                Properties[Resources.Properties_Connected] = Connection.IsConnected;
            };

            void onConnectionFailed(object sender, ConnectionFailedEventArgs args)
            {
                _logger?.LogError($"Redis connection failed: {args.EndPoint} (Connection Type = {args.ConnectionType}, Failure Type = {args.FailureType}).", args.Exception);
                Properties[Resources.Properties_Connected] = Connection.IsConnected;
            };

            try {
                _isInitializing = true;
                var configurationOptions = ConfigurationOptions.Parse(_redisSettings);
                configurationOptions.ClientName = "Aika";

                Connection = await ConnectionMultiplexer.ConnectAsync(configurationOptions).ConfigureAwait(false);

                Connection.ConnectionRestored += onConnected;
                Connection.ConnectionFailed   += onConnectionFailed;

                Properties[Resources.Properties_Connected] = Connection.IsConnected;

                // Load state sets first so that they are already loaded when we start loading tags.
                await RedisStateSet.LoadAll(this, stateSet => _stateSets[stateSet.Name] = stateSet, cancellationToken).ConfigureAwait(false);

                await RedisTagDefinition.LoadAll(this, tag => _tags[tag.Id] = tag, cancellationToken).ConfigureAwait(false);
            }
            catch {
                if (Connection != null)
                {
                    Connection.ConnectionRestored -= onConnected;
                    Connection.ConnectionFailed   -= onConnectionFailed;
                    Connection.Dispose();
                }
                throw;
            }
            finally {
                _isInitializing = false;
            }
        }
コード例 #5
0
ファイル: RedisTagDefinition.cs プロジェクト: lulzzz/aika
        /// <summary>
        /// Loads a tag definition from the Redis database.
        /// </summary>
        /// <param name="historian">The Redis historian to load the tag from.</param>
        /// <param name="tagId">The ID of the tag to load.</param>
        /// <param name="cancellationToken">The cancellation token for the request.</param>
        /// <returns>
        /// A task that will return the loaded tag definition.
        /// </returns>
        internal static async Task <RedisTagDefinition> Load(RedisHistorian historian, string tagId, CancellationToken cancellationToken)
        {
            var values = await historian.Connection.GetDatabase().HashGetAllAsync(historian.GetKeyForTagDefinition(tagId)).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            string      name        = null;
            string      description = null;
            string      units       = null;
            TagDataType dataType    = default(TagDataType);
            string      stateSet    = null;

            bool exceptionFilterEnabled = false;
            TagValueFilterDeviationType exceptionFilterLimitType = default(TagValueFilterDeviationType);
            double   exceptionFilterLimit      = 0;
            TimeSpan exceptionFilterWindowSize = default(TimeSpan);

            bool compressionFilterEnabled = false;
            TagValueFilterDeviationType compressionFilterLimitType = default(TagValueFilterDeviationType);
            double   compressionFilterLimit      = 0;
            TimeSpan compressionFilterWindowSize = default(TimeSpan);

            DateTime createdAt  = DateTime.MinValue;
            string   creator    = null;
            DateTime modifiedAt = DateTime.MinValue;
            string   modifiedBy = null;

            foreach (var item in values)
            {
                switch (item.Name.ToString())
                {
                case "NAME":
                    name = item.Value;
                    break;

                case "DESC":
                    description = item.Value;
                    break;

                case "UNITS":
                    units = item.Value;
                    break;

                case "TYPE":
                    dataType = (TagDataType)((int)item.Value);
                    break;

                case "SSET":
                    stateSet = item.Value;
                    break;

                case "EXC_ENABLED":
                    exceptionFilterEnabled = Convert.ToBoolean((int)item.Value);
                    break;

                case "EXC_LIMIT_TYPE":
                    exceptionFilterLimitType = (TagValueFilterDeviationType)((int)item.Value);
                    break;

                case "EXC_LIMIT":
                    exceptionFilterLimit = (double)item.Value;
                    break;

                case "EXC_WINDOW":
                    exceptionFilterWindowSize = TimeSpan.Parse(item.Value);
                    break;

                case "COM_ENABLED":
                    compressionFilterEnabled = Convert.ToBoolean((int)item.Value);
                    break;

                case "COM_LIMIT_TYPE":
                    compressionFilterLimitType = (TagValueFilterDeviationType)((int)item.Value);
                    break;

                case "COM_LIMIT":
                    compressionFilterLimit = (double)item.Value;
                    break;

                case "COM_WINDOW":
                    compressionFilterWindowSize = TimeSpan.Parse(item.Value);
                    break;

                case "MD_CREATEDAT":
                    createdAt = new DateTime((long)item.Value, DateTimeKind.Utc);
                    break;

                case "MD_CREATEDBY":
                    creator = item.Value;
                    break;

                case "MD_MODIFIEDAT":
                    modifiedAt = new DateTime((long)item.Value, DateTimeKind.Utc);
                    break;

                case "MD_MODIFIEDBY":
                    modifiedBy = item.Value;
                    break;
                }
            }

            if (String.IsNullOrWhiteSpace(name))
            {
                name = tagId;
            }

            var settings = new TagSettings()
            {
                Name                    = name,
                Description             = description,
                Units                   = units,
                DataType                = dataType,
                StateSet                = stateSet,
                ExceptionFilterSettings = new TagValueFilterSettingsUpdate()
                {
                    IsEnabled  = exceptionFilterEnabled,
                    LimitType  = exceptionFilterLimitType,
                    Limit      = exceptionFilterLimit,
                    WindowSize = exceptionFilterWindowSize
                },
                CompressionFilterSettings = new TagValueFilterSettingsUpdate()
                {
                    IsEnabled  = compressionFilterEnabled,
                    LimitType  = compressionFilterLimitType,
                    Limit      = compressionFilterLimit,
                    WindowSize = compressionFilterWindowSize
                }
            };

            var metadata = new TagMetadata(createdAt, creator, modifiedAt, modifiedBy);

            var snapshotTask         = LoadSnapshotValue(historian, tagId, cancellationToken);
            var lastArchivedTask     = LoadLastArchivedValue(historian, tagId, cancellationToken);
            var archiveCandidateTask = LoadArchiveCandidateValue(historian, tagId, cancellationToken);

            await Task.WhenAll(snapshotTask, lastArchivedTask, archiveCandidateTask).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            var initialValues = new InitialTagValues(snapshotTask.Result, lastArchivedTask.Result, archiveCandidateTask.Result.Value, archiveCandidateTask.Result.CompressionAngleMinimum, archiveCandidateTask.Result.CompressionAngleMaximum);

            var result = new RedisTagDefinition(historian,
                                                tagId,
                                                settings,
                                                metadata,
                                                initialValues,
                                                null);

            return(result);
        }