mirror of
https://github.com/prometheus/prometheus.git
synced 2024-11-14 01:24:04 -08:00
4708915ac6
Benchmarks show slight cpu/allocs improvements. benchmark old ns/op new ns/op delta BenchmarkPostingsForMatchers/Head/n="1"-4 269978625 235305110 -12.84% BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 129739974 121646193 -6.24% BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 123826274 122056253 -1.43% BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 126962188 130038235 +2.42% BenchmarkPostingsForMatchers/Head/i=~".*"-4 6423653989 5991126455 -6.73% BenchmarkPostingsForMatchers/Head/i=~".+"-4 6934647521 7033370634 +1.42% BenchmarkPostingsForMatchers/Head/i=~""-4 1177781285 1121497736 -4.78% BenchmarkPostingsForMatchers/Head/i!=""-4 7033680256 7246094991 +3.02% BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 293702332 287440212 -2.13% BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 307628268 307039964 -0.19% BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 512247746 480003862 -6.29% BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 361199794 367066917 +1.62% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 478863761 476037784 -0.59% BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 103394659 102902098 -0.48% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 482552781 475453903 -1.47% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 559257389 589297047 +5.37% BenchmarkPostingsForMatchers/Block/n="1"-4 36492 37012 +1.42% BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 557788 611903 +9.70% BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 554443 573814 +3.49% BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 553227 553826 +0.11% BenchmarkPostingsForMatchers/Block/i=~".*"-4 113855090 111707221 -1.89% BenchmarkPostingsForMatchers/Block/i=~".+"-4 133994674 136520728 +1.89% BenchmarkPostingsForMatchers/Block/i=~""-4 38138091 36299898 -4.82% BenchmarkPostingsForMatchers/Block/i!=""-4 28861213 27396723 -5.07% BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 112699941 110853868 -1.64% BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 113198026 111389742 -1.60% BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 28994069 27363804 -5.62% BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 29709406 28589223 -3.77% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 134695119 135736971 +0.77% BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 26783286 25826928 -3.57% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 134733254 134116739 -0.46% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 160713937 158802768 -1.19% benchmark old allocs new allocs delta BenchmarkPostingsForMatchers/Head/n="1"-4 36 36 +0.00% BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 38 38 +0.00% BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 38 38 +0.00% BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 42 40 -4.76% BenchmarkPostingsForMatchers/Head/i=~".*"-4 61 59 -3.28% BenchmarkPostingsForMatchers/Head/i=~".+"-4 100088 100087 -0.00% BenchmarkPostingsForMatchers/Head/i=~""-4 100053 100051 -0.00% BenchmarkPostingsForMatchers/Head/i!=""-4 100087 100085 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 44 42 -4.55% BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 50 48 -4.00% BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 100076 100074 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 100077 100075 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 100077 100074 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 11167 11165 -0.02% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 100082 100080 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 111265 111261 -0.00% BenchmarkPostingsForMatchers/Block/n="1"-4 6 6 +0.00% BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 11 11 +0.00% BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 11 11 +0.00% BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 15 13 -13.33% BenchmarkPostingsForMatchers/Block/i=~".*"-4 12 10 -16.67% BenchmarkPostingsForMatchers/Block/i=~".+"-4 100040 100038 -0.00% BenchmarkPostingsForMatchers/Block/i=~""-4 100045 100043 -0.00% BenchmarkPostingsForMatchers/Block/i!=""-4 100041 100039 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 17 15 -11.76% BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 23 21 -8.70% BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 100046 100044 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 100050 100048 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 100049 100047 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 11150 11148 -0.02% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 100055 100053 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 111238 111234 -0.00% benchmark old bytes new bytes delta BenchmarkPostingsForMatchers/Head/n="1"-4 10887816 10887817 +0.00% BenchmarkPostingsForMatchers/Head/n="1",j="foo"-4 5456648 5456648 +0.00% BenchmarkPostingsForMatchers/Head/j="foo",n="1"-4 5456648 5456648 +0.00% BenchmarkPostingsForMatchers/Head/n="1",j!="foo"-4 5456792 5456712 -0.00% BenchmarkPostingsForMatchers/Head/i=~".*"-4 258254408 258254328 -0.00% BenchmarkPostingsForMatchers/Head/i=~".+"-4 273912888 273912904 +0.00% BenchmarkPostingsForMatchers/Head/i=~""-4 17266680 17266600 -0.00% BenchmarkPostingsForMatchers/Head/i!=""-4 273912416 273912336 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".*",j="foo"-4 7062578 7062498 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".*",i!="2",j="foo"-4 7062770 7062690 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i!=""-4 28152346 28152266 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i!="",j="foo"-4 22721178 22721098 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",j="foo"-4 22721336 22721224 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~"1.+",j="foo"-4 3623804 3623733 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!="2",j="foo"-4 22721480 22721400 -0.00% BenchmarkPostingsForMatchers/Head/n="1",i=~".+",i!~"2.*",j="foo"-4 24816652 24816444 -0.00% BenchmarkPostingsForMatchers/Block/n="1"-4 296 296 +0.00% BenchmarkPostingsForMatchers/Block/n="1",j="foo"-4 424 424 +0.00% BenchmarkPostingsForMatchers/Block/j="foo",n="1"-4 424 424 +0.00% BenchmarkPostingsForMatchers/Block/n="1",j!="foo"-4 1544 1464 -5.18% BenchmarkPostingsForMatchers/Block/i=~".*"-4 1606114 1606045 -0.00% BenchmarkPostingsForMatchers/Block/i=~".+"-4 17264709 17264629 -0.00% BenchmarkPostingsForMatchers/Block/i=~""-4 17264780 17264696 -0.00% BenchmarkPostingsForMatchers/Block/i!=""-4 17264680 17264600 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~".*",j="foo"-4 1606253 1606165 -0.01% BenchmarkPostingsForMatchers/Block/n="1",i=~".*",i!="2",j="foo"-4 1606445 1606348 -0.01% BenchmarkPostingsForMatchers/Block/n="1",i!=""-4 17264808 17264728 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i!="",j="foo"-4 17264936 17264856 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",j="foo"-4 17264965 17264885 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~"1.+",j="foo"-4 3148262 3148182 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!="2",j="foo"-4 17265141 17265061 -0.00% BenchmarkPostingsForMatchers/Block/n="1",i=~".+",i!~"2.*",j="foo"-4 20416944 20416784 -0.00% Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
508 lines
12 KiB
Go
508 lines
12 KiB
Go
// Copyright 2017 The Prometheus Authors
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package index
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prometheus/prometheus/pkg/labels"
|
|
"github.com/prometheus/prometheus/tsdb/chunkenc"
|
|
"github.com/prometheus/prometheus/tsdb/chunks"
|
|
"github.com/prometheus/prometheus/tsdb/encoding"
|
|
"github.com/prometheus/prometheus/util/testutil"
|
|
)
|
|
|
|
type series struct {
|
|
l labels.Labels
|
|
chunks []chunks.Meta
|
|
}
|
|
|
|
type mockIndex struct {
|
|
series map[uint64]series
|
|
postings map[labels.Label][]uint64
|
|
symbols map[string]struct{}
|
|
}
|
|
|
|
func newMockIndex() mockIndex {
|
|
ix := mockIndex{
|
|
series: make(map[uint64]series),
|
|
postings: make(map[labels.Label][]uint64),
|
|
symbols: make(map[string]struct{}),
|
|
}
|
|
ix.postings[allPostingsKey] = []uint64{}
|
|
return ix
|
|
}
|
|
|
|
func (m mockIndex) Symbols() (map[string]struct{}, error) {
|
|
return m.symbols, nil
|
|
}
|
|
|
|
func (m mockIndex) AddSeries(ref uint64, l labels.Labels, chunks ...chunks.Meta) error {
|
|
if _, ok := m.series[ref]; ok {
|
|
return errors.Errorf("series with reference %d already added", ref)
|
|
}
|
|
for _, lbl := range l {
|
|
m.symbols[lbl.Name] = struct{}{}
|
|
m.symbols[lbl.Value] = struct{}{}
|
|
if _, ok := m.postings[lbl]; !ok {
|
|
m.postings[lbl] = []uint64{}
|
|
}
|
|
m.postings[lbl] = append(m.postings[lbl], ref)
|
|
}
|
|
m.postings[allPostingsKey] = append(m.postings[allPostingsKey], ref)
|
|
|
|
s := series{l: l}
|
|
// Actual chunk data is not stored in the index.
|
|
for _, c := range chunks {
|
|
c.Chunk = nil
|
|
s.chunks = append(s.chunks, c)
|
|
}
|
|
m.series[ref] = s
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m mockIndex) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (m mockIndex) LabelValues(name string) ([]string, error) {
|
|
values := []string{}
|
|
for l := range m.postings {
|
|
if l.Name == name {
|
|
values = append(values, l.Value)
|
|
}
|
|
}
|
|
return values, nil
|
|
}
|
|
|
|
func (m mockIndex) Postings(name string, values ...string) (Postings, error) {
|
|
p := []Postings{}
|
|
for _, value := range values {
|
|
l := labels.Label{Name: name, Value: value}
|
|
p = append(p, m.SortedPostings(NewListPostings(m.postings[l])))
|
|
}
|
|
return Merge(p...), nil
|
|
}
|
|
|
|
func (m mockIndex) SortedPostings(p Postings) Postings {
|
|
ep, err := ExpandPostings(p)
|
|
if err != nil {
|
|
return ErrPostings(errors.Wrap(err, "expand postings"))
|
|
}
|
|
|
|
sort.Slice(ep, func(i, j int) bool {
|
|
return labels.Compare(m.series[ep[i]].l, m.series[ep[j]].l) < 0
|
|
})
|
|
return NewListPostings(ep)
|
|
}
|
|
|
|
func (m mockIndex) Series(ref uint64, lset *labels.Labels, chks *[]chunks.Meta) error {
|
|
s, ok := m.series[ref]
|
|
if !ok {
|
|
return errors.New("not found")
|
|
}
|
|
*lset = append((*lset)[:0], s.l...)
|
|
*chks = append((*chks)[:0], s.chunks...)
|
|
|
|
return nil
|
|
}
|
|
|
|
func TestIndexRW_Create_Open(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "test_index_create")
|
|
testutil.Ok(t, err)
|
|
defer func() {
|
|
testutil.Ok(t, os.RemoveAll(dir))
|
|
}()
|
|
|
|
fn := filepath.Join(dir, indexFilename)
|
|
|
|
// An empty index must still result in a readable file.
|
|
iw, err := NewWriter(context.Background(), fn)
|
|
testutil.Ok(t, err)
|
|
testutil.Ok(t, iw.Close())
|
|
|
|
ir, err := NewFileReader(fn)
|
|
testutil.Ok(t, err)
|
|
testutil.Ok(t, ir.Close())
|
|
|
|
// Modify magic header must cause open to fail.
|
|
f, err := os.OpenFile(fn, os.O_WRONLY, 0666)
|
|
testutil.Ok(t, err)
|
|
_, err = f.WriteAt([]byte{0, 0}, 0)
|
|
testutil.Ok(t, err)
|
|
f.Close()
|
|
|
|
_, err = NewFileReader(dir)
|
|
testutil.NotOk(t, err)
|
|
}
|
|
|
|
func TestIndexRW_Postings(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "test_index_postings")
|
|
testutil.Ok(t, err)
|
|
defer func() {
|
|
testutil.Ok(t, os.RemoveAll(dir))
|
|
}()
|
|
|
|
fn := filepath.Join(dir, indexFilename)
|
|
|
|
iw, err := NewWriter(context.Background(), fn)
|
|
testutil.Ok(t, err)
|
|
|
|
series := []labels.Labels{
|
|
labels.FromStrings("a", "1", "b", "1"),
|
|
labels.FromStrings("a", "1", "b", "2"),
|
|
labels.FromStrings("a", "1", "b", "3"),
|
|
labels.FromStrings("a", "1", "b", "4"),
|
|
}
|
|
|
|
testutil.Ok(t, iw.AddSymbol("1"))
|
|
testutil.Ok(t, iw.AddSymbol("2"))
|
|
testutil.Ok(t, iw.AddSymbol("3"))
|
|
testutil.Ok(t, iw.AddSymbol("4"))
|
|
testutil.Ok(t, iw.AddSymbol("a"))
|
|
testutil.Ok(t, iw.AddSymbol("b"))
|
|
|
|
// Postings lists are only written if a series with the respective
|
|
// reference was added before.
|
|
testutil.Ok(t, iw.AddSeries(1, series[0]))
|
|
testutil.Ok(t, iw.AddSeries(2, series[1]))
|
|
testutil.Ok(t, iw.AddSeries(3, series[2]))
|
|
testutil.Ok(t, iw.AddSeries(4, series[3]))
|
|
|
|
testutil.Ok(t, iw.Close())
|
|
|
|
ir, err := NewFileReader(fn)
|
|
testutil.Ok(t, err)
|
|
|
|
p, err := ir.Postings("a", "1")
|
|
testutil.Ok(t, err)
|
|
|
|
var l labels.Labels
|
|
var c []chunks.Meta
|
|
|
|
for i := 0; p.Next(); i++ {
|
|
err := ir.Series(p.At(), &l, &c)
|
|
|
|
testutil.Ok(t, err)
|
|
testutil.Equals(t, 0, len(c))
|
|
testutil.Equals(t, series[i], l)
|
|
}
|
|
testutil.Ok(t, p.Err())
|
|
|
|
// The label incides are no longer used, so test them by hand here.
|
|
labelIndices := map[string][]string{}
|
|
testutil.Ok(t, ReadOffsetTable(ir.b, ir.toc.LabelIndicesTable, func(key []string, off uint64, _ int) error {
|
|
if len(key) != 1 {
|
|
return errors.Errorf("unexpected key length for label indices table %d", len(key))
|
|
}
|
|
|
|
d := encoding.NewDecbufAt(ir.b, int(off), castagnoliTable)
|
|
vals := []string{}
|
|
nc := d.Be32int()
|
|
if nc != 1 {
|
|
return errors.Errorf("unexpected number of label indices table names %d", nc)
|
|
}
|
|
for i := d.Be32(); i > 0; i-- {
|
|
v, err := ir.lookupSymbol(d.Be32())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
vals = append(vals, v)
|
|
}
|
|
labelIndices[key[0]] = vals
|
|
return d.Err()
|
|
}))
|
|
testutil.Equals(t, map[string][]string{
|
|
"a": []string{"1"},
|
|
"b": []string{"1", "2", "3", "4"},
|
|
}, labelIndices)
|
|
|
|
testutil.Ok(t, ir.Close())
|
|
}
|
|
|
|
func TestPostingsMany(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "test_postings_many")
|
|
testutil.Ok(t, err)
|
|
defer func() {
|
|
testutil.Ok(t, os.RemoveAll(dir))
|
|
}()
|
|
|
|
fn := filepath.Join(dir, indexFilename)
|
|
|
|
iw, err := NewWriter(context.Background(), fn)
|
|
testutil.Ok(t, err)
|
|
|
|
// Create a label in the index which has 999 values.
|
|
symbols := map[string]struct{}{}
|
|
series := []labels.Labels{}
|
|
for i := 1; i < 1000; i++ {
|
|
v := fmt.Sprintf("%03d", i)
|
|
series = append(series, labels.FromStrings("i", v, "foo", "bar"))
|
|
symbols[v] = struct{}{}
|
|
}
|
|
symbols["i"] = struct{}{}
|
|
symbols["foo"] = struct{}{}
|
|
symbols["bar"] = struct{}{}
|
|
syms := []string{}
|
|
for s := range symbols {
|
|
syms = append(syms, s)
|
|
}
|
|
sort.Strings(syms)
|
|
for _, s := range syms {
|
|
testutil.Ok(t, iw.AddSymbol(s))
|
|
}
|
|
|
|
for i, s := range series {
|
|
testutil.Ok(t, iw.AddSeries(uint64(i), s))
|
|
}
|
|
testutil.Ok(t, iw.Close())
|
|
|
|
ir, err := NewFileReader(fn)
|
|
testutil.Ok(t, err)
|
|
defer func() { testutil.Ok(t, ir.Close()) }()
|
|
|
|
cases := []struct {
|
|
in []string
|
|
}{
|
|
// Simple cases, everything is present.
|
|
{in: []string{"002"}},
|
|
{in: []string{"031", "032", "033"}},
|
|
{in: []string{"032", "033"}},
|
|
{in: []string{"127", "128"}},
|
|
{in: []string{"127", "128", "129"}},
|
|
{in: []string{"127", "129"}},
|
|
{in: []string{"128", "129"}},
|
|
{in: []string{"998", "999"}},
|
|
{in: []string{"999"}},
|
|
// Before actual values.
|
|
{in: []string{"000"}},
|
|
{in: []string{"000", "001"}},
|
|
{in: []string{"000", "002"}},
|
|
// After actual values.
|
|
{in: []string{"999a"}},
|
|
{in: []string{"999", "999a"}},
|
|
{in: []string{"998", "999", "999a"}},
|
|
// In the middle of actual values.
|
|
{in: []string{"126a", "127", "128"}},
|
|
{in: []string{"127", "127a", "128"}},
|
|
{in: []string{"127", "127a", "128", "128a", "129"}},
|
|
{in: []string{"127", "128a", "129"}},
|
|
{in: []string{"128", "128a", "129"}},
|
|
{in: []string{"128", "129", "129a"}},
|
|
{in: []string{"126a", "126b", "127", "127a", "127b", "128", "128a", "128b", "129", "129a", "129b"}},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
it, err := ir.Postings("i", c.in...)
|
|
testutil.Ok(t, err)
|
|
|
|
got := []string{}
|
|
var lbls labels.Labels
|
|
var metas []chunks.Meta
|
|
for it.Next() {
|
|
testutil.Ok(t, ir.Series(it.At(), &lbls, &metas))
|
|
got = append(got, lbls.Get("i"))
|
|
}
|
|
testutil.Ok(t, it.Err())
|
|
exp := []string{}
|
|
for _, e := range c.in {
|
|
if _, ok := symbols[e]; ok && e != "l" {
|
|
exp = append(exp, e)
|
|
}
|
|
}
|
|
testutil.Equals(t, exp, got, fmt.Sprintf("input: %v", c.in))
|
|
}
|
|
|
|
}
|
|
|
|
func TestPersistence_index_e2e(t *testing.T) {
|
|
dir, err := ioutil.TempDir("", "test_persistence_e2e")
|
|
testutil.Ok(t, err)
|
|
defer func() {
|
|
testutil.Ok(t, os.RemoveAll(dir))
|
|
}()
|
|
|
|
lbls, err := labels.ReadLabels(filepath.Join("..", "testdata", "20kseries.json"), 20000)
|
|
testutil.Ok(t, err)
|
|
|
|
// Sort labels as the index writer expects series in sorted order.
|
|
sort.Sort(labels.Slice(lbls))
|
|
|
|
symbols := map[string]struct{}{}
|
|
for _, lset := range lbls {
|
|
for _, l := range lset {
|
|
symbols[l.Name] = struct{}{}
|
|
symbols[l.Value] = struct{}{}
|
|
}
|
|
}
|
|
|
|
var input indexWriterSeriesSlice
|
|
|
|
// Generate ChunkMetas for every label set.
|
|
for i, lset := range lbls {
|
|
var metas []chunks.Meta
|
|
|
|
for j := 0; j <= (i % 20); j++ {
|
|
metas = append(metas, chunks.Meta{
|
|
MinTime: int64(j * 10000),
|
|
MaxTime: int64((j + 1) * 10000),
|
|
Ref: rand.Uint64(),
|
|
Chunk: chunkenc.NewXORChunk(),
|
|
})
|
|
}
|
|
input = append(input, &indexWriterSeries{
|
|
labels: lset,
|
|
chunks: metas,
|
|
})
|
|
}
|
|
|
|
iw, err := NewWriter(context.Background(), filepath.Join(dir, indexFilename))
|
|
testutil.Ok(t, err)
|
|
|
|
syms := []string{}
|
|
for s := range symbols {
|
|
syms = append(syms, s)
|
|
}
|
|
sort.Strings(syms)
|
|
for _, s := range syms {
|
|
testutil.Ok(t, iw.AddSymbol(s))
|
|
}
|
|
|
|
// Population procedure as done by compaction.
|
|
var (
|
|
postings = NewMemPostings()
|
|
values = map[string]map[string]struct{}{}
|
|
)
|
|
|
|
mi := newMockIndex()
|
|
|
|
for i, s := range input {
|
|
err = iw.AddSeries(uint64(i), s.labels, s.chunks...)
|
|
testutil.Ok(t, err)
|
|
testutil.Ok(t, mi.AddSeries(uint64(i), s.labels, s.chunks...))
|
|
|
|
for _, l := range s.labels {
|
|
valset, ok := values[l.Name]
|
|
if !ok {
|
|
valset = map[string]struct{}{}
|
|
values[l.Name] = valset
|
|
}
|
|
valset[l.Value] = struct{}{}
|
|
}
|
|
postings.Add(uint64(i), s.labels)
|
|
}
|
|
|
|
err = iw.Close()
|
|
testutil.Ok(t, err)
|
|
|
|
ir, err := NewFileReader(filepath.Join(dir, indexFilename))
|
|
testutil.Ok(t, err)
|
|
|
|
for p := range mi.postings {
|
|
gotp, err := ir.Postings(p.Name, p.Value)
|
|
testutil.Ok(t, err)
|
|
|
|
expp, err := mi.Postings(p.Name, p.Value)
|
|
testutil.Ok(t, err)
|
|
|
|
var lset, explset labels.Labels
|
|
var chks, expchks []chunks.Meta
|
|
|
|
for gotp.Next() {
|
|
testutil.Assert(t, expp.Next() == true, "")
|
|
|
|
ref := gotp.At()
|
|
|
|
err := ir.Series(ref, &lset, &chks)
|
|
testutil.Ok(t, err)
|
|
|
|
err = mi.Series(expp.At(), &explset, &expchks)
|
|
testutil.Ok(t, err)
|
|
testutil.Equals(t, explset, lset)
|
|
testutil.Equals(t, expchks, chks)
|
|
}
|
|
testutil.Assert(t, expp.Next() == false, "Expected no more postings for %q=%q", p.Name, p.Value)
|
|
testutil.Ok(t, gotp.Err())
|
|
}
|
|
|
|
labelPairs := map[string][]string{}
|
|
for l := range mi.postings {
|
|
labelPairs[l.Name] = append(labelPairs[l.Name], l.Value)
|
|
}
|
|
for k, v := range labelPairs {
|
|
sort.Strings(v)
|
|
|
|
res, err := ir.LabelValues(k)
|
|
testutil.Ok(t, err)
|
|
|
|
testutil.Equals(t, len(v), len(res))
|
|
for i := 0; i < len(v); i++ {
|
|
testutil.Equals(t, v[i], res[i])
|
|
}
|
|
}
|
|
|
|
gotSymbols := []string{}
|
|
it := ir.Symbols()
|
|
for it.Next() {
|
|
gotSymbols = append(gotSymbols, it.At())
|
|
}
|
|
testutil.Ok(t, it.Err())
|
|
expSymbols := []string{}
|
|
for s := range mi.symbols {
|
|
expSymbols = append(expSymbols, s)
|
|
}
|
|
sort.Strings(expSymbols)
|
|
testutil.Equals(t, expSymbols, gotSymbols)
|
|
|
|
testutil.Ok(t, ir.Close())
|
|
}
|
|
|
|
func TestDecbufUvarintWithInvalidBuffer(t *testing.T) {
|
|
b := realByteSlice([]byte{0x81, 0x81, 0x81, 0x81, 0x81, 0x81})
|
|
|
|
db := encoding.NewDecbufUvarintAt(b, 0, castagnoliTable)
|
|
testutil.NotOk(t, db.Err())
|
|
}
|
|
|
|
func TestReaderWithInvalidBuffer(t *testing.T) {
|
|
b := realByteSlice([]byte{0x81, 0x81, 0x81, 0x81, 0x81, 0x81})
|
|
|
|
_, err := NewReader(b)
|
|
testutil.NotOk(t, err)
|
|
}
|
|
|
|
// TestNewFileReaderErrorNoOpenFiles ensures that in case of an error no file remains open.
|
|
func TestNewFileReaderErrorNoOpenFiles(t *testing.T) {
|
|
dir := testutil.NewTemporaryDirectory("block", t)
|
|
|
|
idxName := filepath.Join(dir.Path(), "index")
|
|
err := ioutil.WriteFile(idxName, []byte("corrupted contents"), 0644)
|
|
testutil.Ok(t, err)
|
|
|
|
_, err = NewFileReader(idxName)
|
|
testutil.NotOk(t, err)
|
|
|
|
// dir.Close will fail on Win if idxName fd is not closed on error path.
|
|
dir.Close()
|
|
}
|