prometheus/index/page.go

109 lines
1.7 KiB
Go
Raw Normal View History

2016-11-15 14:53:48 +00:00
package index
import (
"encoding/binary"
"errors"
"io"
)
const pageSize = 2048
var errPageFull = errors.New("page full")
type pageCursor interface {
Iterator
append(v DocID) error
}
type page interface {
cursor() pageCursor
init(v DocID) error
data() []byte
}
type pageDelta struct {
b []byte
}
type pageType uint8
const (
pageTypeDelta pageType = iota
)
func newPageDelta(data []byte) *pageDelta {
return &pageDelta{b: data}
}
func (p *pageDelta) init(v DocID) error {
// Write first value.
binary.PutUvarint(p.b, uint64(v))
return nil
}
func (p *pageDelta) cursor() pageCursor {
return &pageDeltaCursor{data: p.b}
}
func (p *pageDelta) data() []byte {
return p.b
}
type pageDeltaCursor struct {
data []byte
pos int
cur DocID
}
func (p *pageDeltaCursor) append(id DocID) error {
// Run to the end.
_, err := p.Next()
for ; err == nil; _, err = p.Next() {
// Consume.
}
if err != io.EOF {
return err
}
if len(p.data)-p.pos < binary.MaxVarintLen64 {
return errPageFull
}
if p.cur >= id {
return errOutOfOrder
}
p.pos += binary.PutUvarint(p.data[p.pos:], uint64(id-p.cur))
p.cur = id
return nil
}
func (p *pageDeltaCursor) Close() error {
return nil
}
func (p *pageDeltaCursor) Seek(min DocID) (v DocID, err error) {
if min < p.cur {
p.pos = 0
}
for v, err = p.Next(); err == nil && v < min; v, err = p.Next() {
// Consume.
}
return p.cur, err
}
func (p *pageDeltaCursor) Next() (DocID, error) {
var n int
var dv uint64
if p.pos == 0 {
dv, n = binary.Uvarint(p.data)
p.cur = DocID(dv)
} else {
dv, n = binary.Uvarint(p.data[p.pos:])
if n <= 0 || dv == 0 {
return 0, io.EOF
}
p.cur += DocID(dv)
}
p.pos += n
return p.cur, nil
}