2023-10-13 09:43:27 +00:00
|
|
|
package pfile
|
|
|
|
|
|
|
|
import (
|
|
|
|
"hash/crc32"
|
|
|
|
"unsafe"
|
2023-10-16 08:50:19 +00:00
|
|
|
|
|
|
|
"git.crumpington.com/public/jldb/lib/errs"
|
2023-10-13 09:43:27 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
const (
|
|
|
|
pageSize = 512
|
|
|
|
pageHeaderSize = 40
|
|
|
|
pageDataSize = pageSize - pageHeaderSize
|
|
|
|
|
|
|
|
pageTypeFree = 0
|
|
|
|
pageTypeHead = 1
|
|
|
|
pageTypeData = 2
|
|
|
|
)
|
|
|
|
|
|
|
|
var emptyPage = func() dataPage {
|
|
|
|
p := newDataPage()
|
|
|
|
h := p.Header()
|
|
|
|
h.CRC = p.ComputeCRC()
|
|
|
|
return p
|
|
|
|
}()
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
type pageHeader struct {
|
|
|
|
CRC uint32 // IEEE CRC-32 checksum.
|
|
|
|
PageType uint32 // One of the PageType* constants.
|
2023-10-16 08:50:19 +00:00
|
|
|
CollectionID uint64 //
|
2023-10-13 09:43:27 +00:00
|
|
|
ItemID uint64
|
|
|
|
DataSize uint64
|
|
|
|
NextPage uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
type dataPage []byte
|
|
|
|
|
|
|
|
func newDataPage() dataPage {
|
|
|
|
p := dataPage(make([]byte, pageSize))
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p dataPage) Header() *pageHeader {
|
|
|
|
return (*pageHeader)(unsafe.Pointer(&p[0]))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p dataPage) ComputeCRC() uint32 {
|
|
|
|
return crc32.ChecksumIEEE(p[4:])
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p dataPage) Data() []byte {
|
|
|
|
return p[pageHeaderSize:]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p dataPage) Write(data []byte) int {
|
|
|
|
return copy(p[pageHeaderSize:], data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p dataPage) Validate() error {
|
|
|
|
header := p.Header()
|
|
|
|
if header.CRC != p.ComputeCRC() {
|
|
|
|
return errs.Corrupt.WithMsg("CRC mismatch on data page.")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|