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 {
|
||||
|
||||
//}
|
||||
107
storage/misc.go
107
storage/misc.go
@@ -6,87 +6,50 @@ import (
|
||||
bin "gordenko.dev/dima/bin/little"
|
||||
"gordenko.dev/dima/qb"
|
||||
"gordenko.dev/dima/qb/enc"
|
||||
"gordenko.dev/dima/qb/util"
|
||||
)
|
||||
|
||||
// func (s *BackwardCursor) makeDecompressors() error {
|
||||
// timestampsSize, _ := bin.GetUint16(s.pageData[timestampsSizeIdx:])
|
||||
// valuesSize, _ := bin.GetUint16(s.pageData[valuesSizeIdx:])
|
||||
|
||||
// payloadSize := timestampsSize + valuesSize
|
||||
|
||||
// if payloadSize > dataFooterIdx {
|
||||
// return fmt.Errorf("corrupted data page %d: timestamps + values size %d gt payload size",
|
||||
// s.pageNo, payloadSize)
|
||||
// }
|
||||
|
||||
// s.timestampDecompressor = enc.NewTimeDeltaDecompressor(
|
||||
// s.pageData[:timestampsSize],
|
||||
// )
|
||||
|
||||
// vbuf := s.pageData[timestampsSize : timestampsSize+valuesSize]
|
||||
|
||||
// switch s.metricType {
|
||||
// case qb.Instant:
|
||||
// s.valueDecompressor = enc.NewInstantDeltaDecompressor(
|
||||
// vbuf, s.fracDigits)
|
||||
|
||||
// case qb.Cumulative:
|
||||
// s.valueDecompressor = enc.NewCumulativeDeltaDecompressor(
|
||||
// vbuf, s.fracDigits)
|
||||
|
||||
// default:
|
||||
// return fmt.Errorf("bug: wrong metricType %d", s.metricType)
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func makeDecompressors(pageData []byte, metricType qb.MetricType, fracDigits byte) (
|
||||
qb.TimestampDecompressor, qb.ValueDecompressor, error,
|
||||
) {
|
||||
|
||||
valuesSize, _ := bin.GetUint16(pageData[valuesSizeIdx:])
|
||||
|
||||
payloadSize := timestampsSize + valuesSize
|
||||
|
||||
if payloadSize > dataFooterIdx {
|
||||
return nil, nil, fmt.Errorf("corrupted: timestamps + values size %d > payload size",
|
||||
payloadSize)
|
||||
}
|
||||
|
||||
timestampDecompressor := enc.NewTimeDeltaDecompressor(
|
||||
pageData[:timestampsSize],
|
||||
)
|
||||
|
||||
vbuf := pageData[timestampsSize : timestampsSize+valuesSize]
|
||||
|
||||
var valueDecompressor qb.ValueDecompressor
|
||||
switch metricType {
|
||||
case qb.Instant:
|
||||
valueDecompressor = enc.NewInstantDeltaDecompressor(
|
||||
vbuf, fracDigits)
|
||||
|
||||
case qb.Cumulative:
|
||||
valueDecompressor = enc.NewCumulativeDeltaDecompressor(
|
||||
vbuf, fracDigits)
|
||||
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("bug: wrong metricType %d", metricType)
|
||||
}
|
||||
return timestampDecompressor, valueDecompressor, nil
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
func CreateTimeDeltaDecompressor(page []byte) qb.TimestampDecompressor {
|
||||
func CreateTimestampDecompressor(page []byte) (qb.TimestampDecompressor, error) {
|
||||
size, _ := bin.GetUint16(page[timestampsSizeIdx:])
|
||||
if size > DataPageFooterSize {
|
||||
return nil, fmt.Errorf("bug: invalid timestamps size %d", size)
|
||||
}
|
||||
pos := DataPagePayloadSize - int(size)
|
||||
d := enc.NewTimeDeltaDecompressor()
|
||||
d.RestoreFromEnd(page[pos:DataPagePayloadSize])
|
||||
return d
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func CreateValueDeltaDecompressor(page []byte, metricType qb.MetricType, fracDigits byte) qb.ValueDecompressor {
|
||||
func CreateValueDecompressor(page []byte, metricType qb.MetricType, fracDigits byte) (qb.ValueDecompressor, error) {
|
||||
size, _ := bin.GetUint16(page[valuesSizeIdx:])
|
||||
if size > DataPageFooterSize {
|
||||
return nil, fmt.Errorf("bug: invalid timestamps size %d", size)
|
||||
}
|
||||
d := enc.NewValueDeltaDecompressor(metricType, fracDigits)
|
||||
d.RestoreFromEnd(page[:size])
|
||||
return d
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func VerifyDataPageCRC32(data []byte) error {
|
||||
var (
|
||||
calculatedCRC = util.CalculateCRC32(data[:dataCRC32Idx])
|
||||
writtenCRC, _ = bin.GetUint32(data[dataCRC32Idx:])
|
||||
)
|
||||
if calculatedCRC != writtenCRC {
|
||||
return fmt.Errorf("calculated CRC32 %d are not equal written CRC32 %d",
|
||||
calculatedCRC, writtenCRC)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyIndexPageCRC32(data []byte) error {
|
||||
var (
|
||||
calculatedCRC = util.CalculateCRC32(data[:indexCRC32Idx])
|
||||
writtenCRC, _ = bin.GetUint32(data[indexCRC32Idx:])
|
||||
)
|
||||
if calculatedCRC != writtenCRC {
|
||||
return fmt.Errorf("calculated CRC32 %d are not equal written CRC32 %d",
|
||||
calculatedCRC, writtenCRC)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
214
storage/navigation.go
Normal file
214
storage/navigation.go
Normal file
@@ -0,0 +1,214 @@
|
||||
package storage
|
||||
|
||||
import bin "gordenko.dev/dima/bin/little"
|
||||
|
||||
const (
|
||||
PageNoSize = 4
|
||||
)
|
||||
|
||||
type KeyComparator interface {
|
||||
CompareTo(int) int
|
||||
}
|
||||
|
||||
type ValueAtComparator struct {
|
||||
buf []byte
|
||||
timestamp uint32
|
||||
}
|
||||
|
||||
func (s ValueAtComparator) CompareTo(elemIdx int) int {
|
||||
var (
|
||||
pos = elemIdx * IndexRecordSize
|
||||
elem, _ = bin.GetUint32(s.buf[pos:])
|
||||
)
|
||||
|
||||
if s.timestamp < elem {
|
||||
return -1
|
||||
} else if s.timestamp > elem {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func BinarySearch(qty int, keyComparator KeyComparator) (elemIdx int, isFound bool) {
|
||||
if qty == 0 {
|
||||
return
|
||||
}
|
||||
a := 0
|
||||
b := qty - 1
|
||||
for {
|
||||
var (
|
||||
elemIdx = (b-a)/2 + a
|
||||
code = keyComparator.CompareTo(elemIdx)
|
||||
)
|
||||
if code == 1 {
|
||||
a = elemIdx + 1
|
||||
if a > b {
|
||||
return elemIdx, false // +1
|
||||
}
|
||||
} else if code == -1 {
|
||||
b = elemIdx - 1
|
||||
if b < a {
|
||||
if elemIdx == 0 {
|
||||
return 0, false
|
||||
} else {
|
||||
return elemIdx - 1, false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return elemIdx, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// func getPrevPageNo(buf []byte) uint32 {
|
||||
// pageNo, _ := bin.GetUint32(buf[prevPageIdx:])
|
||||
// return pageNo
|
||||
// }
|
||||
|
||||
// func GetIndexRecordsSince(buf []byte) (pageNo uint32) {
|
||||
// pageNo, _ = bin.GetUint32(buf)
|
||||
// return
|
||||
// }
|
||||
|
||||
func FindPageOnIndexLevelTail(level IndexLevelTail, timestamp uint32) (pageNo uint32) {
|
||||
comparator := ValueAtComparator{
|
||||
buf: level.Buffer,
|
||||
timestamp: timestamp,
|
||||
}
|
||||
elemIdx, _ := BinarySearch(level.RecordsCount, comparator)
|
||||
pos := elemIdx*IndexRecordSize + 4 // timestamp size
|
||||
pageNo, _ = bin.GetUint32(level.Buffer[pos:])
|
||||
return
|
||||
}
|
||||
|
||||
// func FindPageOnRecords(records []byte, timestamp uint32) (pageNo uint32) {
|
||||
// comparator := ValueAtComparator{
|
||||
// buf: records,
|
||||
// timestamp: timestamp,
|
||||
// }
|
||||
// count := len(records) / IndexRecordSize
|
||||
// elemIdx, _ := BinarySearch(count, comparator)
|
||||
// pageNo, _ = bin.GetUint32(records[elemIdx*IndexRecordSize:])
|
||||
// return
|
||||
// }
|
||||
|
||||
func FindPageOnIndexPage(page []byte, timestamp uint32) (pageNo uint32) {
|
||||
comparator := ValueAtComparator{
|
||||
buf: page,
|
||||
timestamp: timestamp,
|
||||
}
|
||||
count, _ := bin.GetUint16(page[indexRecordsCountIdx:])
|
||||
elemIdx, _ := BinarySearch(int(count), comparator)
|
||||
pos := elemIdx*IndexRecordSize + 4 // timestamp size
|
||||
pageNo, _ = bin.GetUint32(page[pos:])
|
||||
return
|
||||
}
|
||||
|
||||
func IsZeroLevelPage(buf []byte) bool {
|
||||
return buf[isZeroLevelIdx] == 1
|
||||
}
|
||||
|
||||
// можна перевірити хвости від 0 до ... Перевіряю since кожного хвоста.
|
||||
// Якщо timestamp >=, шукаю pageNo бінарним пошуком. І сторінка мені однозначно підходить.
|
||||
// Якщо timestamp <, піднімаюсь вище. Якщо рівнів більше немає - until вказано за межами Range показань.
|
||||
func FindPageOnIndexLevelTails(levels []IndexLevelTail, timestamp uint32) (pageNo uint32, isDataPage bool) {
|
||||
for i, level := range levels {
|
||||
tailSince, _ := bin.GetUint32(level.Buffer)
|
||||
if timestamp >= tailSince {
|
||||
pageNo = FindPageOnIndexLevelTail(level, timestamp)
|
||||
return pageNo, i == 0
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// func findPageNoIdx(buf []byte, timestamp uint32) (idx int) {
|
||||
// comparator := ValueAtComparator{
|
||||
// buf: buf,
|
||||
// timestamp: timestamp,
|
||||
// }
|
||||
// qty, _ := bin.GetUint16(buf[indexRecordsQtyIdx:])
|
||||
// elemIdx, _ := BinarySearch(int(qty), comparator)
|
||||
// return elemIdx
|
||||
// }
|
||||
|
||||
// func findPageNoForDeleteSince(buf []byte, since uint32) (uint32, int, int) {
|
||||
// comparator := ValueAtComparator{
|
||||
// buf: buf,
|
||||
// timestamp: since,
|
||||
// }
|
||||
// qty, _ := bin.GetUint16(buf[indexRecordsQtyIdx:])
|
||||
// elemIdx, _ := BinarySearch(int(qty), comparator)
|
||||
// pos := elemIdx * timestampSize
|
||||
// timestamp, _ := bin.GetUint32(buf[pos:])
|
||||
|
||||
// if timestamp == since {
|
||||
// if elemIdx == 0 {
|
||||
// return 0, int(qty), -1
|
||||
// }
|
||||
// elemIdx--
|
||||
// }
|
||||
// pos = indexFooterIdx - (elemIdx+1)*PageNoSize
|
||||
// pageNo, _ := bin.GetUint32(buf[pos:])
|
||||
// return pageNo, int(qty), elemIdx
|
||||
// }
|
||||
|
||||
// func getLastPageNo(buf []byte) (pageNo uint32) {
|
||||
// qty, _ := bin.GetUint16(buf[indexRecordsQtyIdx:])
|
||||
// pos := indexFooterIdx - qty*PageNoSize
|
||||
// pageNo, _ = bin.GetUint32(buf[pos:])
|
||||
// return
|
||||
// }
|
||||
|
||||
// func getPageNo(buf []byte, idx int) (pageNo uint32) {
|
||||
// pos := indexFooterIdx - (idx+1)*PageNoSize
|
||||
// pageNo, _ = bin.GetUint32(buf[pos:])
|
||||
// return
|
||||
// }
|
||||
|
||||
// func listPageNumbers(buf []byte) (pageNumbers []uint32) {
|
||||
// qty, _ := bin.GetUint16(buf[indexRecordsQtyIdx:])
|
||||
// pos := indexFooterIdx - PageNoSize
|
||||
// for range qty {
|
||||
// pageNo, _ := bin.GetUint32(buf[pos:])
|
||||
// pageNumbers = append(pageNumbers, pageNo)
|
||||
// pos -= PageNoSize
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
// // include since timestamp
|
||||
// func listPageNumbersSince(buf []byte, timestamp uint32) (pageNumbers []uint32) {
|
||||
// comparator := ValueAtComparator{
|
||||
// buf: buf,
|
||||
// timestamp: timestamp,
|
||||
// }
|
||||
// qty, _ := bin.GetUint16(buf[indexRecordsQtyIdx:])
|
||||
// elemIdx, _ := BinarySearch(int(qty), comparator)
|
||||
// pos := indexFooterIdx - (elemIdx+1)*PageNoSize
|
||||
// for range qty {
|
||||
// pageNo, _ := bin.GetUint32(buf[pos:])
|
||||
// pageNumbers = append(pageNumbers, pageNo)
|
||||
// pos -= PageNoSize
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
|
||||
// func getSince(buf []byte) uint32 {
|
||||
// return bin.GetUint32(buf[0:])
|
||||
// }
|
||||
|
||||
// func appendPair(buf []byte, timestamp uint32, pageNo uint32) bool {
|
||||
// qty := bin.GetUint16AsInt(buf[indexRecordsQtyIdx:])
|
||||
// free := indexFooterIdx - qty*pairSize
|
||||
// if free < pairSize {
|
||||
// return false
|
||||
// }
|
||||
// pos := qty * timestampSize
|
||||
// bin.PutUint32(buf[pos:], timestamp)
|
||||
// pos = indexFooterIdx - (qty+1)*PageNoSize
|
||||
// bin.PutUint32(buf[pos:], pageNo)
|
||||
// bin.PutIntAsUint16(buf[indexRecordsQtyIdx:], qty+1)
|
||||
// return true
|
||||
// }
|
||||
@@ -9,7 +9,7 @@ var (
|
||||
// data page
|
||||
DataPageSize = 8192
|
||||
|
||||
DataPagePayloadSize int = DataPageSize - DataPageFooterSize
|
||||
DataPagePayloadSize = DataPageSize - DataPageFooterSize
|
||||
|
||||
dataCRC32Idx = DataPageSize - 4
|
||||
timestampsSizeIdx = DataPageSize - 6
|
||||
@@ -19,6 +19,7 @@ var (
|
||||
// index page
|
||||
IndexPageSize = 1024
|
||||
|
||||
IndexPagePayloadSize = IndexPageSize - IndexPageFooterSize
|
||||
//indexPageIncSize = IndexPageIncSize
|
||||
indexCRC32Idx = IndexPageSize - 4
|
||||
indexRecordsCountIdx = IndexPageSize - 6
|
||||
@@ -28,7 +29,6 @@ var (
|
||||
|
||||
// timestampSize = 4
|
||||
// pairSize = timestampSize + PageNoSize
|
||||
// indexFooterIdx = indexRecordsQtyIdx
|
||||
// dataFooterIdx = timestampsSizeIdx
|
||||
)
|
||||
|
||||
|
||||
@@ -1081,3 +1081,74 @@ func TestReplayMetric(t *testing.T) {
|
||||
fmt.Printf("%d: % x\n", metric.IndexLevelTails[0].RecordsCount, metric.IndexLevelTails[0].Buffer)
|
||||
fmt.Printf("%d: % x\n", metric.IndexLevelTails[1].RecordsCount, metric.IndexLevelTails[1].Buffer)
|
||||
}
|
||||
|
||||
// func TestComposeHeadIndexPage(t *testing.T) {
|
||||
// var (
|
||||
// levelIdx = 0
|
||||
// level = storage.IndexLevelTail{
|
||||
// Buffer: []byte{
|
||||
// 1, 2, 3,
|
||||
// },
|
||||
// RecordsCount: 2,
|
||||
// }
|
||||
// head = &storage.IndexPageTail{
|
||||
// PageNo: 100,
|
||||
// CRC32: 12345,
|
||||
// Records: []byte{},
|
||||
// }
|
||||
// )
|
||||
// page := composeHeadIndexPage(levelIdx, level, head)
|
||||
// if page.PageNo != head.PageNo {
|
||||
// t.Fatalf("PageNo: got %d are not equal expected %v",
|
||||
// page.PageNo, head.PageNo)
|
||||
// }
|
||||
// // fix compare pages
|
||||
// }
|
||||
|
||||
func TestFindPageOnIndexTails(t *testing.T) {
|
||||
levels := []IndexLevelTail{
|
||||
{
|
||||
Buffer: []byte{
|
||||
0x64, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, // 100 => 10
|
||||
0x6e, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, // 110 => 11
|
||||
},
|
||||
RecordsCount: 2,
|
||||
},
|
||||
{
|
||||
Buffer: []byte{
|
||||
0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // 10 => 1
|
||||
0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, // 40 => 4
|
||||
0x46, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, // 70 => 7
|
||||
},
|
||||
RecordsCount: 3,
|
||||
},
|
||||
}
|
||||
testCases := []struct {
|
||||
Timestamp uint32
|
||||
PageNo uint32
|
||||
IsDataPage bool
|
||||
}{
|
||||
{Timestamp: 9, PageNo: 0, IsDataPage: false},
|
||||
{Timestamp: 10, PageNo: 1, IsDataPage: false},
|
||||
{Timestamp: 20, PageNo: 1, IsDataPage: false},
|
||||
{Timestamp: 40, PageNo: 4, IsDataPage: false},
|
||||
{Timestamp: 60, PageNo: 4, IsDataPage: false},
|
||||
{Timestamp: 70, PageNo: 7, IsDataPage: false},
|
||||
{Timestamp: 90, PageNo: 7, IsDataPage: false},
|
||||
{Timestamp: 100, PageNo: 10, IsDataPage: true},
|
||||
{Timestamp: 105, PageNo: 10, IsDataPage: true},
|
||||
{Timestamp: 110, PageNo: 11, IsDataPage: true},
|
||||
{Timestamp: 120, PageNo: 11, IsDataPage: true},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
pageNo, isDataPage := FindPageOnIndexLevelTails(levels, testCase.Timestamp)
|
||||
if pageNo != testCase.PageNo {
|
||||
t.Fatalf("timestamp %d: got pageNo %d are not equal expected %d",
|
||||
testCase.Timestamp, pageNo, testCase.PageNo)
|
||||
}
|
||||
if isDataPage != testCase.IsDataPage {
|
||||
t.Fatalf("timestamp %d: got isDataPage %t are not equal expected %t",
|
||||
testCase.Timestamp, isDataPage, testCase.IsDataPage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,9 +365,6 @@ type PageToWrite struct {
|
||||
|
||||
func WriteDataPages(file *os.File, pages []PageToWrite) (err error) {
|
||||
for _, p := range pages {
|
||||
fmt.Println("pageNo: %d\n", p.PageNo)
|
||||
}
|
||||
for _, p := range pages {
|
||||
if len(p.Content) != DataPageSize {
|
||||
return fmt.Errorf("wrong data page size: %d", len(p.Content))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user