func (f *freelist) init(pgids []pgid) {
	if len(pgids) == 0 {
		return
	}
	size := uint64(1)
	start := pgids[0]
	if !sort.SliceIsSorted([]pgid(pgids), func(i, j int) bool { return pgids[i] < pgids[j] }) {
		panic("pgids not sorted")
	}
	f.freemaps = make(map[uint64]pidSet)
	f.forwardMap = make(map[pgid]uint64)
	f.backwardMap = make(map[pgid]uint64)
	for i := 1; i < len(pgids); i++ {
		if pgids[i] == pgids[i-1]+1 {
			size++
		} else {
			f.addSpan(start, size)
			size = 1
			start = pgids[i]
		}
	}
	if size != 0 && start != 0 {
		f.addSpan(start, size)
	}
}
initial from pgids using when use hashmap version
pgids must be sorted
package bbolt
import "sort"
func (f *freelist) hashmapFreeCount() int {
	count := 0
	for _, size := range f.forwardMap {
		count += int(size)
	}
	return count
}
func (f *freelist) hashmapAllocate(txid txid, n int) pgid {
	if n == 0 {
		return 0
	}
	if bm, ok := f.freemaps[uint64(n)]; ok {
		for pid := range bm {
			f.delSpan(pid, uint64(n))
			f.allocs[pid] = txid
			for i := pgid(0); i < pgid(n); i++ {
				delete(f.cache, pid+i)
			}
			return pid
		}
	}
	for size, bm := range f.freemaps {
		if size < uint64(n) {
			continue
		}
		for pid := range bm {
			f.delSpan(pid, uint64(size))
			f.allocs[pid] = txid
			remain := size - uint64(n)
			f.addSpan(pid+pgid(n), remain)
			for i := pgid(0); i < pgid(n); i++ {
				delete(f.cache, pid+pgid(i))
			}
			return pid
		}
	}
	return 0
}
func (f *freelist) hashmapReadIDs(pgids []pgid) {
	f.init(pgids)
	f.reindex()
}
func (f *freelist) hashmapGetFreePageIDs() []pgid {
	count := f.free_count()
	if count == 0 {
		return nil
	}
	m := make([]pgid, 0, count)
	for start, size := range f.forwardMap {
		for i := 0; i < int(size); i++ {
			m = append(m, start+pgid(i))
		}
	}
	sort.Sort(pgids(m))
	return m
}
func (f *freelist) hashmapMergeSpans(ids pgids) {
	for _, id := range ids {
		f.mergeWithExistingSpan(id)
	}
}
func (f *freelist) mergeWithExistingSpan(pid pgid) {
	prev := pid - 1
	next := pid + 1
	preSize, mergeWithPrev := f.backwardMap[prev]
	nextSize, mergeWithNext := f.forwardMap[next]
	newStart := pid
	newSize := uint64(1)
	if mergeWithPrev {
		start := prev + 1 - pgid(preSize)
		f.delSpan(start, preSize)
		newStart -= pgid(preSize)
		newSize += preSize
	}
	if mergeWithNext {
		f.delSpan(next, nextSize)
		newSize += nextSize
	}
	f.addSpan(newStart, newSize)
}
func (f *freelist) addSpan(start pgid, size uint64) {
	f.backwardMap[start-1+pgid(size)] = size
	f.forwardMap[start] = size
	if _, ok := f.freemaps[size]; !ok {
		f.freemaps[size] = make(map[pgid]struct{})
	}
	f.freemaps[size][start] = struct{}{}
}
func (f *freelist) delSpan(start pgid, size uint64) {
	delete(f.forwardMap, start)
	delete(f.backwardMap, start+pgid(size-1))
	delete(f.freemaps[size], start)
	if len(f.freemaps[size]) == 0 {
		delete(f.freemaps, size)
	}
}