mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
tsdb: Fixed Symbol Lookup edge case; Added tests.
Signed-off-by: Bartlomiej Plotka <bwplotka@gmail.com>
This commit is contained in:
parent
4aef43a9f5
commit
59ea320d96
|
@ -1234,17 +1234,13 @@ func NewSymbols(bs ByteSlice, version int, off int) (*Symbols, error) {
|
||||||
version: version,
|
version: version,
|
||||||
off: off,
|
off: off,
|
||||||
}
|
}
|
||||||
if off == 0 {
|
|
||||||
// Only happens in some tests.
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
d := encoding.NewDecbufAt(bs, off, castagnoliTable)
|
d := encoding.NewDecbufAt(bs, off, castagnoliTable)
|
||||||
var (
|
var (
|
||||||
origLen = d.Len()
|
origLen = d.Len()
|
||||||
cnt = d.Be32int()
|
cnt = d.Be32int()
|
||||||
basePos = off + 4
|
basePos = off + 4
|
||||||
)
|
)
|
||||||
s.offsets = make([]int, 0, cnt/symbolFactor)
|
s.offsets = make([]int, 0, 1+cnt/symbolFactor)
|
||||||
for d.Err() == nil && s.seen < cnt {
|
for d.Err() == nil && s.seen < cnt {
|
||||||
if s.seen%symbolFactor == 0 {
|
if s.seen%symbolFactor == 0 {
|
||||||
s.offsets = append(s.offsets, basePos+origLen-d.Len())
|
s.offsets = append(s.offsets, basePos+origLen-d.Len())
|
||||||
|
@ -1262,8 +1258,9 @@ func (s Symbols) Lookup(o uint32) (string, error) {
|
||||||
d := encoding.Decbuf{
|
d := encoding.Decbuf{
|
||||||
B: s.bs.Range(0, s.bs.Len()),
|
B: s.bs.Range(0, s.bs.Len()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.version == FormatV2 {
|
if s.version == FormatV2 {
|
||||||
if int(o) > s.seen {
|
if int(o) >= s.seen {
|
||||||
return "", errors.Errorf("unknown symbol offset %d", o)
|
return "", errors.Errorf("unknown symbol offset %d", o)
|
||||||
}
|
}
|
||||||
d.Skip(s.offsets[int(o/symbolFactor)])
|
d.Skip(s.offsets[int(o/symbolFactor)])
|
||||||
|
|
|
@ -16,6 +16,7 @@ package index
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/crc32"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
@ -505,3 +506,50 @@ func TestNewFileReaderErrorNoOpenFiles(t *testing.T) {
|
||||||
// dir.Close will fail on Win if idxName fd is not closed on error path.
|
// dir.Close will fail on Win if idxName fd is not closed on error path.
|
||||||
dir.Close()
|
dir.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSymbols(t *testing.T) {
|
||||||
|
buf := encoding.Encbuf{}
|
||||||
|
|
||||||
|
// Add prefix to the buffer to simulate symbols as part of larger buffer.
|
||||||
|
buf.PutUvarintStr("something")
|
||||||
|
|
||||||
|
symbolsStart := buf.Len()
|
||||||
|
buf.PutBE32int(204) // Length of symbols table.
|
||||||
|
buf.PutBE32int(100) // Number of symbols.
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
// i represents index in unicode characters table.
|
||||||
|
buf.PutUvarintStr(string(i)) // Symbol.
|
||||||
|
}
|
||||||
|
checksum := crc32.Checksum(buf.Get()[symbolsStart+4:], castagnoliTable)
|
||||||
|
buf.PutBE32(checksum) // Check sum at the end.
|
||||||
|
|
||||||
|
s, err := NewSymbols(realByteSlice(buf.Get()), FormatV2, symbolsStart)
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
|
||||||
|
// We store only 4 offsets to symbols.
|
||||||
|
testutil.Equals(t, 32, s.Size())
|
||||||
|
|
||||||
|
for i := 99; i >= 0; i-- {
|
||||||
|
s, err := s.Lookup(uint32(i))
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
testutil.Equals(t, string(i), s)
|
||||||
|
}
|
||||||
|
_, err = s.Lookup(100)
|
||||||
|
testutil.NotOk(t, err)
|
||||||
|
|
||||||
|
for i := 99; i >= 0; i-- {
|
||||||
|
r, err := s.ReverseLookup(string(i))
|
||||||
|
testutil.Ok(t, err)
|
||||||
|
testutil.Equals(t, uint32(i), r)
|
||||||
|
}
|
||||||
|
_, err = s.ReverseLookup(string(100))
|
||||||
|
testutil.NotOk(t, err)
|
||||||
|
|
||||||
|
iter := s.Iter()
|
||||||
|
i := 0
|
||||||
|
for iter.Next() {
|
||||||
|
testutil.Equals(t, string(i), iter.At())
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
testutil.Ok(t, iter.Err())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue