コード例 #1
0
ファイル: ExtendedBuffer.cs プロジェクト: Apollo3zehn/Nexus
        public ExtendedBuffer(int length) : base(length)
        {
            _buffer = MemoryPool <T> .Shared.Rent(length);

            MemoryMarshal.AsBytes(_buffer.Memory.Span).Fill(0);

            this.ElementSize = NexusUtilities.SizeOf(typeof(T));
        }
コード例 #2
0
        public static double[] ApplyDatasetStatus2(Array dataset, byte[] status)
        {
            var methodName  = nameof(BufferUtilities.ForwardApplyDatasetStatus);
            var flags       = BindingFlags.NonPublic | BindingFlags.Static;
            var genericType = dataset.GetType().GetElementType();
            var parameters  = new object[] { dataset, status };

            var result = NexusUtilities.InvokeGenericMethod(typeof(BufferUtilities), null, methodName, flags, genericType, parameters);

            return((double[])result);
        }
コード例 #3
0
        public void Validate()
        {
            Contract.Requires(this.ProductVersion != null);

            string errorMessage;

            if (!NexusUtilities.CheckNamingConvention(this.Id, out errorMessage))
            {
                throw new Exception($"The ID is invalid: { errorMessage }");
            }
        }
コード例 #4
0
        public long GetByteCount()
        {
            var totalDays = (this.DateTimeEnd - this.DateTimeBegin).TotalDays;
            var frequency = string.IsNullOrWhiteSpace(this.SampleRate) ? 0 : new SampleRateContainer(this.SampleRate).SamplesPerDay;

            return((long)this.GetSelectedDatasets().Sum(dataset =>
            {
                var elementSize = NexusUtilities.SizeOf(dataset.DataType);

                return frequency * totalDays * elementSize;
            }));
        }
コード例 #5
0
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var name = value as string;

            if (NexusUtilities.CheckNamingConvention(name, out var errorDescription))
            {
                return(ValidationResult.Success);
            }
            else
            {
                return(new ValidationResult(errorDescription));
            }
        }
コード例 #6
0
        public DataWriterContext(string systemName, string dataDirectoryPath, NexusProjectDescription projectDescription, IList <CustomMetadataEntry> customMetadataEntrySet)
        {
            Contract.Requires(customMetadataEntrySet != null);

            customMetadataEntrySet.ToList().ForEach(customMetaDataEntry =>
            {
                if (!NexusUtilities.CheckNamingConvention(customMetaDataEntry.Key, out errorDescription))
                {
                    throw new ArgumentException($"Argument '{ nameof(customMetadataEntrySet) }', value '{ customMetaDataEntry.Key }': { errorDescription }");
                }
            });

            this.SystemName             = systemName;
            this.DataDirectoryPath      = dataDirectoryPath;
            this.ProjectDescription     = projectDescription;
            this.CustomMetadataEntrySet = customMetadataEntrySet;
        }
コード例 #7
0
        public DataReaderDoubleStream ReadAsDoubleStream(
            DatasetInfo dataset,
            DateTime begin,
            DateTime end,
            ulong upperBlockSize,
            CancellationToken cancellationToken)
        {
            var progressRecords = this.Read(new List <DatasetInfo>()
            {
                dataset
            }, begin, end, upperBlockSize, TimeSpan.FromMinutes(1), cancellationToken);
            var samplesPerSecond = new SampleRateContainer(dataset.Id).SamplesPerSecond;
            var length           = (long)Math.Round(samplesPerSecond *
                                                    (decimal)(end - begin).TotalSeconds, MidpointRounding.AwayFromZero) *
                                   NexusUtilities.SizeOf(NexusDataType.FLOAT64);

            return(new DataReaderDoubleStream(length, progressRecords));
        }
コード例 #8
0
        public void Validate()
        {
            string errorMessage;

            if (this.Version < 0)
            {
                throw new Exception(ErrorMessage.NexusProjectDescription_InvalidVersion);
            }

            if (!NexusUtilities.CheckNamingConvention(this.PrimaryGroupName, out errorMessage))
            {
                throw new Exception($"The PrimaryGroupName is invalid: { errorMessage }");
            }

            if (!NexusUtilities.CheckNamingConvention(this.SecondaryGroupName, out errorMessage))
            {
                throw new Exception($"The SecondaryGroupName is invalid: { errorMessage }");
            }

            if (!NexusUtilities.CheckNamingConvention(this.ProjectName, out errorMessage))
            {
                throw new Exception($"The ProjectName is invalid: { errorMessage }");
            }
        }
コード例 #9
0
        public static IExtendedBuffer CreateExtendedBuffer(NexusDataType dataType, int length)
        {
            var type = typeof(ExtendedBuffer <>).MakeGenericType(new Type[] { NexusUtilities.GetTypeFromNexusDataType(dataType) });

            return((IExtendedBuffer)Activator.CreateInstance(type, length));
        }
コード例 #10
0
        private void AggregateProject(ClaimsPrincipal user,
                                      string databaseFolderPath,
                                      string projectId,
                                      DateTime date,
                                      AggregationSetup setup,
                                      AggregationInstruction instruction,
                                      CancellationToken cancellationToken)
        {
            foreach (var(registration, aggregationChannels) in instruction.DataReaderToAggregationsMap)
            {
                using var dataReader = _databaseManager.GetDataReader(user, registration);

                // find reader configurations
                foreach (var configuration in setup.ReaderConfigurations
                         .Where(configuration => configuration.ProjectId == projectId))
                {
                    var tmpRegistration = new DataReaderRegistration()
                    {
                        RootPath     = configuration.DataReaderRootPath,
                        DataReaderId = configuration.DataReaderId
                    };

                    if (dataReader.Registration.Equals(tmpRegistration))
                    {
                        dataReader.OptionalParameters = configuration.Parameters;
                        break;
                    }
                }

                // get files
                if (!dataReader.IsDataOfDayAvailable(projectId, date))
                {
                    return;
                }

                // project
                var container = _databaseManager.Database.ProjectContainers.FirstOrDefault(container => container.Id == projectId);

                if (container == null)
                {
                    throw new Exception($"The requested project '{projectId}' could not be found.");
                }

                var targetDirectoryPath = Path.Combine(databaseFolderPath, "DATA", WebUtility.UrlEncode(container.Id), date.ToString("yyyy-MM"), date.ToString("dd"));

                // for each channel
                foreach (var aggregationChannel in aggregationChannels)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    try
                    {
                        var dataset = aggregationChannel.Channel.Datasets.First();

                        NexusUtilities.InvokeGenericMethod(this, nameof(this.OrchestrateAggregation),
                                                           BindingFlags.Instance | BindingFlags.NonPublic,
                                                           NexusUtilities.GetTypeFromNexusDataType(dataset.DataType),
                                                           new object[]
                        {
                            targetDirectoryPath,
                            dataReader,
                            dataset,
                            aggregationChannel.Aggregations,
                            date,
                            setup.Force,
                            cancellationToken
                        });
                    }
                    catch (TaskCanceledException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex.GetFullMessage());
                    }
                }
            }
        }
コード例 #11
0
        private RenderFragment CreateComponent() => builder =>
        {
            var properties = this.DataContext.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            var sequence = 0; // Autoincrement is not recommended for performance reasons (https://docs.microsoft.com/en-us/aspnet/core/blazor/advanced-scenarios?view=aspnetcore-5.0#the-problem-with-generating-sequence-numbers-programmatically)

            builder.OpenElement(sequence++, "div");
            builder.AddAttribute(sequence++, "class", "form-generator");

            foreach (var property in properties)
            {
                builder.OpenElement(sequence++, "div");
                builder.AddAttribute(sequence++, "class", "form-generator-property");

                var type       = this.DataContext.GetType();
                var constant   = Expression.Constant(this.DataContext, type);
                var expression = MemberExpression.Property(constant, property.Name);
                var value      = property.GetValue(this.DataContext);

                if (property.PropertyType == typeof(string))
                {
                    builder.OpenComponent(sequence++, typeof(MatTextField <string>));
                    builder.AddAttribute(sequence++, "Value", value);

                    builder.AddAttribute(sequence++, "ValueChanged",
                                         EventCallback.Factory.Create <string>(this, value =>
                    {
                        property.SetValue(this.DataContext, value);
                        this.OnChanged();
                    }));

                    builder.AddAttribute(sequence++, "Label", property.Name);
                    builder.CloseComponent();
                }
                else if (property.PropertyType == typeof(bool))
                {
                    builder.OpenComponent(sequence++, typeof(MatCheckbox <bool>));
                    builder.AddAttribute(sequence++, "Value", value);

                    builder.AddAttribute(sequence++, "ValueChanged",
                                         EventCallback.Factory.Create <bool>(this, value =>
                    {
                        property.SetValue(this.DataContext, value);
                        this.OnChanged();
                    }));

                    builder.AddAttribute(sequence++, "Label", property.Name);
                    builder.CloseComponent();
                }
                else if (property.PropertyType == typeof(DateTime))
                {
                    builder.OpenComponent(sequence++, typeof(MatDatePicker <DateTime>));
                    builder.AddAttribute(sequence++, "Value", value);

                    builder.AddAttribute(sequence++, "ValueChanged",
                                         EventCallback.Factory.Create <DateTime>(this, value =>
                    {
                        property.SetValue(this.DataContext, value);
                        this.OnChanged();
                    }));

                    builder.AddAttribute(sequence++, "Label", property.Name);
                    builder.AddAttribute(sequence++, "Format", "dd.MM.yyyy HH:mm");
                    builder.AddAttribute(sequence++, "EnableTime", true);
                    builder.AddAttribute(sequence++, "EnableSeconds", false);
                    builder.AddAttribute(sequence++, "Enable24hours", true);
                    builder.AddAttribute(sequence++, "AllowInput", true);
                    builder.CloseComponent();
                }
                // List
                else if (value is IList list)
                {
                    var elementType = list.GetType().GetGenericArguments().Single();

                    builder.OpenElement(sequence++, "div");
                    builder.AddAttribute(sequence++, "class", "form-generator-list");

                    builder.OpenElement(sequence++, "div");
                    builder.AddAttribute(sequence++, "class", "form-generator-header");

                    builder.OpenElement(sequence++, "span");
                    builder.AddAttribute(sequence++, "class", "form-generator-title");
                    builder.AddContent(sequence++, $"{property.Name} ({list.Count})");
                    builder.CloseComponent();

                    builder.OpenElement(sequence++, "span");
                    builder.AddAttribute(sequence++, "class", "form-generator-add-button");
                    builder.AddAttribute(sequence++, "onclick",
                                         EventCallback.Factory.Create <MouseEventArgs>(this, value =>
                    {
                        var element = this.Instantiate(elementType);
                        list.Add(element);
                        this.OnChanged();
                    }));
                    builder.OpenElement(sequence++, "i");
                    builder.AddAttribute(sequence++, "class", "fas fa-plus");
                    builder.CloseElement();
                    builder.CloseElement();

                    builder.CloseElement();

                    builder.OpenElement(sequence++, "div");
                    builder.AddAttribute(sequence++, "class", "form-generator-content");

                    if (list.Count > 0)
                    {
                        var index = 0;

                        foreach (var item in list)
                        {
                            builder.OpenElement(sequence++, "div");
                            builder.AddAttribute(sequence++, "class", "form-generator-list-item");

                            if (elementType.IsPrimitive || elementType.IsEnum || elementType == typeof(string) || elementType == typeof(decimal))
                            {
                                var localIndex = index;

                                Action <object> valueChanged = newValue =>
                                {
                                    list[localIndex] = newValue;
                                    this.OnChanged();
                                };

                                var onKeyDown = EventCallback.Factory.Create <KeyboardEventArgs>(this, e =>
                                {
                                    if (e.Key == "Delete")
                                    {
                                        list.RemoveAt(localIndex);
                                        this.OnChanged();
                                    }
                                });

                                sequence = (int)NexusUtilities.InvokeGenericMethod(
                                    this.GetType(),
                                    this,
                                    nameof(AddGenericPrimitive),
                                    BindingFlags.NonPublic | BindingFlags.Instance,
                                    elementType,
                                    new object[] { builder, sequence, "Value", item, valueChanged, onKeyDown });
                            }
                            else
                            {
                                builder.OpenComponent(sequence++, typeof(FormGenerator));
                                builder.AddAttribute(sequence++, "DataContext", item);
                                builder.AddAttribute(sequence++, "Changed",
                                                     EventCallback.Factory.Create(this, value => this.OnChanged()));
                                builder.CloseComponent();

                                var localIndex = index;
                                builder.OpenElement(sequence++, "span");
                                builder.AddAttribute(sequence++, "class", "form-generator-remove-button");
                                builder.AddAttribute(sequence++, "onclick",
                                                     EventCallback.Factory.Create <MouseEventArgs>(this, e =>
                                {
                                    var element = this.Instantiate(elementType);
                                    list.RemoveAt(localIndex);
                                    this.OnChanged();
                                }));
                                builder.OpenElement(sequence++, "i");
                                builder.AddAttribute(sequence++, "class", "fas fa-trash-alt");
                                builder.CloseElement();
                                builder.CloseElement();
                            }

                            builder.CloseElement();

                            index++;
                        }
                    }

                    builder.CloseElement();
                    builder.CloseElement();
                }
                // Dictionary
                else if (value is IDictionary dict)
                {
                    var elementTypes = dict.GetType().GetGenericArguments();

                    if (!(elementTypes[0].IsPrimitive || elementTypes[0].IsEnum || elementTypes[0] == typeof(string) || elementTypes[0] == typeof(decimal)))
                    {
                        throw new Exception("Only primitive keys are supported.");
                    }

                    builder.OpenElement(sequence++, "div");
                    builder.AddAttribute(sequence++, "class", "form-generator-dict");

                    builder.OpenElement(sequence++, "div");
                    builder.AddAttribute(sequence++, "class", "form-generator-header");

                    builder.OpenElement(sequence++, "span");
                    builder.AddAttribute(sequence++, "class", "form-generator-title");
                    builder.AddContent(sequence++, $"{property.Name} ({dict.Count})");
                    builder.CloseComponent();

                    builder.OpenElement(sequence++, "span");
                    builder.AddAttribute(sequence++, "class", "form-generator-add-button");
                    builder.AddAttribute(sequence++, "onclick",
                                         EventCallback.Factory.Create <MouseEventArgs>(this, value =>
                    {
                        var dictKey   = this.Instantiate(elementTypes[0]);
                        var dictValue = this.Instantiate(elementTypes[1]);
                        dict[dictKey] = dictValue;
                        this.OnChanged();
                    }));
                    builder.OpenElement(sequence++, "i");
                    builder.AddAttribute(sequence++, "class", "fas fa-plus");
                    builder.CloseElement();
                    builder.CloseElement();

                    builder.CloseElement();

                    builder.OpenElement(sequence++, "div");
                    builder.AddAttribute(sequence++, "class", "form-generator-content");

                    if (dict.Count > 0)
                    {
                        foreach (var key in dict.Keys)
                        {
                            builder.OpenElement(sequence++, "div");
                            builder.AddAttribute(sequence++, "class", "form-generator-dict-entry");

                            // key
                            Action <object> valueChanged = newKey =>
                            {
                                dict.Remove(key);
                                dict[newKey] = this.Instantiate(elementTypes[1]);
                                this.OnChanged();
                            };

                            var onKeyDown = EventCallback.Factory.Create <KeyboardEventArgs>(this, e =>
                            {
                                if (e.Key == "Delete")
                                {
                                    dict.Remove(key);
                                    this.OnChanged();
                                }
                            });

                            sequence = (int)NexusUtilities.InvokeGenericMethod(
                                this.GetType(),
                                this,
                                nameof(AddGenericPrimitive),
                                BindingFlags.NonPublic | BindingFlags.Instance,
                                elementTypes[0],
                                new object[] { builder, sequence, "Key", key, valueChanged, onKeyDown });

                            // space
                            builder.OpenElement(sequence++, "span");
                            builder.AddContent(sequence++, " ");
                            builder.CloseElement();

                            // value
                            if (elementTypes[1].IsPrimitive || elementTypes[1].IsEnum || elementTypes[1] == typeof(string) || elementTypes[1] == typeof(decimal))
                            {
                                Action <object> valueChanged2 = newValue =>
                                {
                                    dict[key] = newValue;
                                    this.OnChanged();
                                };

                                sequence = (int)NexusUtilities.InvokeGenericMethod(
                                    this.GetType(),
                                    this,
                                    nameof(AddGenericPrimitive),
                                    BindingFlags.NonPublic | BindingFlags.Instance,
                                    elementTypes[1],
                                    new object[] { builder, sequence, "Value", dict[key], valueChanged2, null });
                            }
                            else
                            {
                                builder.OpenComponent(sequence++, typeof(FormGenerator));
                                builder.AddAttribute(sequence++, "DataContext", dict[key]);
                                builder.AddAttribute(sequence++, "Changed",
                                                     EventCallback.Factory.Create(this, value => this.OnChanged()));
                                builder.CloseComponent();
                            }

                            builder.CloseElement();
                        }
                    }

                    builder.CloseElement();
                    builder.CloseElement();
                }

                builder.CloseElement();
            }

            builder.CloseComponent();
        };
コード例 #12
0
        private IEnumerable <DataReaderProgressRecord> InternalRead(
            List <DatasetInfo> datasets,
            DateTime begin,
            DateTime end,
            ulong blockSizeLimit,
            TimeSpan basePeriod,
            TimeSpan fundamentalPeriod,
            CancellationToken cancellationToken)
        {
            /*
             * |....................|
             * |
             * |
             * |....................
             * |
             * |
             * |....................
             * |
             * |====================
             * |....................
             * |
             * |
             * |....................|
             *
             * |     = base period (1 minute)
             *  ...  = fundamental period (e.g. 10 minutes)
             * |...| = begin & end markers
             *  ===  = block period
             */

            if (cancellationToken.IsCancellationRequested)
            {
                yield break;
            }

            if (!datasets.Any() || begin == end)
            {
                yield break;
            }

            // calculation
            var minutesPerFP = fundamentalPeriod.Ticks / basePeriod.Ticks;

            var bytesPerFP = datasets.Sum(dataset =>
            {
                var bytesPerSample   = NexusUtilities.SizeOf(dataset.DataType);
                var samplesPerMinute = dataset.GetSampleRate().SamplesPerSecond * 60;
                var bytesPerFP       = bytesPerSample * samplesPerMinute * minutesPerFP;

                return(bytesPerFP);
            });

            var FPCountPerBlock = blockSizeLimit / bytesPerFP;
            var roundedFPCount  = (long)Math.Floor(FPCountPerBlock);

            if (roundedFPCount < 1)
            {
                throw new Exception("The block size limit is too small.");
            }

            var maxPeriodPerRequest = TimeSpan.FromTicks(fundamentalPeriod.Ticks * roundedFPCount);

            // load data
            var period          = end - begin;
            var currentBegin    = begin;
            var remainingPeriod = end - currentBegin;

            while (remainingPeriod > TimeSpan.Zero)
            {
                var datasetToRecordMap = new Dictionary <DatasetInfo, DataRecord>();
                var currentPeriod      = TimeSpan.FromTicks(Math.Min(remainingPeriod.Ticks, maxPeriodPerRequest.Ticks));
                var currentEnd         = currentBegin + currentPeriod;
                var index = 1;
                var count = datasets.Count;

                foreach (var dataset in datasets)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        yield break;
                    }

                    (var data, var status)      = this.ReadSingle(dataset, currentBegin, currentEnd);
                    datasetToRecordMap[dataset] = new DataRecord(data, status);

                    // update progress
                    var localProgress   = TimeSpan.FromTicks(currentPeriod.Ticks * index / count);
                    var currentProgress = (currentBegin + localProgress - begin).Ticks / (double)period.Ticks;

                    ((IProgress <double>) this.Progress).Report(currentProgress);
                    index++;
                }

                // notify about new data
                yield return(new DataReaderProgressRecord(datasetToRecordMap, currentBegin, currentEnd));

                // continue in time
                currentBegin   += currentPeriod;
                remainingPeriod = end - currentBegin;
            }
        }
コード例 #13
0
ファイル: FamosWriter.cs プロジェクト: Apollo3zehn/Nexus
        private void OpenFile(string dataFilePath, DateTime startDateTime, List <ChannelContextGroup> channelContextGroupSet)
        {
            if (File.Exists(dataFilePath))
            {
                throw new Exception($"The file {dataFilePath} already exists. Extending an already existing file with additional channels is not supported.");
            }

            var famosFile = new FamosFileHeader();

            // file
            var metadataGroup = new FamosFileGroup("Metadata");

            metadataGroup.PropertyInfo = new FamosFilePropertyInfo(new List <FamosFileProperty>()
            {
                new FamosFileProperty("format_version", this.FormatVersion),
                new FamosFileProperty("system_name", this.DataWriterContext.SystemName),
                new FamosFileProperty("date_time", startDateTime),
            });

            foreach (var customMetadataEntry in this.DataWriterContext.CustomMetadataEntrySet.Where(customMetadataEntry => customMetadataEntry.CustomMetadataEntryLevel == CustomMetadataEntryLevel.File))
            {
                metadataGroup.PropertyInfo.Properties.Add(new FamosFileProperty(customMetadataEntry.Key, customMetadataEntry.Value));
            }

            famosFile.Groups.Add(metadataGroup);

            // file -> project
            var projectGroup = new FamosFileGroup($"{this.DataWriterContext.ProjectDescription.PrimaryGroupName} / {this.DataWriterContext.ProjectDescription.SecondaryGroupName} / {this.DataWriterContext.ProjectDescription.ProjectName}");

            projectGroup.PropertyInfo = new FamosFilePropertyInfo(new List <FamosFileProperty>()
            {
                new FamosFileProperty("project_version", this.DataWriterContext.ProjectDescription.Version)
            });

            foreach (var customMetadataEntry in this.DataWriterContext.CustomMetadataEntrySet.Where(customMetadataEntry => customMetadataEntry.CustomMetadataEntryLevel == CustomMetadataEntryLevel.Project))
            {
                projectGroup.PropertyInfo.Properties.Add(new FamosFileProperty(customMetadataEntry.Key, customMetadataEntry.Value));
            }

            famosFile.Groups.Add(projectGroup);

            // for each context group
            foreach (var contextGroup in channelContextGroupSet)
            {
                var totalSeconds = (int)Math.Round(_settings.FilePeriod.TotalSeconds, MidpointRounding.AwayFromZero);
                var totalLength  = (int)(totalSeconds * contextGroup.SampleRate.SamplesPerSecond);

                if (totalLength * (double)NexusUtilities.SizeOf(NexusDataType.FLOAT64) > 2 * Math.Pow(10, 9))
                {
                    throw new Exception(ErrorMessage.FamosWriter_DataSizeExceedsLimit);
                }

                // file -> project -> channels
                var field = new FamosFileField(FamosFileFieldType.MultipleYToSingleEquidistantTime);

                foreach (ChannelContext channelContext in contextGroup.ChannelContextSet)
                {
                    var dx      = contextGroup.SampleRate.Period.TotalSeconds;
                    var channel = this.PrepareChannel(field, channelContext.ChannelDescription, (int)totalLength, startDateTime, dx);

                    projectGroup.Channels.Add(channel);
                }

                famosFile.Fields.Add(field);
                _spdToFieldIndexMap[contextGroup.SampleRate.SamplesPerDay] = famosFile.Fields.Count - 1;
            }

            //
            famosFile.Save(dataFilePath, _ => { });
            _famosFile = FamosFile.OpenEditable(dataFilePath);
        }