1st
This commit is contained in:
96
atree/redo/reader.go
Normal file
96
atree/redo/reader.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package redo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"gordenko.dev/dima/qb/bin"
|
||||
)
|
||||
|
||||
type REDOFile struct {
|
||||
MetricID uint32
|
||||
Timestamp uint32
|
||||
Value float64
|
||||
IsDataPageReused bool
|
||||
DataPage PageToWrite
|
||||
IsRootChanged bool
|
||||
RootPageNo uint32
|
||||
ReusedIndexPages []uint32
|
||||
IndexPages []PageToWrite
|
||||
}
|
||||
|
||||
type ReadREDOFileReq struct {
|
||||
FileName string
|
||||
DataPageSize int
|
||||
IndexPageSize int
|
||||
}
|
||||
|
||||
func ReadREDOFile(req ReadREDOFileReq) (*REDOFile, error) {
|
||||
buf, err := os.ReadFile(req.FileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(buf) < 25 {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
var (
|
||||
end = len(buf) - 4
|
||||
payload = buf[:end]
|
||||
checksum = bin.GetUint32(buf[end:])
|
||||
calculatedChecksum = crc32.ChecksumIEEE(payload)
|
||||
)
|
||||
|
||||
// Помилка чексуми означає що файл або недописаний, або пошкодженний
|
||||
if checksum != calculatedChecksum {
|
||||
return nil, fmt.Errorf("written checksum %d not equal calculated checksum %d",
|
||||
checksum, calculatedChecksum)
|
||||
}
|
||||
|
||||
var (
|
||||
redoLog = REDOFile{
|
||||
MetricID: bin.GetUint32(buf[0:]),
|
||||
Timestamp: bin.GetUint32(buf[4:]),
|
||||
Value: bin.GetFloat64(buf[8:]),
|
||||
IsDataPageReused: buf[16] == 1,
|
||||
DataPage: PageToWrite{
|
||||
PageNo: bin.GetUint32(buf[17:]),
|
||||
Data: buf[21 : 21+req.DataPageSize],
|
||||
},
|
||||
}
|
||||
pos = 21 + req.DataPageSize
|
||||
)
|
||||
|
||||
for {
|
||||
if pos == len(payload) {
|
||||
return &redoLog, nil
|
||||
}
|
||||
|
||||
if pos > len(payload) {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
flags := buf[pos]
|
||||
|
||||
item := PageToWrite{
|
||||
PageNo: bin.GetUint32(buf[pos+1:]),
|
||||
}
|
||||
pos += 5 // flags + pageNo
|
||||
item.Data = buf[pos : pos+req.IndexPageSize]
|
||||
pos += req.IndexPageSize
|
||||
|
||||
redoLog.IndexPages = append(redoLog.IndexPages, item)
|
||||
|
||||
if (flags & FlagReused) == FlagReused {
|
||||
redoLog.ReusedIndexPages = append(redoLog.ReusedIndexPages, item.PageNo)
|
||||
}
|
||||
|
||||
if (flags & FlagNewRoot) == FlagNewRoot {
|
||||
redoLog.IsRootChanged = true
|
||||
redoLog.RootPageNo = item.PageNo
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user