From d61cf2303f412f270c917b0dc76ce681306ecbf3 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 3 Aug 2025 19:27:41 +0300 Subject: [PATCH] Implement another multilist-style allocator for metadata blocks --- src/blockstore/multilist.cpp | 60 ++++++++++++++++++++++++++++++++++++ src/blockstore/multilist.h | 12 ++++++++ 2 files changed, 72 insertions(+) diff --git a/src/blockstore/multilist.cpp b/src/blockstore/multilist.cpp index bd9ef419..b26cb880 100644 --- a/src/blockstore/multilist.cpp +++ b/src/blockstore/multilist.cpp @@ -276,3 +276,63 @@ void multilist_alloc_t::do_free(uint32_t pos) prevs[heads[ni]-1] = pos+1; heads[ni] = pos+1; } + +multilist_index_t::multilist_index_t(uint32_t count, uint32_t max_used, uint32_t init_used): + count(count), max_used(max_used) +{ + assert(init_used < max_used); + nexts.resize(count, UINT32_MAX); + prevs.resize(count, UINT32_MAX); + heads.resize(max_used, UINT32_MAX); + for (size_t i = 0; i < count-1; i++) + { + nexts[i] = i+1; + prevs[i+1] = i; + } + prevs[0] = UINT32_MAX; + nexts[count-1] = UINT32_MAX; + heads[init_used] = 0; +} + +uint32_t multilist_index_t::find(uint32_t wanted_used) +{ + assert(wanted_used < max_used); + return heads[wanted_used]; +} + +void multilist_index_t::change(uint32_t pos, uint32_t old_used, uint32_t new_used) +{ + if (new_used == old_used) + return; + assert(old_used < max_used && new_used < max_used); + if (prevs[pos] != UINT32_MAX) + nexts[prevs[pos]] = nexts[pos]; + if (nexts[pos] != UINT32_MAX) + prevs[nexts[pos]] = prevs[pos]; + if (heads[old_used] == pos) + heads[old_used] = nexts[pos]; + prevs[pos] = UINT32_MAX; + if (heads[new_used] != UINT32_MAX) + prevs[heads[new_used]] = pos; + nexts[pos] = heads[new_used]; + heads[new_used] = pos; +} + +void multilist_index_t::print() +{ + printf("heads:"); + for (int i = 0; i < max_used; i++) + if (heads[i] != UINT32_MAX) + printf(" %u=%u", i, heads[i]); + printf("\n"); + printf("prevs:"); + for (int i = 0; i < count; i++) + if (prevs[i] != UINT32_MAX) + printf(" %d=%d", i, prevs[i]); + printf("\n"); + printf("nexts:"); + for (int i = 0; i < count; i++) + if (nexts[i] != UINT32_MAX) + printf(" %d=%d", i, nexts[i]); + printf("\n"); +} diff --git a/src/blockstore/multilist.h b/src/blockstore/multilist.h index 8079faa1..58b25f5a 100644 --- a/src/blockstore/multilist.h +++ b/src/blockstore/multilist.h @@ -23,3 +23,15 @@ struct multilist_alloc_t void verify(); void print(); }; + +struct multilist_index_t +{ + const uint32_t count, max_used; + std::vector nexts, prevs, heads; + + // used should be always < max_used + multilist_index_t(uint32_t count, uint32_t max_used, uint32_t init_used); + uint32_t find(uint32_t wanted_used); + void change(uint32_t pos, uint32_t old_used, uint32_t new_used); + void print(); +};