influxdb/tsdb/tsm1/reader_time_range.go

96 lines
2.3 KiB
Go

package tsm1
// TimeRange holds a min and max timestamp.
type TimeRange struct {
Min, Max int64
}
func (t TimeRange) Overlaps(min, max int64) bool {
return t.Min <= max && t.Max >= min
}
// Within returns true if min < t.Min and t.Max < max and therefore the interval [t.Min, t.Max] is
// contained within [min, max]
func (t TimeRange) Within(min, max int64) bool {
return min < t.Min && t.Max < max
}
func (t TimeRange) Less(o TimeRange) bool {
return t.Min < o.Min || (t.Min == o.Min && t.Max < o.Max)
}
// timeRangesCoverEntries returns true if the time ranges fully cover the entries.
func timeRangesCoverEntries(merger timeRangeMerger, entries []IndexEntry) (covers bool) {
if len(entries) == 0 {
return true
}
mustCover := entries[0].MinTime
ts, ok := merger.Pop()
for len(entries) > 0 && ok {
switch {
// If the tombstone does not include mustCover, we
// know we do not fully cover every entry.
case ts.Min > mustCover:
return false
// Otherwise, if the tombstone covers the rest of
// the entry, consume it and bump mustCover to the
// start of the next entry.
case ts.Max >= entries[0].MaxTime:
entries = entries[1:]
if len(entries) > 0 {
mustCover = entries[0].MinTime
}
// Otherwise, we're still inside of an entry, and
// so the tombstone must adjoin the current tombstone.
default:
if ts.Max >= mustCover {
mustCover = ts.Max + 1
}
ts, ok = merger.Pop()
}
}
return len(entries) == 0
}
// timeRangeMerger is a special purpose data structure to merge three sources of
// TimeRanges so that we can check if they cover a slice of index entries.
type timeRangeMerger struct {
fromMap []TimeRange
fromPrefix []TimeRange
single TimeRange
used bool // if single has been used
}
// Pop returns the next TimeRange in sorted order and a boolean indicating that
// there was a TimeRange to read.
func (t *timeRangeMerger) Pop() (out TimeRange, ok bool) {
var where *[]TimeRange
var what []TimeRange
if len(t.fromMap) > 0 {
where, what = &t.fromMap, t.fromMap[1:]
out, ok = t.fromMap[0], true
}
if len(t.fromPrefix) > 0 && (!ok || t.fromPrefix[0].Less(out)) {
where, what = &t.fromPrefix, t.fromPrefix[1:]
out, ok = t.fromPrefix[0], true
}
if !t.used && (!ok || t.single.Less(out)) {
t.used = true
return t.single, true
}
if ok {
*where = what
}
return out, ok
}