This commit is contained in:
2026-06-05 19:43:01 +00:00
parent db5ecd3dfd
commit 05eea3b279
16 changed files with 1187 additions and 724 deletions

306
txlog/wal_records.go Normal file
View File

@@ -0,0 +1,306 @@
package txlog
import (
"bytes"
bin "gordenko.dev/dima/bin/little"
)
type CompletedDataPage struct {
PageNo uint32
Reused bool
PrevPageNo uint32
Checksum uint32
TimestampsOffset int // offset on 1st page
Timestamps []byte
ValuesOffset int // offset on 1st page
Values []byte
}
type CompletedIndexPage struct {
PageNo uint32
Reused bool
Checksum uint32
Records []byte // offset не потрібен, оскільки Records додаються в кінець
}
type ChangedIndexLevel struct {
CompletedIndexPage *CompletedIndexPage
IndexPages []SealedIndexPage
TailRecords []byte // payload only
}
type WALRecordAppendMeasures struct {
MetricID uint32
CompletedDataPage CompletedDataPage
DataPages []SealedDataPage
ChangedIndexLevels []ChangedIndexLevel
TailTimestamps []byte // data level tail
TailValues []byte // data level tail
}
/*
Format appended measures:
1b - tx type
4b - metricID
4b - pageNo
1b - reused
4b - prevPageNo
4b - page crc32
Nb - (varsize) timestamps offset
Nb - (varsize) timestamps tail size on 1st filled data page
Nb - timestamps tail on 1st filled data page
Nb - (varsize) values offset
Nb - (varsize) values tail size on 1st filled data page
Nb - values tail on 1st filled data page
Nb - (varsize) filled data pages qty
[
4b - pageNo
1b - reused
Nb - (data page size) page content
]
Nb - (varsize) timestamps payload size on tail
Nb - timestamps payload
Nb - (varsize) values payload size on tail
Nb - values payload
Nb - (varsize) qty of index levels
[
// NOTE!
// - idx = 0 - zeroLevel
// - skipped = maxRecordsOnIndexPage - records count
4b - pageNo of 1st index page
1b - reused
4b - page crc32
Nb - (varsize) records tail count on 1st filled index page
Nb - records tail on 1st filled index page
Nb - (varsize) qty of level filled pages
[
4b - pageNo
1b - reused
Nb - (index page size) page content
]
Nb - (varsize) size of records level tail
Nb - level tail records
]
*/
func (s WALRecordAppendMeasures) WriteTo(w *bytes.Buffer) {
w.WriteByte(CodeAppendedMeasures)
bin.WriteUint32(w, s.MetricID)
// completed data page
completed := s.CompletedDataPage
bin.WriteUint32(w, completed.PageNo)
bin.WriteBool(w, completed.Reused)
bin.WriteUint32(w, completed.PrevPageNo)
bin.WriteUint32(w, completed.Checksum)
bin.WriteVarSize(w, completed.TimestampsOffset)
bin.WriteVarSize(w, len(completed.Timestamps))
w.Write(completed.Timestamps)
bin.WriteVarSize(w, completed.ValuesOffset)
bin.WriteVarSize(w, len(completed.Values))
w.Write(completed.Values)
// data pages
bin.WriteVarSize(w, len(s.DataPages))
for _, p := range s.DataPages {
bin.WriteUint32(w, p.PageNo)
bin.WriteBool(w, p.Reused)
bin.WriteVarSize(w, len(p.Content))
w.Write(p.Content)
}
// data tail
bin.WriteVarSize(w, len(s.TailTimestamps))
w.Write(s.TailTimestamps)
bin.WriteVarSize(w, len(s.TailValues))
w.Write(s.TailValues)
// changed levels
bin.WriteVarSize(w, len(s.ChangedIndexLevels))
for _, level := range s.ChangedIndexLevels {
// completed index page
completed := level.CompletedIndexPage
bin.WriteUint32(w, completed.PageNo)
bin.WriteBool(w, completed.Reused)
bin.WriteUint32(w, completed.Checksum)
bin.WriteVarSize(w, len(completed.Records)/indexRecordSize)
w.Write(completed.Records)
// full index pages
for _, p := range level.IndexPages {
bin.WriteUint32(w, p.PageNo)
bin.WriteBool(w, p.Reused)
bin.WriteVarSize(w, len(p.Content))
w.Write(p.Content)
}
// level tail
bin.WriteVarSize(w, len(level.TailRecords)/indexRecordSize)
w.Write(level.TailRecords)
}
return
}
func (s *WALRecordAppendMeasures) Parse(r *bytes.Buffer) (err error) {
var (
size int
recordsCount int
)
s.MetricID, err = bin.ReadUint32(r)
if err != nil {
return
}
s.CompletedDataPage.PageNo, err = bin.ReadUint32(r)
if err != nil {
return
}
s.CompletedDataPage.Reused, err = bin.ReadBool(r)
if err != nil {
return
}
s.CompletedDataPage.PrevPageNo, err = bin.ReadUint32(r)
if err != nil {
return
}
s.CompletedDataPage.Checksum, err = bin.ReadUint32(r)
if err != nil {
return
}
s.CompletedDataPage.TimestampsOffset, err = bin.ReadVarSize(r)
if err != nil {
return
}
size, err = bin.ReadVarSize(r)
if err != nil {
return
}
s.CompletedDataPage.Timestamps, err = bin.ReadN(r, size)
if err != nil {
return
}
size, err = bin.ReadVarSize(r)
if err != nil {
return
}
s.CompletedDataPage.Values, err = bin.ReadN(r, size)
if err != nil {
return
}
// data pages
dataPagesQty, err := bin.ReadVarSize(r)
if err != nil {
return
}
for range dataPagesQty {
var (
p SealedDataPage
)
p.PageNo, err = bin.ReadUint32(r)
if err != nil {
return
}
p.Reused, err = bin.ReadBool(r)
if err != nil {
return
}
size, err = bin.ReadVarSize(r)
if err != nil {
return
}
p.Content, err = bin.ReadN(r, size)
if err != nil {
return
}
s.DataPages = append(s.DataPages, p)
}
// data tail
size, err = bin.ReadVarSize(r)
if err != nil {
return
}
s.TailTimestamps, err = bin.ReadN(r, size)
if err != nil {
return
}
size, err = bin.ReadVarSize(r)
if err != nil {
return
}
s.TailValues, err = bin.ReadN(r, size)
if err != nil {
return
}
// changed levels
changedIndexLevelsCount, err := bin.ReadVarSize(r)
if err != nil {
return
}
for range changedIndexLevelsCount {
var (
indexPagesCount int
level ChangedIndexLevel
)
// completed index page
level.CompletedIndexPage.PageNo, err = bin.ReadUint32(r)
if err != nil {
return
}
level.CompletedIndexPage.Reused, err = bin.ReadBool(r)
if err != nil {
return
}
level.CompletedIndexPage.Checksum, err = bin.ReadUint32(r)
if err != nil {
return
}
recordsCount, err = bin.ReadVarSize(r)
if err != nil {
return
}
level.CompletedIndexPage.Records, err = bin.ReadN(r, recordsCount*indexRecordSize)
if err != nil {
return
}
//
indexPagesCount, err = bin.ReadVarSize(r)
if err != nil {
return
}
for range indexPagesCount {
var p SealedIndexPage
p.PageNo, err = bin.ReadUint32(r)
if err != nil {
return
}
p.Reused, err = bin.ReadBool(r)
if err != nil {
return
}
p.Checksum, err = bin.ReadUint32(r)
if err != nil {
return
}
size, err = bin.ReadVarSize(r)
if err != nil {
return
}
p.Content, err = bin.ReadN(r, size)
if err != nil {
return
}
level.IndexPages = append(level.IndexPages, p)
}
recordsCount, err = bin.ReadVarSize(r)
if err != nil {
return
}
level.TailRecords, err = bin.ReadN(r, recordsCount*indexRecordSize)
if err != nil {
return
}
s.ChangedIndexLevels = append(s.ChangedIndexLevels, level)
}
return
}