diff options
Diffstat (limited to 'buckets.go')
-rw-r--r-- | buckets.go | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/buckets.go b/buckets.go new file mode 100644 index 0000000..59a82d8 --- /dev/null +++ b/buckets.go @@ -0,0 +1,107 @@ +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 int = 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{items[index].root} + } +} + +// write writes the items onto a page. +func (b *buckets) write(p *page) { + // Initialize page. + p.flags |= p_buckets + 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 + } + } +} |