bbolt/sys.go

109 lines
2.2 KiB
Go

package bolt
import (
"sort"
"unsafe"
)
// sys represents a in-memory system page.
type sys struct {
pgid pgid
buckets map[string]*bucket
}
// size returns the size of the page after serialization.
func (s *sys) size() int {
var size int = pageHeaderSize
for key, _ := range s.buckets {
size += int(unsafe.Sizeof(bucket{})) + len(key)
}
return size
}
// get retrieves a bucket by name.
func (s *sys) get(key string) *bucket {
return s.buckets[key]
}
// getByRoot retrieves a bucket by root page id.
func (s *sys) getByRoot(pgid pgid) *bucket {
for _, b := range s.buckets {
if b.root == pgid {
return b
}
}
panic("root not found")
}
// put sets a new value for a bucket.
func (s *sys) put(key string, b *bucket) {
s.buckets[key] = b
}
// del deletes a bucket by name.
func (s *sys) del(key string) {
if b := s.buckets[key]; b != nil {
delete(s.buckets, key)
}
}
// read initializes the data from an on-disk page.
func (s *sys) read(p *page) {
s.pgid = p.id
s.buckets = make(map[string]*bucket)
var buckets []*bucket
var keys []string
// Read buckets.
nodes := (*[maxNodesPerPage]bucket)(unsafe.Pointer(&p.ptr))
for i := 0; i < int(p.count); i++ {
node := &nodes[i]
buckets = append(buckets, node)
}
// Read keys.
buf := (*[maxAllocSize]byte)(unsafe.Pointer(&nodes[p.count]))[:]
for i := 0; i < int(p.count); i++ {
size := int(buf[0])
buf = buf[1:]
keys = append(keys, string(buf[:size]))
buf = buf[size:]
}
// Associate keys and buckets.
for index, key := range keys {
b := &bucket{buckets[index].root}
s.buckets[key] = b
}
}
// write writes the items onto a page.
func (s *sys) write(p *page) {
// Initialize page.
p.flags |= p_sys
p.count = uint16(len(s.buckets))
// Sort keys.
var keys []string
for key, _ := range s.buckets {
keys = append(keys, key)
}
sort.StringSlice(keys).Sort()
// Write each bucket to the page.
buckets := (*[maxNodesPerPage]bucket)(unsafe.Pointer(&p.ptr))
for index, key := range keys {
buckets[index] = *s.buckets[key]
}
// Write each key to the page.
buf := (*[maxAllocSize]byte)(unsafe.Pointer(&buckets[p.count]))[:]
for _, key := range keys {
buf[0] = byte(len(key))
buf = buf[1:]
copy(buf, []byte(key))
buf = buf[len(key):]
}
}