示例#1
0
        internal static unsafe TimeSeriesRangeResult GetTimeSeriesRange(DocumentsOperationContext context, string docId, string name, DateTime from, DateTime to, ref int start, ref int pageSize,
                                                                        IncludeDocumentsDuringTimeSeriesLoadingCommand includesCommand = null)
        {
            if (pageSize == 0)
            {
                return(null);
            }

            List <TimeSeriesEntry> values = new List <TimeSeriesEntry>();

            var reader = new TimeSeriesReader(context, docId, name, from, to, offset: null);

            // init hash
            var size = Sodium.crypto_generichash_bytes();

            Debug.Assert((int)size == 32);
            var cryptoGenerichashStatebytes = (int)Sodium.crypto_generichash_statebytes();
            var state = stackalloc byte[cryptoGenerichashStatebytes];

            if (Sodium.crypto_generichash_init(state, null, UIntPtr.Zero, size) != 0)
            {
                ComputeHttpEtags.ThrowFailToInitHash();
            }

            var      initialStart  = start;
            var      hasMore       = false;
            DateTime lastSeenEntry = from;

            includesCommand?.InitializeNewRangeResult(state);

            foreach (var(individualValues, segmentResult) in reader.SegmentsOrValues())
            {
                if (individualValues == null &&
                    start > segmentResult.Summary.NumberOfLiveEntries)
                {
                    lastSeenEntry = segmentResult.End;
                    start        -= segmentResult.Summary.NumberOfLiveEntries;
                    continue;
                }

                var enumerable = individualValues ?? segmentResult.Values;

                foreach (var singleResult in enumerable)
                {
                    lastSeenEntry = segmentResult.End;

                    if (start-- > 0)
                    {
                        continue;
                    }

                    if (pageSize-- <= 0)
                    {
                        hasMore = true;
                        break;
                    }

                    includesCommand?.Fill(singleResult.Tag);

                    values.Add(new TimeSeriesEntry
                    {
                        Timestamp = singleResult.Timestamp,
                        Tag       = singleResult.Tag,
                        Values    = singleResult.Values.ToArray(),
                        IsRollup  = singleResult.Type == SingleResultType.RolledUp
                    });
                }

                ComputeHttpEtags.HashChangeVector(state, segmentResult.ChangeVector);

                if (pageSize <= 0)
                {
                    break;
                }
            }

            var hash = ComputeHttpEtags.FinalizeHash(size, state);

            TimeSeriesRangeResult result;

            if (initialStart > 0 && values.Count == 0)
            {
                // this is a special case, because before the 'start' we might have values
                result = new TimeSeriesRangeResult
                {
                    From    = lastSeenEntry,
                    To      = to,
                    Entries = values.ToArray(),
                    Hash    = hash
                };
            }
            else
            {
                result = new TimeSeriesRangeResult
                {
                    From    = (initialStart > 0) ? values[0].Timestamp : from,
                    To      = hasMore ? values.Last().Timestamp : to,
                    Entries = values.ToArray(),
                    Hash    = hash
                };
            }

            includesCommand?.AddIncludesToResult(result);

            return(result);
        }
示例#2
0
        private static Dictionary <string, List <TimeSeriesRangeResult> > GetTimeSeriesRangeResults(DocumentsOperationContext context, string documentId, StringValues names, StringValues fromList, StringValues toList, int start, int pageSize, IncludeDocumentsDuringTimeSeriesLoadingCommand includes)
        {
            if (fromList.Count == 0)
            {
                throw new ArgumentException("Length of query string values 'from' must be greater than zero");
            }

            if (fromList.Count != toList.Count)
            {
                throw new ArgumentException("Length of query string values 'from' must be equal to the length of query string values 'to'");
            }

            if (fromList.Count != names.Count)
            {
                throw new InvalidOperationException($"GetMultipleTimeSeriesOperation : Argument count miss match on document '{documentId}'. " +
                                                    $"Received {names.Count} 'name' arguments, and {fromList.Count} 'from'/'to' arguments.");
            }

            var rangeResultDictionary = new Dictionary <string, List <TimeSeriesRangeResult> >(StringComparer.OrdinalIgnoreCase);

            for (int i = 0; i < fromList.Count; i++)
            {
                var name = names[i];

                if (string.IsNullOrEmpty(name))
                {
                    throw new InvalidOperationException($"GetMultipleTimeSeriesOperation : Missing '{nameof(TimeSeriesRange.Name)}' argument in 'TimeSeriesRange' on document '{documentId}'. " +
                                                        $"'{nameof(TimeSeriesRange.Name)}' cannot be null or empty");
                }

                var from = string.IsNullOrEmpty(fromList[i]) ? DateTime.MinValue : ParseDate(fromList[i], name);
                var to   = string.IsNullOrEmpty(toList[i]) ? DateTime.MaxValue : ParseDate(toList[i], name);

                var rangeResult = GetTimeSeriesRange(context, documentId, name, from, to, ref start, ref pageSize, includes);
                if (rangeResult == null)
                {
                    Debug.Assert(pageSize <= 0, "Page size must be zero or less here");
                    return(rangeResultDictionary);
                }
                if (rangeResultDictionary.TryGetValue(name, out var list) == false)
                {
                    rangeResultDictionary[name] = new List <TimeSeriesRangeResult> {
                        rangeResult
                    };
                }
                else
                {
                    list.Add(rangeResult);
                }

                if (pageSize <= 0)
                {
                    break;
                }
            }

            return(rangeResultDictionary);
        }