From 8e104b4b157035ebe2673bf4ec029c5ef3a68e75 Mon Sep 17 00:00:00 2001 From: Thomas Jungblut Date: Tue, 9 Jul 2024 19:04:43 +0200 Subject: [PATCH] ensure hashmap init clears maps This reorders some statements in the hashmap initialization to ensure we always start fresh, even when no pageids were passed to it. fixes #791 Signed-off-by: Thomas Jungblut --- internal/freelist/freelist_test.go | 24 ++++++++++++++++++++++++ internal/freelist/hashmap.go | 16 ++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/internal/freelist/freelist_test.go b/internal/freelist/freelist_test.go index df7c7697e..2fb2e0b32 100644 --- a/internal/freelist/freelist_test.go +++ b/internal/freelist/freelist_test.go @@ -179,6 +179,30 @@ func TestFreelist_releaseRange(t *testing.T) { } } +func TestFreeList_reload_page_dedupe(t *testing.T) { + buf := make([]byte, 4096) + f := newTestFreelist() + f.Init([]common.Pgid{5, 6, 8}) + + p := common.LoadPage(buf) + f.Write(p) + + f2 := newTestFreelist() + f.Init([]common.Pgid{}) + + 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.freePageIds()) != 0 { + t.Fatalf("expected empty; got=%v", f2.freePageIds()) + } + if exp := []common.Pgid{5, 6, 7, 8, 9}; !reflect.DeepEqual(exp, f2.pendingPageIds()[5].ids) { + t.Fatalf("exp=%v; got=%v", exp, f2.pendingPageIds()[5].ids) + } +} + // Ensure that a freelist can deserialize from a freelist page. func TestFreelist_read(t *testing.T) { // Create a page. diff --git a/internal/freelist/hashmap.go b/internal/freelist/hashmap.go index a6bad8976..1dca8e971 100644 --- a/internal/freelist/hashmap.go +++ b/internal/freelist/hashmap.go @@ -21,22 +21,22 @@ type hashMap struct { } func (f *hashMap) Init(pgids common.Pgids) { + // 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) + 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] }) { 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