mirror of https://github.com/hak5/bolt.git
111 lines
2.3 KiB
Go
111 lines
2.3 KiB
Go
package bolt
|
|
|
|
import (
|
|
"sort"
|
|
"unsafe"
|
|
)
|
|
|
|
// buckets represents a in-memory buckets page.
|
|
type buckets struct {
|
|
pgid pgid
|
|
items map[string]*bucket
|
|
}
|
|
|
|
// size returns the size of the page after serialization.
|
|
func (b *buckets) size() int {
|
|
var size = pageHeaderSize
|
|
for key := range b.items {
|
|
size += int(unsafe.Sizeof(bucket{})) + len(key)
|
|
}
|
|
return size
|
|
}
|
|
|
|
// get retrieves a bucket by name.
|
|
func (b *buckets) get(key string) *bucket {
|
|
return b.items[key]
|
|
}
|
|
|
|
// put sets a new value for a bucket.
|
|
func (b *buckets) put(key string, item *bucket) {
|
|
b.items[key] = item
|
|
}
|
|
|
|
// del deletes a bucket by name.
|
|
func (b *buckets) del(key string) {
|
|
if item := b.items[key]; item != nil {
|
|
delete(b.items, key)
|
|
}
|
|
}
|
|
|
|
// read initializes the data from an on-disk page.
|
|
func (b *buckets) read(p *page) {
|
|
b.pgid = p.id
|
|
b.items = make(map[string]*bucket)
|
|
|
|
var items []*bucket
|
|
var keys []string
|
|
|
|
// Read items.
|
|
nodes := (*[maxNodesPerPage]bucket)(unsafe.Pointer(&p.ptr))
|
|
for i := 0; i < int(p.count); i++ {
|
|
node := &nodes[i]
|
|
items = append(items, 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 items.
|
|
for index, key := range keys {
|
|
b.items[key] = &bucket{
|
|
root: items[index].root,
|
|
sequence: items[index].sequence,
|
|
}
|
|
}
|
|
}
|
|
|
|
// write writes the items onto a page.
|
|
func (b *buckets) write(p *page) {
|
|
// Initialize page.
|
|
p.flags |= bucketsPageFlag
|
|
p.count = uint16(len(b.items))
|
|
|
|
// Sort keys.
|
|
var keys []string
|
|
for key := range b.items {
|
|
keys = append(keys, key)
|
|
}
|
|
sort.StringSlice(keys).Sort()
|
|
|
|
// Write each bucket to the page.
|
|
items := (*[maxNodesPerPage]bucket)(unsafe.Pointer(&p.ptr))
|
|
for index, key := range keys {
|
|
items[index] = *b.items[key]
|
|
}
|
|
|
|
// Write each key to the page.
|
|
buf := (*[maxAllocSize]byte)(unsafe.Pointer(&items[p.count]))[:]
|
|
for _, key := range keys {
|
|
buf[0] = byte(len(key))
|
|
buf = buf[1:]
|
|
copy(buf, []byte(key))
|
|
buf = buf[len(key):]
|
|
}
|
|
}
|
|
|
|
// updateRoot finds a bucket by root id and then updates it to point to a new root.
|
|
func (b *buckets) updateRoot(oldid, newid pgid) {
|
|
for _, b := range b.items {
|
|
if b.root == oldid {
|
|
b.root = newid
|
|
return
|
|
}
|
|
}
|
|
}
|