diff --git a/mnode.go b/mnode.go new file mode 100644 index 0000000..1d0abca --- /dev/null +++ b/mnode.go @@ -0,0 +1,9 @@ +package bolt + +type mnodes []mnode + +type mnode struct { + key []byte + value []byte +} + diff --git a/lpage.go b/mpage.go similarity index 83% rename from lpage.go rename to mpage.go index 56c5c56..7c5e048 100644 --- a/lpage.go +++ b/mpage.go @@ -6,26 +6,23 @@ import ( "unsafe" ) -type lpage struct { - nodes []lpnode -} - -type lpnode struct { - key []byte - value []byte +// mpage represents a deserialized leaf page. +// It is deserialized from an memory-mapped page and is not restricted by page size. +type mpage struct { + nodes mnodes } // allocator is a function that returns a set of contiguous pages. type allocator func(count int) (*page, error) // put inserts or replaces a key on a leaf page. -func (p *lpage) put(key []byte, value []byte) { +func (p *mpage) put(key []byte, value []byte) { // Find insertion index. index := sort.Search(len(p.nodes), func(i int) bool { return bytes.Compare(p.nodes[i].key, key) != -1 }) // If there is no existing key then add a new node. if len(p.nodes) == 0 || !bytes.Equal(p.nodes[index].key, key) { - p.nodes = append(p.nodes, lpnode{}) + p.nodes = append(p.nodes, mnode{}) copy(p.nodes[index+1:], p.nodes[index:]) } p.nodes[index].key = key @@ -33,8 +30,8 @@ func (p *lpage) put(key []byte, value []byte) { } // read initializes the node data from an on-disk page. -func (p *lpage) read(page *page) { - p.nodes = make([]lpnode, page.count) +func (p *mpage) read(page *page) { + p.nodes = make(mnodes, page.count) lnodes := (*[maxNodesPerPage]lnode)(unsafe.Pointer(&page.ptr)) for i := 0; i < int(page.count); i++ { lnode := lnodes[i] @@ -45,7 +42,7 @@ func (p *lpage) read(page *page) { } // write writes the nodes onto one or more leaf pages. -func (p *lpage) write(pageSize int, allocate allocator) ([]*page, error) { +func (p *mpage) write(pageSize int, allocate allocator) ([]*page, error) { var pages []*page for _, nodes := range p.split(pageSize) { @@ -87,10 +84,10 @@ func (p *lpage) write(pageSize int, allocate allocator) ([]*page, error) { } // split divides up the noes in the page into appropriately sized groups. -func (p *lpage) split(pageSize int) [][]lpnode { +func (p *mpage) split(pageSize int) []mnodes { // If we only have enough nodes for one page then just return the nodes. if len(p.nodes) <= minKeysPerPage { - return [][]lpnode{p.nodes} + return []mnodes{p.nodes} } // If we're not larger than one page then just return the nodes. @@ -99,13 +96,13 @@ func (p *lpage) split(pageSize int) [][]lpnode { totalSize += lnodeSize + len(node.key) + len(node.value) } if totalSize < pageSize { - return [][]lpnode{p.nodes} + return []mnodes{p.nodes} } // Otherwise group into smaller pages and target a given fill size. var size int - var group []lpnode - var groups [][]lpnode + var group mnodes + var groups []mnodes // Set fill threshold to 25%. threshold := pageSize >> 4 @@ -116,7 +113,7 @@ func (p *lpage) split(pageSize int) [][]lpnode { // TODO(benbjohnson): Don't create a new group for just the last node. if group == nil || (len(group) > minKeysPerPage && size+nodeSize > threshold) { size = pageHeaderSize - group = make([]lpnode, 0) + group = make(mnodes, 0) groups = append(groups, group) } diff --git a/rwtransaction.go b/rwtransaction.go index f665dc2..9ecd4ee 100644 --- a/rwtransaction.go +++ b/rwtransaction.go @@ -8,8 +8,7 @@ import ( // Only one read/write transaction can be active for a DB at a time. type RWTransaction struct { Transaction - bpages map[pgid]*bpage - lpages map[pgid]*lpage + mpages map[pgid]*mpage } // TODO: Allocate scratch meta page. @@ -62,7 +61,7 @@ func (t *RWTransaction) CreateBucket(name string) error { // Insert new node. c := t.sys.cursor() c.Goto([]byte(name)) - t.lpage(c.page().id).put([]byte(name), buf[:]) + t.mpage(c.page().id).put([]byte(name), buf[:]) return nil } @@ -105,7 +104,7 @@ func (t *RWTransaction) Put(name string, key []byte, value []byte) error { // Insert a new node. c := b.cursor() c.Goto(key) - t.lpage(c.page().id).put(key, value) + t.mpage(c.page().id).put(key, value) return nil } @@ -125,18 +124,18 @@ func (t *RWTransaction) allocate(size int) (*page, error) { return nil, nil } -// lpage returns a deserialized leaf page. -func (t *RWTransaction) lpage(id pgid) *lpage { - if t.lpages != nil { - if p := t.lpages[id]; p != nil { +// mpage returns a deserialized leaf page. +func (t *RWTransaction) mpage(id pgid) *mpage { + if t.mpages != nil { + if p := t.mpages[id]; p != nil { return p } } // Read raw page and deserialize. - p := &lpage{} + p := &mpage{} p.read(t.page(id)) - t.lpages[id] = p + t.mpages[id] = p return p }