wp
This commit is contained in:
136
storage/cursor.go
Normal file
136
storage/cursor.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
bin "gordenko.dev/dima/bin/little"
|
||||
"gordenko.dev/dima/qb"
|
||||
)
|
||||
|
||||
type BackwardCursor struct {
|
||||
metricType qb.MetricType
|
||||
fracDigits byte
|
||||
fetchDataPage func(uint32) ([]byte, error)
|
||||
releasePage func(uint32)
|
||||
pageNo uint32
|
||||
pageData []byte
|
||||
timestampDecompressor qb.TimestampDecompressor
|
||||
valueDecompressor qb.ValueDecompressor
|
||||
}
|
||||
|
||||
type BackwardCursorOptions struct {
|
||||
MetricType qb.MetricType
|
||||
FracDigits byte
|
||||
PageNo uint32
|
||||
PageData []byte
|
||||
FetchDataPage func(uint32) ([]byte, error)
|
||||
ReleasePage func(uint32)
|
||||
}
|
||||
|
||||
func NewBackwardCursor(opt BackwardCursorOptions) (*BackwardCursor, error) {
|
||||
switch opt.MetricType {
|
||||
case qb.Instant, qb.Cumulative:
|
||||
// ok
|
||||
default:
|
||||
return nil, fmt.Errorf("MetricType option has wrong value: %d", opt.MetricType)
|
||||
}
|
||||
if opt.FracDigits > qb.MaxFracDigits {
|
||||
return nil, errors.New("FracDigits option is required")
|
||||
}
|
||||
if opt.FetchDataPage == nil {
|
||||
return nil, errors.New("FetchDataPage option is required")
|
||||
}
|
||||
if opt.ReleasePage == nil {
|
||||
return nil, errors.New("ReleasePage option is required")
|
||||
}
|
||||
if opt.PageNo == 0 {
|
||||
return nil, errors.New("PageNo option is required")
|
||||
}
|
||||
if len(opt.PageData) == 0 {
|
||||
return nil, errors.New("PageData option is required")
|
||||
}
|
||||
s := &BackwardCursor{
|
||||
metricType: opt.MetricType,
|
||||
fracDigits: opt.FracDigits,
|
||||
fetchDataPage: opt.FetchDataPage,
|
||||
releasePage: opt.ReleasePage,
|
||||
pageNo: opt.PageNo,
|
||||
pageData: opt.PageData,
|
||||
}
|
||||
var err error
|
||||
s.timestampDecompressor, err = CreateTimestampDecompressor(s.pageData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateTimestampDecompressor: %s", err)
|
||||
}
|
||||
s.valueDecompressor, err = CreateValueDecompressor(s.pageData, s.metricType, s.fracDigits)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateValueDecompressor: %s", err)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// timestamp, value, done, error
|
||||
func (s *BackwardCursor) Prev() (uint32, float64, bool, error) {
|
||||
var (
|
||||
timestamp uint32
|
||||
value float64
|
||||
done bool
|
||||
err error
|
||||
)
|
||||
timestamp, done = s.timestampDecompressor.NextValue()
|
||||
if !done {
|
||||
value, done = s.valueDecompressor.NextValue()
|
||||
if done {
|
||||
return 0, 0, false,
|
||||
fmt.Errorf("corrupted data page %d: has timestamp, no value",
|
||||
s.pageNo)
|
||||
}
|
||||
return timestamp, value, false, nil
|
||||
}
|
||||
|
||||
prevPageNo, _ := bin.GetUint32(s.pageData[prevPageIdx:])
|
||||
if prevPageNo == 0 {
|
||||
return 0, 0, true, nil
|
||||
}
|
||||
s.releasePage(s.pageNo)
|
||||
|
||||
s.pageNo = prevPageNo
|
||||
s.pageData, err = s.fetchDataPage(s.pageNo)
|
||||
if err != nil {
|
||||
return 0, 0, false,
|
||||
fmt.Errorf("fetchDataPage(%d): %s", s.pageNo, err)
|
||||
}
|
||||
s.timestampDecompressor, err = CreateTimestampDecompressor(s.pageData)
|
||||
if err != nil {
|
||||
return 0, 0, false,
|
||||
fmt.Errorf("CreateTimestampDecompressor: %s", err)
|
||||
}
|
||||
s.valueDecompressor, err = CreateValueDecompressor(s.pageData, s.metricType, s.fracDigits)
|
||||
if err != nil {
|
||||
return 0, 0, false,
|
||||
fmt.Errorf("CreateValueDecompressor: %s", err)
|
||||
}
|
||||
//
|
||||
timestamp, done = s.timestampDecompressor.NextValue()
|
||||
if done {
|
||||
return 0, 0, false,
|
||||
fmt.Errorf("corrupted data page %d: no timestamps", s.pageNo)
|
||||
}
|
||||
value, done = s.valueDecompressor.NextValue()
|
||||
if done {
|
||||
return 0, 0, false,
|
||||
fmt.Errorf("corrupted data page %d: no values", s.pageNo)
|
||||
}
|
||||
return timestamp, value, false, nil
|
||||
}
|
||||
|
||||
func (s *BackwardCursor) Close() {
|
||||
s.releasePage(s.pageNo)
|
||||
}
|
||||
|
||||
// HELPER
|
||||
|
||||
//func (s *BackwardCursor) makeDecompressors() error {
|
||||
|
||||
//}
|
||||
Reference in New Issue
Block a user