Check for freelist overflow.

master
Ben Johnson 2014-06-13 07:56:10 -06:00
parent 01bc9be72f
commit f448639ce4
2 changed files with 21 additions and 2 deletions

View File

@ -1,11 +1,18 @@
package bolt
import (
"errors"
"fmt"
"sort"
"unsafe"
)
var (
// ErrFreelistOverflow is returned when the total number of free pages
// exceeds 65,536 and the freelist cannot hold any more.
ErrFreelistOverflow = errors.New("freelist overflow")
)
// freelist represents a list of all pages that are available for allocation.
// It also tracks pages that have been freed but are still in use by open transactions.
type freelist struct {
@ -134,9 +141,19 @@ func (f *freelist) read(p *page) {
// write writes the page ids onto a freelist page. All free and pending ids are
// saved to disk since in the event of a program crash, all pending ids will
// become free.
func (f *freelist) write(p *page) {
func (f *freelist) write(p *page) error {
// Combine the old free pgids and pgids waiting on an open transaction.
ids := f.all()
// Make sure that the sum of all free pages is less than the max uint16 size.
if len(ids) > (1 << 16) {
return ErrFreelistOverflow
}
// Update the header and write the ids to the page.
p.flags |= freelistPageFlag
p.count = uint16(len(ids))
copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:], ids)
return nil
}

4
tx.go
View File

@ -173,7 +173,9 @@ func (tx *Tx) Commit() error {
tx.close()
return err
}
tx.db.freelist.write(p)
if err := tx.db.freelist.write(p); err != nil {
return err
}
tx.meta.freelist = p.id
// Write dirty pages to disk.