func (f *freelist) release(txid txid) {
	m := make(pgids, 0)
	for tid, txp := range f.pending {
		if tid <= txid {
			m = append(m, txp.ids...)
			delete(f.pending, tid)
		}
	}
	sort.Sort(m)
	f.ids = pgids(f.ids).merge(m)
}
release moves all page ids for a transaction id (or older) to the freelist.
package bolt
import (
	"fmt"
	"sort"
	"unsafe"
)
type txPending struct {
	ids              []pgid
	alloctx          []txid  
	lastReleaseBegin txid    
}
type freelist struct {
	ids     []pgid               
	allocs  map[pgid]txid        
	pending map[txid]*txPending  
	cache   map[pgid]bool        
}
func newFreelist() *freelist {
	return &freelist{
		allocs:  make(map[pgid]txid),
		pending: make(map[txid]*txPending),
		cache:   make(map[pgid]bool),
	}
}
func (f *freelist) size() int {
	n := f.count()
	if n >= 0xFFFF {
		n++
	}
	return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * n)
}
func (f *freelist) count() int {
	return f.free_count() + f.pending_count()
}
func (f *freelist) free_count() int {
	return len(f.ids)
}
func (f *freelist) pending_count() int {
	var count int
	for _, txp := range f.pending {
		count += len(txp.ids)
	}
	return count
}
func (f *freelist) copyall(dst []pgid) {
	m := make(pgids, 0, f.pending_count())
	for _, txp := range f.pending {
		m = append(m, txp.ids...)
	}
	sort.Sort(m)
	mergepgids(dst, f.ids, m)
}
func (f *freelist) allocate(txid txid, n int) pgid {
	if len(f.ids) == 0 {
		return 0
	}
	var initial, previd pgid
	for i, id := range f.ids {
		if id <= 1 {
			panic(fmt.Sprintf("invalid page allocation: %d", id))
		}
		if previd == 0 || id-previd != 1 {
			initial = id
		}
		if (id-initial)+1 == pgid(n) {
			if (i + 1) == n {
				f.ids = f.ids[i+1:]
			} else {
				copy(f.ids[i-n+1:], f.ids[i+1:])
				f.ids = f.ids[:len(f.ids)-n]
			}
			for i := pgid(0); i < pgid(n); i++ {
				delete(f.cache, initial+i)
			}
			f.allocs[initial] = txid
			return initial
		}
		previd = id
	}
	return 0
}
func (f *freelist) free(txid txid, p *page) {
	if p.id <= 1 {
		panic(fmt.Sprintf("cannot free page 0 or 1: %d", p.id))
	}
	txp := f.pending[txid]
	if txp == nil {
		txp = &txPending{}
		f.pending[txid] = txp
	}
	allocTxid, ok := f.allocs[p.id]
	if ok {
		delete(f.allocs, p.id)
	} else if (p.flags & freelistPageFlag) != 0 {
		allocTxid = txid - 1
	}
	for id := p.id; id <= p.id+pgid(p.overflow); id++ {
		if f.cache[id] {
			panic(fmt.Sprintf("page %d already freed", id))
		}
		txp.ids = append(txp.ids, id)
		txp.alloctx = append(txp.alloctx, allocTxid)
		f.cache[id] = true
	}
}