diff --git a/freelist_hmap.go b/freelist_hmap.go index c5c09f55e..387c3a427 100644 --- a/freelist_hmap.go +++ b/freelist_hmap.go @@ -195,22 +195,23 @@ func (f *freelist) delSpan(start common.Pgid, size uint64) { // initial from pgids using when use hashmap version // pgids must be sorted func (f *freelist) init(pgids []common.Pgid) { + // reset the counter when freelist init + f.freePagesCount = 0 + f.freemaps = make(map[uint64]pidSet) + f.forwardMap = make(map[common.Pgid]uint64) + f.backwardMap = make(map[common.Pgid]uint64) + f.reindex() + if len(pgids) == 0 { return } - size := uint64(1) - start := pgids[0] - // reset the counter when freelist init - f.freePagesCount = 0 - - if !sort.SliceIsSorted([]common.Pgid(pgids), func(i, j int) bool { return pgids[i] < pgids[j] }) { + if !sort.SliceIsSorted(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[common.Pgid]uint64) - f.backwardMap = make(map[common.Pgid]uint64) + size := uint64(1) + start := pgids[0] for i := 1; i < len(pgids); i++ { // continuous page diff --git a/freelist_test.go b/freelist_test.go index 5cf40bd1c..4315a55bf 100644 --- a/freelist_test.go +++ b/freelist_test.go @@ -179,6 +179,29 @@ func TestFreelist_releaseRange(t *testing.T) { } } +func TestFreeList_reload_page_dedupe(t *testing.T) { + var buf [4096]byte + f := newTestFreelist() + f.readIDs([]common.Pgid{5, 6, 8}) + + p := (*common.Page)(unsafe.Pointer(&buf[0])) + if err := f.write(p); err != nil { + t.Fatal(err) + } + + f2 := newTestFreelist() + f2.free(common.Txid(5), common.NewPage(5, common.LeafPageFlag, 0, 4)) + // reload should deduplicate as a pending page when reading from p's freelist + f2.reload(p) + + if len(f2.getFreePageIDs()) != 0 { + t.Fatalf("expected empty; got=%v", f2.getFreePageIDs()) + } + if exp := []common.Pgid{5, 6, 7, 8, 9}; !reflect.DeepEqual(exp, f2.pending[5].ids) { + t.Fatalf("exp=%v; got=%v", exp, f2.pending[5].ids) + } +} + func TestFreelistHashmap_allocate(t *testing.T) { f := newTestFreelist() if f.freelistType != FreelistMapType {