From 8abfecb95cb52a54b416531755172ec103a529ea Mon Sep 17 00:00:00 2001 From: gzdaijie Date: Sun, 29 Mar 2020 22:24:42 +0800 Subject: [PATCH] init geebolt --- gee-bolt/day1-pages/go.mod | 3 ++ gee-bolt/day1-pages/meta.go | 33 ++++++++++++++ gee-bolt/day1-pages/page.go | 88 +++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 gee-bolt/day1-pages/go.mod create mode 100644 gee-bolt/day1-pages/meta.go create mode 100644 gee-bolt/day1-pages/page.go diff --git a/gee-bolt/day1-pages/go.mod b/gee-bolt/day1-pages/go.mod new file mode 100644 index 0000000..17b5990 --- /dev/null +++ b/gee-bolt/day1-pages/go.mod @@ -0,0 +1,3 @@ +module geebolt + +go 1.13 diff --git a/gee-bolt/day1-pages/meta.go b/gee-bolt/day1-pages/meta.go new file mode 100644 index 0000000..4e9cdb1 --- /dev/null +++ b/gee-bolt/day1-pages/meta.go @@ -0,0 +1,33 @@ +package geebolt + +import ( + "errors" + "hash/fnv" + "unsafe" +) + +// Represent a marker value to indicate that a file is a gee-bolt DB +const magic uint32 = 0xED0CDAED + +type meta struct { + magic uint32 + pageSize uint32 + pgid uint64 + checksum uint64 +} + +func (m *meta) sum64() uint64 { + var h = fnv.New64a() + _, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:]) + return h.Sum64() +} + +func (m *meta) validate() error { + if m.magic != magic { + return errors.New("invalid magic number") + } + if m.checksum != m.sum64() { + return errors.New("invalid checksum") + } + return nil +} diff --git a/gee-bolt/day1-pages/page.go b/gee-bolt/day1-pages/page.go new file mode 100644 index 0000000..18fc492 --- /dev/null +++ b/gee-bolt/day1-pages/page.go @@ -0,0 +1,88 @@ +package geebolt + +import ( + "fmt" + "reflect" + "unsafe" +) + +const pageHeaderSize = unsafe.Sizeof(page{}) +const branchPageElementSize = unsafe.Sizeof(branchPageElement{}) +const leafPageElementSize = unsafe.Sizeof(leafPageElement{}) +const maxKeysPerPage = 1024 + +const ( + branchPageFlag uint16 = iota + leafPageFlag + metaPageFlag + freelistPageFlag +) + +type page struct { + id uint64 + flags uint16 + count uint16 + overflow uint32 +} + +type leafPageElement struct { + pos uint32 + ksize uint32 + vsize uint32 +} + +type branchPageElement struct { + pos uint32 + ksize uint32 + pgid uint64 +} + +func (p *page) typ() string { + switch p.flags { + case branchPageFlag: + return "branch" + case leafPageFlag: + return "leaf" + case metaPageFlag: + return "meta" + case freelistPageFlag: + return "freelist" + } + return fmt.Sprintf("unknown<%02x>", p.flags) +} + +func (p *page) meta() *meta { + return (*meta)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + pageHeaderSize)) +} + +func (p *page) dataPtr() unsafe.Pointer { + return unsafe.Pointer(&reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(p)) + pageHeaderSize, + Len: int(p.count), + Cap: int(p.count), + }) +} + +func (p *page) leafPageElement(index uint16) *leafPageElement { + off := pageHeaderSize + uintptr(index)*leafPageElementSize + return (*leafPageElement)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + off)) +} + +func (p *page) leafPageElements() []leafPageElement { + if p.count == 0 { + return nil + } + return *(*[]leafPageElement)(p.dataPtr()) +} + +func (p *page) branchPageElement(index uint16) *branchPageElement { + off := pageHeaderSize + uintptr(index)*branchPageElementSize + return (*branchPageElement)(unsafe.Pointer(uintptr(unsafe.Pointer(p)) + off)) +} + +func (p *page) branchPageElements() []branchPageElement { + if p.count == 0 { + return nil + } + return *(*[]branchPageElement)(p.dataPtr()) +}