From efb0dfe1be5391cfb6403fffd4e4d0653add1930 Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Sun, 26 Mar 2017 23:40:12 +0530 Subject: [PATCH] Implement Postings Iterator Over Bytes Closes fabxc/tsdb#18 --- index.go | 17 ++++------------- postings.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/index.go b/index.go index d0e557dd6..c012b7c76 100644 --- a/index.go +++ b/index.go @@ -698,20 +698,11 @@ func (r *indexReader) Postings(name, value string) (Postings, error) { return nil, errors.Wrapf(errInvalidFlag, "section at %d", off) } - // TODO(fabxc): just read into memory as an intermediate solution. - // Add iterator over serialized data. - var l []uint32 - - for len(b) > 0 { - if len(b) < 4 { - return nil, errors.Wrap(errInvalidSize, "plain postings entry") - } - l = append(l, binary.BigEndian.Uint32(b[:4])) - - b = b[4:] + // Add iterator over the bytes. + if len(b)%4 != 0 { + return nil, errors.Wrap(errInvalidSize, "plain postings entry") } - - return &listPostings{list: l, idx: -1}, nil + return newBytePostings(b), nil } type stringTuples struct { diff --git a/postings.go b/postings.go index b3afe831a..3d6e32759 100644 --- a/postings.go +++ b/postings.go @@ -1,6 +1,7 @@ package tsdb import ( + "encoding/binary" "sort" "strings" ) @@ -240,6 +241,40 @@ func (it *listPostings) Err() error { return nil } +type bytePostings struct { + list []byte + idx int +} + +func newBytePostings(list []byte) *bytePostings { + return &bytePostings{list: list, idx: -1} +} + +func (it *bytePostings) At() uint32 { + idx := 4 * it.idx + return binary.BigEndian.Uint32(it.list[idx : idx+4]) +} + +func (it *bytePostings) Next() bool { + it.idx++ + return it.idx*4 < len(it.list) +} + +func (it *bytePostings) Seek(x uint32) bool { + num := len(it.list) / 4 + // Do binary search between current position and end. + it.idx += sort.Search(num-it.idx, func(i int) bool { + idx := 4 * (it.idx + i) + val := binary.BigEndian.Uint32(it.list[idx : idx+4]) + return val >= x + }) + return it.idx*4 < len(it.list) +} + +func (it *bytePostings) Err() error { + return nil +} + type stringset map[string]struct{} func (ss stringset) set(s string) {