tombstones: Fixed Add method in order to support trimming time series; Simplified the algo. (#7471)

* tombstones: Fixed Add method in order to support edge trimming; Simplified the algo.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>

* Removed duplicated test case.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>

* Fixed comment, removed "edge" mention.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>

* Removed trimming word.

Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
This commit is contained in:
Bartlomiej Plotka 2020-06-29 18:00:22 +02:00 committed by GitHub
parent 487f1e07ff
commit 1861bf38f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 51 deletions

View File

@ -22,6 +22,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"sort"
"sync"
"github.com/go-kit/kit/log"
@ -286,47 +287,32 @@ type Intervals []Interval
// Add the new time-range to the existing ones.
// The existing ones must be sorted.
func (itvs Intervals) Add(n Interval) Intervals {
for i, r := range itvs {
// TODO(gouthamve): Make this codepath easier to digest.
if r.InBounds(n.Mint-1) || r.InBounds(n.Mint) {
if n.Maxt > r.Maxt {
itvs[i].Maxt = n.Maxt
func (in Intervals) Add(n Interval) Intervals {
if len(in) == 0 {
return append(in, n)
}
// Find min and max indexes of intervals that overlap with the new interval.
// Intervals are closed [t1, t2] and t is discreet, so if neighbour intervals are 1 step difference
// to the new one, we can merge those together.
mini := sort.Search(len(in), func(i int) bool { return in[i].Maxt >= n.Mint-1 })
if mini == len(in) {
return append(in, n)
}
j := 0
for _, r2 := range itvs[i+1:] {
if n.Maxt < r2.Mint {
break
maxi := sort.Search(len(in)-mini, func(i int) bool { return in[mini+i].Mint > n.Maxt+1 })
if maxi == 0 {
if mini == 0 {
return append(Intervals{n}, in...)
}
j++
}
if j != 0 {
if itvs[i+j].Maxt > n.Maxt {
itvs[i].Maxt = itvs[i+j].Maxt
}
itvs = append(itvs[:i+1], itvs[i+j+1:]...)
}
return itvs
return append(in[:mini], append(Intervals{n}, in[mini:]...)...)
}
if r.InBounds(n.Maxt+1) || r.InBounds(n.Maxt) {
if n.Mint < r.Maxt {
itvs[i].Mint = n.Mint
if n.Mint < in[mini].Mint {
in[mini].Mint = n.Mint
}
return itvs
in[mini].Maxt = in[maxi+mini-1].Maxt
if n.Maxt > in[mini].Maxt {
in[mini].Maxt = n.Maxt
}
if n.Mint < r.Mint {
newRange := make(Intervals, i, len(itvs[:i])+1)
copy(newRange, itvs[:i])
newRange = append(newRange, n)
newRange = append(newRange, itvs[i:]...)
return newRange
}
}
itvs = append(itvs, n)
return itvs
return append(in[:mini+1], in[maxi+mini:]...)
}

View File

@ -15,6 +15,7 @@ package tombstones
import (
"io/ioutil"
"math"
"math/rand"
"os"
"sync"
@ -25,7 +26,7 @@ import (
"github.com/prometheus/prometheus/util/testutil"
)
func TestWriteAndReadbackTombStones(t *testing.T) {
func TestWriteAndReadbackTombstones(t *testing.T) {
tmpdir, _ := ioutil.TempDir("", "test")
defer func() {
testutil.Ok(t, os.RemoveAll(tmpdir))
@ -80,19 +81,19 @@ func TestAddingNewIntervals(t *testing.T) {
},
{
exist: Intervals{{1, 10}, {12, 20}, {25, 30}},
new: Interval{21, 23},
exp: Intervals{{1, 10}, {12, 23}, {25, 30}},
new: Interval{21, 25},
exp: Intervals{{1, 10}, {12, 30}},
},
{
exist: Intervals{{1, 10}, {12, 20}, {25, 30}},
new: Interval{22, 23},
exp: Intervals{{1, 10}, {12, 20}, {22, 23}, {25, 30}},
},
{
exist: Intervals{{1, 2}, {3, 5}, {7, 7}},
new: Interval{6, 7},
exp: Intervals{{1, 2}, {3, 7}},
},
{
exist: Intervals{{1, 10}, {12, 20}, {25, 30}},
new: Interval{21, 25},
exp: Intervals{{1, 10}, {12, 30}},
},
{
exist: Intervals{{1, 10}, {12, 20}, {25, 30}},
new: Interval{18, 23},
@ -123,11 +124,36 @@ func TestAddingNewIntervals(t *testing.T) {
new: Interval{1, 3},
exp: Intervals{{1, 3}, {5, 10}, {12, 20}, {25, 30}},
},
{
exist: Intervals{{5, 10}, {12, 20}, {25, 30}},
new: Interval{35, 40},
exp: Intervals{{5, 10}, {12, 20}, {25, 30}, {35, 40}},
},
{
new: Interval{math.MinInt64, 2},
exp: Intervals{{math.MinInt64, 2}},
},
{
exist: Intervals{{math.MinInt64, 2}},
new: Interval{9, math.MaxInt64},
exp: Intervals{{math.MinInt64, 2}, {9, math.MaxInt64}},
},
{
exist: Intervals{{9, math.MaxInt64}},
new: Interval{math.MinInt64, 2},
exp: Intervals{{math.MinInt64, 2}, {9, math.MaxInt64}},
},
{
exist: Intervals{{9, math.MaxInt64}},
new: Interval{math.MinInt64, 10},
exp: Intervals{{math.MinInt64, math.MaxInt64}},
},
}
for _, c := range cases {
t.Run("", func(t *testing.T) {
testutil.Equals(t, c.exp, c.exist.Add(c.new))
})
}
}