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 , 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 +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 )
}
}
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 )
}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .