Fix omitting of chunk on Seek()

This commit is contained in:
Fabian Reinartz 2017-06-30 15:06:27 +02:00
parent 1e74c155eb
commit bda3ed20ac
2 changed files with 28 additions and 19 deletions

View file

@ -15,7 +15,6 @@ package tsdb
import (
"fmt"
"sort"
"strings"
"github.com/prometheus/tsdb/chunks"
@ -671,25 +670,13 @@ func (it *chunkSeriesIterator) Seek(t int64) (ok bool) {
t = it.mint
}
// Only do binary search forward to stay in line with other iterators
// that can only move forward.
x := sort.Search(len(it.chunks[it.i:]), func(i int) bool {
return it.chunks[it.i+i].MinTime >= t
})
x += it.i
// If the timestamp was not found, it might be in the last chunk.
if x == len(it.chunks) {
x--
// Go to previous chunk if the chunk doesn't exactly start with t.
// If we are already at the first chunk, we use it as it's the best we have.
} else if x > 0 && it.chunks[x].MinTime > t {
x--
for ; it.chunks[it.i].MaxTime < t; it.i++ {
if it.i == len(it.chunks)-1 {
return false
}
}
it.i = x
it.cur = it.chunks[x].Chunk.Iterator()
it.cur = it.chunks[it.i].Chunk.Iterator()
if len(it.intervals) > 0 {
it.cur = &deletedIterator{it: it.cur, intervals: it.intervals}
}

View file

@ -1028,7 +1028,7 @@ func TestSeriesIterator(t *testing.T) {
}
// Regression for: https://github.com/prometheus/tsdb/pull/97
func TestCSIteratorDoubleSeek(t *testing.T) {
func TestChunkSeriesIterator_DoubleSeek(t *testing.T) {
chkMetas := []*ChunkMeta{
chunkFromSamples([]sample{}),
chunkFromSamples([]sample{{1, 1}, {2, 2}, {3, 3}}),
@ -1043,6 +1043,28 @@ func TestCSIteratorDoubleSeek(t *testing.T) {
require.Equal(t, float64(2), v)
}
// Regression when seeked chunks were still found via binary search and we always
// skipped to the end when seeking a value in the current chunk.
func TestChunkSeriesIterator_SeekInCurrentChunk(t *testing.T) {
metas := []*ChunkMeta{
chunkFromSamples([]sample{}),
chunkFromSamples([]sample{{1, 2}, {3, 4}, {5, 6}, {7, 8}}),
chunkFromSamples([]sample{}),
}
it := newChunkSeriesIterator(metas, nil, 1, 7)
require.True(t, it.Next())
ts, v := it.At()
require.Equal(t, int64(1), ts)
require.Equal(t, float64(2), v)
require.True(t, it.Seek(4))
ts, v = it.At()
require.Equal(t, int64(5), ts)
require.Equal(t, float64(6), v)
}
func TestPopulatedCSReturnsValidChunkSlice(t *testing.T) {
lbls := []labels.Labels{labels.New(labels.Label{"a", "b"})}
chunkMetas := [][]*ChunkMeta{