From bf5458de2f302248c02015a7439104baa9b0b103 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Mon, 18 May 2015 10:14:47 -0600 Subject: [PATCH] Add inline documentation for bdc109b. This commit simply adds some additional comments to the commit provided by sasha-s that fixes the "slice out of bounds" errors. --- bolt_amd64.go | 4 ---- node.go | 17 ++++++++++------- tx.go | 12 ++++++++++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/bolt_amd64.go b/bolt_amd64.go index 83f935f..cca6b7e 100644 --- a/bolt_amd64.go +++ b/bolt_amd64.go @@ -5,7 +5,3 @@ const maxMapSize = 0xFFFFFFFFFFFF // 256TB // maxAllocSize is the size used when creating array pointers. const maxAllocSize = 0x7FFFFFFF - -// Setting -// const maxAllocSize = 70000 -// reveals the index out of bound bug(s) diff --git a/node.go b/node.go index 4276e4a..c9fb21c 100644 --- a/node.go +++ b/node.go @@ -220,16 +220,21 @@ func (n *node) write(p *page) { elem.pgid = item.pgid _assert(elem.pgid != p.id, "write: circular dependency occurred") } - lk, lv := len(item.key), len(item.value) - if len(b) < lk+lv { + + // If the length of key+value is larger than the max allocation size + // then we need to reallocate the byte array pointer. + // + // See: https://github.com/boltdb/bolt/pull/335 + klen, vlen := len(item.key), len(item.value) + if len(b) < klen+vlen { b = (*[maxAllocSize]byte)(unsafe.Pointer(&b[0]))[:] } // Write data for the element to the end of the page. copy(b[0:], item.key) - b = b[lk:] + b = b[klen:] copy(b[0:], item.value) - b = b[lv:] + b = b[vlen:] } // DEBUG ONLY: n.dump() @@ -355,9 +360,7 @@ func (n *node) spill() error { } // Allocate contiguous space for the node. - // sz := node.size() + n.pageElementSize()*len(n.inodes) - sz := node.size() - p, err := tx.allocate((sz / tx.db.pageSize) + 1) + p, err := tx.allocate((node.size() / tx.db.pageSize) + 1) if err != nil { return err } diff --git a/tx.go b/tx.go index 9ffceaf..3fef4b4 100644 --- a/tx.go +++ b/tx.go @@ -422,26 +422,38 @@ func (tx *Tx) write() error { for _, p := range pages { size := (int(p.overflow) + 1) * tx.db.pageSize offset := int64(p.id) * int64(tx.db.pageSize) + + // Write out page in "max allocation" sized chunks. ptr := (*[maxAllocSize]byte)(unsafe.Pointer(p)) for { + // Limit our write to our max allocation size. sz := size if sz > maxAllocSize-1 { sz = maxAllocSize - 1 } + + // Write chunk to disk. buf := ptr[:sz] if _, err := tx.db.ops.writeAt(buf, offset); err != nil { return err } + // Update statistics. tx.stats.Write++ + + // Exit inner for loop if we've written all the chunks. size -= sz if size == 0 { break } + + // Otherwise move offset forward and move pointer to next chunk. offset += int64(sz) ptr = (*[maxAllocSize]byte)(unsafe.Pointer(&ptr[sz])) } } + + // Ignore file sync if flag is set on DB. if !tx.db.NoSync || IgnoreNoSync { if err := fdatasync(tx.db); err != nil { return err