private static unsafe string CombineHashesFromMultipleRanges(Dictionary <string, List <TimeSeriesRangeResult> > ranges) { // 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(); } ComputeHttpEtags.HashNumber(state, ranges.Count); foreach (var kvp in ranges) { foreach (var range in kvp.Value) { ComputeHttpEtags.HashChangeVector(state, range.Hash); } } return(ComputeHttpEtags.FinalizeHash(size, state)); }
internal static unsafe TimeSeriesRangeResult GetTimeSeriesRange(DocumentsOperationContext context, string docId, string name, DateTime from, DateTime to, ref int start, ref int pageSize) { if (pageSize == 0) { return(new TimeSeriesRangeResult()); } 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 oldStart = start; var lastResult = true; foreach (var(individualValues, segmentResult) in reader.SegmentsOrValues()) { if (individualValues == null && start > segmentResult.Summary.Span[0].Count) { start -= segmentResult.Summary.Span[0].Count; continue; } var enumerable = individualValues ?? segmentResult.Values; foreach (var singleResult in enumerable) { if (start-- > 0) { continue; } if (pageSize-- <= 0) { lastResult = false; break; } 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; } } if ((oldStart > 0) && (values.Count == 0)) { return(new TimeSeriesRangeResult()); } return(new TimeSeriesRangeResult { From = (oldStart > 0) ? values[0].Timestamp : from, To = lastResult ? to : values.Last().Timestamp, Entries = values.ToArray(), Hash = ComputeHttpEtags.FinalizeHash(size, state) }); }
internal static unsafe TimeSeriesRangeResult GetTimeSeriesRange(DocumentsOperationContext context, string docId, string name, DateTime from, DateTime to, ref int start, ref int pageSize) { 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; 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; } 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); if ((initialStart > 0) && (values.Count == 0)) { // this is a special case, because before the 'start' we might have values return new TimeSeriesRangeResult { From = lastSeenEntry, To = to, Entries = values.ToArray(), Hash = hash } } ; return(new TimeSeriesRangeResult { From = (initialStart > 0) ? values[0].Timestamp : from, To = hasMore ? values.Last().Timestamp : to, Entries = values.ToArray(), Hash = hash }); }