prometheus/postings.go

266 lines
4.8 KiB
Go
Raw Normal View History

2016-12-04 12:16:11 +00:00
package tsdb
import (
"sort"
"strings"
)
2016-12-04 12:16:11 +00:00
2016-12-22 00:12:28 +00:00
type memPostings struct {
m map[term][]uint32
2016-12-10 08:44:00 +00:00
}
type term struct {
name, value string
2016-12-04 12:16:11 +00:00
}
// Postings returns an iterator over the postings list for s.
2016-12-14 20:58:29 +00:00
func (p *memPostings) get(t term) Postings {
l := p.m[t]
if l == nil {
return emptyPostings
}
return &listPostings{list: l, idx: -1}
}
// add adds a document to the index. The caller has to ensure that no
// term argument appears twice.
2016-12-10 08:44:00 +00:00
func (p *memPostings) add(id uint32, terms ...term) {
for _, t := range terms {
p.m[t] = append(p.m[t], id)
}
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
// Postings provides iterative access over a postings list.
type Postings interface {
2016-12-13 14:26:58 +00:00
// Next advances the iterator and returns true if another value was found.
2016-12-04 12:16:11 +00:00
Next() bool
2016-12-13 14:26:58 +00:00
2016-12-04 12:16:11 +00:00
// Seek advances the iterator to value v or greater and returns
// true if a value was found.
Seek(v uint32) bool
2016-12-13 14:26:58 +00:00
2017-01-02 12:27:52 +00:00
// At returns the value at the current iterator position.
At() uint32
2016-12-13 14:26:58 +00:00
// Err returns the last error of the iterator.
Err() error
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
// errPostings is an empty iterator that always errors.
type errPostings struct {
2016-12-13 14:26:58 +00:00
err error
}
2016-12-14 20:58:29 +00:00
func (e errPostings) Next() bool { return false }
func (e errPostings) Seek(uint32) bool { return false }
2017-01-02 12:27:52 +00:00
func (e errPostings) At() uint32 { return 0 }
2016-12-14 20:58:29 +00:00
func (e errPostings) Err() error { return e.err }
2016-12-13 14:26:58 +00:00
2016-12-27 10:32:10 +00:00
func expandPostings(p Postings) (res []uint32, err error) {
for p.Next() {
2017-01-02 12:27:52 +00:00
res = append(res, p.At())
2016-12-27 10:32:10 +00:00
}
return res, p.Err()
}
2016-12-14 20:58:29 +00:00
// Intersect returns a new postings list over the intersection of the
// input postings.
func Intersect(its ...Postings) Postings {
2016-12-04 12:16:11 +00:00
if len(its) == 0 {
2016-12-14 20:58:29 +00:00
return errPostings{err: nil}
2016-12-04 12:16:11 +00:00
}
a := its[0]
for _, b := range its[1:] {
2016-12-27 10:32:10 +00:00
a = newIntersectPostings(a, b)
2016-12-04 12:16:11 +00:00
}
return a
}
2016-12-28 10:02:19 +00:00
var emptyPostings = errPostings{}
2016-12-14 20:58:29 +00:00
type intersectPostings struct {
2016-12-27 10:32:10 +00:00
a, b Postings
aok, bok bool
cur uint32
}
func newIntersectPostings(a, b Postings) *intersectPostings {
it := &intersectPostings{a: a, b: b}
it.aok = it.a.Next()
it.bok = it.b.Next()
return it
2016-12-04 12:16:11 +00:00
}
2017-01-02 12:27:52 +00:00
func (it *intersectPostings) At() uint32 {
2016-12-27 10:32:10 +00:00
return it.cur
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
func (it *intersectPostings) Next() bool {
2016-12-27 10:32:10 +00:00
for {
if !it.aok || !it.bok {
return false
}
2017-01-02 12:27:52 +00:00
av, bv := it.a.At(), it.b.At()
2016-12-27 10:32:10 +00:00
if av < bv {
it.aok = it.a.Seek(bv)
} else if bv < av {
it.bok = it.b.Seek(av)
} else {
it.cur = av
it.aok = it.a.Next()
it.bok = it.b.Next()
return true
}
}
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
func (it *intersectPostings) Seek(id uint32) bool {
2016-12-27 10:32:10 +00:00
it.aok = it.a.Seek(id)
it.bok = it.b.Seek(id)
return it.Next()
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
func (it *intersectPostings) Err() error {
2016-12-27 10:32:10 +00:00
if it.a.Err() != nil {
return it.a.Err()
}
return it.b.Err()
2016-12-13 14:26:58 +00:00
}
2016-12-04 12:16:11 +00:00
// Merge returns a new iterator over the union of the input iterators.
2016-12-14 20:58:29 +00:00
func Merge(its ...Postings) Postings {
2016-12-04 12:16:11 +00:00
if len(its) == 0 {
return nil
}
a := its[0]
for _, b := range its[1:] {
2016-12-28 10:02:19 +00:00
a = newMergePostings(a, b)
2016-12-04 12:16:11 +00:00
}
return a
}
2016-12-14 20:58:29 +00:00
type mergePostings struct {
2016-12-28 10:02:19 +00:00
a, b Postings
aok, bok bool
cur uint32
}
func newMergePostings(a, b Postings) *mergePostings {
it := &mergePostings{a: a, b: b}
it.aok = it.a.Next()
it.bok = it.b.Next()
return it
2016-12-04 12:16:11 +00:00
}
2017-01-02 12:27:52 +00:00
func (it *mergePostings) At() uint32 {
2016-12-28 10:02:19 +00:00
return it.cur
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
func (it *mergePostings) Next() bool {
2016-12-28 10:02:19 +00:00
if !it.aok && !it.bok {
return false
}
if !it.aok {
2017-01-02 12:27:52 +00:00
it.cur = it.b.At()
2016-12-28 10:02:19 +00:00
it.bok = it.b.Next()
return true
}
if !it.bok {
2017-01-02 12:27:52 +00:00
it.cur = it.a.At()
2016-12-28 10:02:19 +00:00
it.aok = it.a.Next()
return true
}
2017-01-02 12:27:52 +00:00
acur, bcur := it.a.At(), it.b.At()
2016-12-28 10:02:19 +00:00
if acur < bcur {
it.cur = acur
it.aok = it.a.Next()
return true
}
if bcur < acur {
it.cur = bcur
it.bok = it.b.Next()
return true
}
it.cur = acur
it.aok = it.a.Next()
it.bok = it.b.Next()
return true
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
func (it *mergePostings) Seek(id uint32) bool {
2016-12-28 10:02:19 +00:00
it.aok = it.a.Seek(id)
it.bok = it.b.Seek(id)
return it.Next()
2016-12-04 12:16:11 +00:00
}
2016-12-14 20:58:29 +00:00
func (it *mergePostings) Err() error {
2016-12-28 10:02:19 +00:00
if it.a.Err() != nil {
return it.a.Err()
}
return it.b.Err()
2016-12-13 14:26:58 +00:00
}
2016-12-19 10:44:11 +00:00
// listPostings implements the Postings interface over a plain list.
type listPostings struct {
2016-12-04 12:16:11 +00:00
list []uint32
idx int
}
func newListPostings(list []uint32) *listPostings {
return &listPostings{list: list, idx: -1}
}
2017-01-02 12:27:52 +00:00
func (it *listPostings) At() uint32 {
2016-12-04 12:16:11 +00:00
return it.list[it.idx]
}
2016-12-19 10:44:11 +00:00
func (it *listPostings) Next() bool {
2016-12-04 12:16:11 +00:00
it.idx++
return it.idx < len(it.list)
}
2016-12-19 10:44:11 +00:00
func (it *listPostings) Seek(x uint32) bool {
2016-12-04 12:16:11 +00:00
// Do binary search between current position and end.
it.idx += sort.Search(len(it.list)-it.idx, func(i int) bool {
2016-12-04 12:16:11 +00:00
return it.list[i+it.idx] >= x
})
return it.idx < len(it.list)
}
2016-12-19 10:44:11 +00:00
func (it *listPostings) Err() error {
2016-12-13 14:26:58 +00:00
return nil
}
type stringset map[string]struct{}
func (ss stringset) set(s string) {
ss[s] = struct{}{}
}
func (ss stringset) has(s string) bool {
_, ok := ss[s]
return ok
}
func (ss stringset) String() string {
return strings.Join(ss.slice(), ",")
}
func (ss stringset) slice() []string {
slice := make([]string, 0, len(ss))
for k := range ss {
slice = append(slice, k)
}
sort.Strings(slice)
return slice
}