wp
This commit is contained in:
@@ -22,21 +22,27 @@ const (
|
||||
pageTypeIdx = PageSize - 5
|
||||
|
||||
// index page
|
||||
indexRecordsQtyIdx = PageSize - 8
|
||||
isDataPageNumbersIdx = PageSize - 6
|
||||
indexCRC32Idx = IndexPageSize - 4
|
||||
isLastLevelIdx = IndexPageSize - 5
|
||||
indexRecordsQtyIdx = IndexPageSize - 7
|
||||
|
||||
indexRecordSize = 8
|
||||
|
||||
// data page
|
||||
timestampsSizeIdx = PageSize - 13
|
||||
valuesSizeIdx = PageSize - 11
|
||||
prevPageIdx = PageSize - 9
|
||||
dataCRC32Idx = DataPageSize - 4
|
||||
prevPageIdx = DataPageSize - 8
|
||||
valuesSizeIdx = DataPageSize - 10
|
||||
timestampsSizeIdx = DataPageSize - 12
|
||||
|
||||
timestampSize = 4
|
||||
pairSize = timestampSize + PageNoSize
|
||||
indexFooterIdx = indexRecordsQtyIdx
|
||||
dataFooterIdx = timestampsSizeIdx
|
||||
|
||||
PageSize = 8192
|
||||
PageNoSize = 4
|
||||
PageSize = 8192
|
||||
DataPageSize = 8192
|
||||
IndexPageSize = 1024
|
||||
PageNoSize = 4
|
||||
//
|
||||
DataPagePayloadSize int = dataFooterIdx
|
||||
)
|
||||
@@ -161,7 +167,7 @@ func (s *Atree) findDataPage(rootPageNo uint32, timestamp uint32) (uint32, []byt
|
||||
s.releasePage(indexPageNo)
|
||||
|
||||
// fix
|
||||
if buf[isDataPageNumbersIdx] == 1 {
|
||||
if buf[isLastLevelIdx] == 1 {
|
||||
buf, err := s.fetchDataPage(foundPageNo)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("fetchDataPage(%d): %s", foundPageNo, err)
|
||||
@@ -206,7 +212,7 @@ func (s *Atree) FindPathToLastPage(rootPageNo uint32) (_ PathToDataPage, err err
|
||||
foundPageNo := getLastPageNo(buf)
|
||||
|
||||
// fix
|
||||
if buf[isDataPageNumbersIdx] == 1 {
|
||||
if buf[isLastLevelIdx] == 1 {
|
||||
return PathToDataPage{
|
||||
Legs: legs,
|
||||
LastPageNo: foundPageNo,
|
||||
|
||||
147
atree/x.go
Normal file
147
atree/x.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package atree
|
||||
|
||||
import "gordenko.dev/dima/qb/bin"
|
||||
|
||||
const (
|
||||
payloadSize = 24
|
||||
recordSize = 4 + 4 // timestamp + pageNo
|
||||
)
|
||||
|
||||
type DataPage struct {
|
||||
PrevPageNo uint32
|
||||
LowerTimestamp uint32
|
||||
Timestamps [][]byte // chunks
|
||||
TimestampsSize int
|
||||
Values [][]byte // chunks
|
||||
ValuesSize int
|
||||
PageNo uint32
|
||||
IsReused bool
|
||||
}
|
||||
|
||||
type IndexPage struct {
|
||||
LowerTimestamp uint32
|
||||
Data []byte
|
||||
PageNo uint32
|
||||
IsReused bool
|
||||
}
|
||||
type IndexLevel struct {
|
||||
// вже записані дані (лише для першої в списку індексної сторінки, беремо із _metric)
|
||||
// дані потрібні, якщо сторінка буде заповнена і піде на запис в .index файл
|
||||
Offset int // (заповнені одразу)
|
||||
LowerTimestamp uint32 // (заповнені одразу)
|
||||
Data []byte // поточні дані index сторінки (заповнені одразу)
|
||||
Filled []IndexPage // пусто
|
||||
}
|
||||
|
||||
func appendIndexRecord(data []byte, timestamp uint32, pageNo uint32) []byte {
|
||||
var tmp = []byte{
|
||||
0, 0, 0, 0, // timestamp
|
||||
0, 0, 0, 0, // pageNo
|
||||
}
|
||||
bin.PutUint32(tmp, timestamp)
|
||||
bin.PutUint32(tmp[4:], pageNo)
|
||||
return append(data, tmp...)
|
||||
}
|
||||
|
||||
type ChunksToDataPageReq struct {
|
||||
PrevPageNo uint32
|
||||
Timestamps [][]byte // chunks
|
||||
TimestampsSize uint16
|
||||
Values [][]byte // chunks
|
||||
ValuesSize uint16
|
||||
}
|
||||
|
||||
func ChunksToDataPage(buf []byte, req ChunksToDataPageReq) {
|
||||
var (
|
||||
remainingSize = int(req.TimestampsSize)
|
||||
pos = 0
|
||||
)
|
||||
for _, chunk := range req.Timestamps {
|
||||
if remainingSize >= len(chunk) {
|
||||
copy(buf[pos:], chunk)
|
||||
remainingSize -= len(chunk)
|
||||
pos += len(chunk)
|
||||
} else {
|
||||
copy(buf[pos:], chunk[:remainingSize])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
remainingSize = int(req.ValuesSize)
|
||||
pos = int(req.TimestampsSize)
|
||||
|
||||
for _, chunk := range req.Values {
|
||||
if remainingSize >= len(chunk) {
|
||||
copy(buf[pos:], chunk)
|
||||
remainingSize -= len(chunk)
|
||||
pos += len(chunk)
|
||||
} else {
|
||||
copy(buf[pos:], chunk[:remainingSize])
|
||||
break
|
||||
}
|
||||
}
|
||||
bin.PutUint16(buf[timestampsSizeIdx:], req.TimestampsSize)
|
||||
bin.PutUint16(buf[valuesSizeIdx:], req.ValuesSize)
|
||||
bin.PutUint32(buf[prevPageIdx:], req.PrevPageNo)
|
||||
bin.PutUint32(buf[dataCRC32Idx:], calcChecksum(buf[:dataCRC32Idx]))
|
||||
}
|
||||
|
||||
func DataToIndexPage(buf []byte, data []byte, lastLevel bool) {
|
||||
copy(buf, data)
|
||||
bin.PutUint16(buf[indexRecordsQtyIdx:], uint16(len(data)/indexRecordSize))
|
||||
if lastLevel {
|
||||
buf[isLastLevelIdx] = 1
|
||||
}
|
||||
bin.PutUint32(buf[indexCRC32Idx:], calcChecksum(buf[:indexCRC32Idx]))
|
||||
}
|
||||
|
||||
type Pager interface {
|
||||
GetPageNumber() (uint32, bool)
|
||||
}
|
||||
|
||||
func AppendDataPagesToTree(pager Pager, levels []*IndexLevel, dataPages []*DataPage) {
|
||||
for i, d := range dataPages[1:] {
|
||||
d.PageNo, d.IsReused = pager.GetPageNumber()
|
||||
d.PrevPageNo = dataPages[i-1].PageNo
|
||||
}
|
||||
|
||||
for _, d := range dataPages {
|
||||
var (
|
||||
upTimestamp = d.LowerTimestamp
|
||||
upPageNo = d.PageNo
|
||||
levelIdx = 0
|
||||
)
|
||||
for {
|
||||
if levelIdx == len(levels) {
|
||||
// encode prev page record + up*
|
||||
levels = append(levels, &IndexLevel{
|
||||
LowerTimestamp: upTimestamp,
|
||||
Data: appendIndexRecord(nil, upTimestamp, upPageNo),
|
||||
})
|
||||
break
|
||||
}
|
||||
level := levels[levelIdx]
|
||||
if len(level.Data)+recordSize <= payloadSize {
|
||||
level.Data = appendIndexRecord(level.Data, upTimestamp, upPageNo)
|
||||
break
|
||||
}
|
||||
// в буфері немає місця для додавання нової пари, отже це
|
||||
// заповнена сторінка
|
||||
filled := IndexPage{
|
||||
LowerTimestamp: level.LowerTimestamp,
|
||||
Data: level.Data,
|
||||
}
|
||||
filled.PageNo, filled.IsReused = pager.GetPageNumber()
|
||||
|
||||
level.Filled = append(level.Filled, filled)
|
||||
//
|
||||
level.LowerTimestamp = upTimestamp
|
||||
level.Data = appendIndexRecord(nil, upTimestamp, upPageNo)
|
||||
|
||||
//
|
||||
upPageNo = filled.PageNo
|
||||
upTimestamp = filled.LowerTimestamp
|
||||
levelIdx++
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user