From ff7469ee914b42aaa1642307781ab4d44687ddea Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 27 Nov 2019 00:50:57 +0300 Subject: [PATCH] Make allocator a class --- allocator.cpp | 46 ++++++++++++++++++++++---------------------- allocator.h | 14 +++++++------- blockstore.cpp | 5 ++--- blockstore.h | 2 +- blockstore_flush.cpp | 4 ++-- blockstore_init.cpp | 4 ++-- blockstore_write.cpp | 4 ++-- 7 files changed, 39 insertions(+), 40 deletions(-) diff --git a/allocator.cpp b/allocator.cpp index 4bb3e899..3f697cda 100644 --- a/allocator.cpp +++ b/allocator.cpp @@ -1,13 +1,14 @@ +#include #include "allocator.h" #include #include -allocator *allocator_create(uint64_t blocks) +allocator::allocator(uint64_t blocks) { if (blocks >= 0x80000000 || blocks <= 1) { - return NULL; + throw std::invalid_argument("blocks"); } uint64_t p2 = 1, total = 1; while (p2 * 64 < blocks) @@ -17,31 +18,30 @@ allocator *allocator_create(uint64_t blocks) } total -= p2; total += (blocks+63) / 64; - allocator *buf = (allocator*)memalign(sizeof(uint64_t), (2 + total)*sizeof(uint64_t)); - buf->size = blocks; - buf->last_one_mask = (blocks % 64) == 0 + mask = new uint64_t[2 + total]; + size = blocks; + last_one_mask = (blocks % 64) == 0 ? UINT64_MAX : ~(UINT64_MAX << (64 - blocks % 64)); for (uint64_t i = 0; i < total; i++) { - buf->mask[i] = 0; + mask[i] = 0; } - return buf; } -void allocator_destroy(allocator *alloc) +allocator::~allocator() { - free(alloc); + delete[] mask; } -void allocator_set(allocator *alloc, uint64_t addr, bool value) +void allocator::set(uint64_t addr, bool value) { - if (addr >= alloc->size) + if (addr >= size) { return; } uint64_t p2 = 1, offset = 0; - while (p2 * 64 < alloc->size) + while (p2 * 64 < size) { offset += p2; p2 = p2 * 64; @@ -53,21 +53,21 @@ void allocator_set(allocator *alloc, uint64_t addr, bool value) { uint64_t last = offset + cur_addr/64; uint64_t bit = cur_addr % 64; - if (((alloc->mask[last] >> bit) & 1) != value64) + if (((mask[last] >> bit) & 1) != value64) { if (value) { - alloc->mask[last] = alloc->mask[last] | (1 << bit); - if (alloc->mask[last] != (!is_last || cur_addr/64 < alloc->size/64 - ? UINT64_MAX : alloc->last_one_mask)) + mask[last] = mask[last] | (1 << bit); + if (mask[last] != (!is_last || cur_addr/64 < size/64 + ? UINT64_MAX : last_one_mask)) { break; } } else { - alloc->mask[last] = alloc->mask[last] & ~(1 << bit); - if (alloc->mask[last] != 0) + mask[last] = mask[last] & ~(1 << bit); + if (mask[last] != 0) { break; } @@ -91,15 +91,15 @@ void allocator_set(allocator *alloc, uint64_t addr, bool value) } } -uint64_t allocator_find_free(allocator *alloc) +uint64_t allocator::find_free() { uint64_t p2 = 1, offset = 0, addr = 0, f, i; - while (p2 < alloc->size) + while (p2 < size) { - uint64_t mask = alloc->mask[offset + addr]; + uint64_t m = mask[offset + addr]; for (i = 0, f = 1; i < 64; i++, f <<= 1) { - if (!(mask & f)) + if (!(m & f)) { break; } @@ -110,7 +110,7 @@ uint64_t allocator_find_free(allocator *alloc) return UINT64_MAX; } addr = (addr * 64) | i; - if (addr >= alloc->size) + if (addr >= size) { // No space return UINT64_MAX; diff --git a/allocator.h b/allocator.h index aa14f19f..4adb2dfa 100644 --- a/allocator.h +++ b/allocator.h @@ -3,14 +3,14 @@ #include // Hierarchical bitmap allocator -struct allocator +class allocator { uint64_t size; uint64_t last_one_mask; - uint64_t mask[]; + uint64_t *mask; +public: + allocator(uint64_t blocks); + ~allocator(); + void set(uint64_t addr, bool value); + uint64_t find_free(); }; - -allocator *allocator_create(uint64_t blocks); -void allocator_destroy(allocator *alloc); -void allocator_set(allocator *alloc, uint64_t addr, bool value); -uint64_t allocator_find_free(allocator *alloc); diff --git a/blockstore.cpp b/blockstore.cpp index 76581ef9..641b4333 100644 --- a/blockstore.cpp +++ b/blockstore.cpp @@ -24,9 +24,7 @@ blockstore::blockstore(spp::sparse_hash_map & config, open_meta(config); open_journal(config); calc_lengths(config); - data_alloc = allocator_create(block_count); - if (!data_alloc) - throw std::bad_alloc(); + data_alloc = new allocator(block_count); } catch (std::exception & e) { @@ -46,6 +44,7 @@ blockstore::blockstore(spp::sparse_hash_map & config, blockstore::~blockstore() { + delete data_alloc; delete flusher; free(zero_object); ringloop->unregister_consumer(ring_consumer); diff --git a/blockstore.h b/blockstore.h index 5cd7c0fa..7240f51d 100644 --- a/blockstore.h +++ b/blockstore.h @@ -255,7 +255,7 @@ class blockstore std::vector unsynced_big_writes, unsynced_small_writes; std::list in_progress_syncs; // ...and probably here, too uint64_t block_count; - allocator *data_alloc; + allocator *data_alloc = NULL; uint8_t *zero_object; int meta_fd; diff --git a/blockstore_flush.cpp b/blockstore_flush.cpp index e02d21f5..77744675 100644 --- a/blockstore_flush.cpp +++ b/blockstore_flush.cpp @@ -384,7 +384,7 @@ resume_0: // Update clean_db and dirty_db, free old data locations if (clean_it != bs->clean_db.end() && clean_it->second.location != clean_loc) { - allocator_set(bs->data_alloc, clean_it->second.location >> bs->block_order, false); + bs->data_alloc->set(clean_it->second.location >> bs->block_order, false); } bs->clean_db[cur.oid] = { .version = cur.version, @@ -395,7 +395,7 @@ resume_0: { if (IS_BIG_WRITE(dirty_it->second.state) && dirty_it->second.location != clean_loc) { - allocator_set(bs->data_alloc, dirty_it->second.location >> bs->block_order, false); + bs->data_alloc->set(dirty_it->second.location >> bs->block_order, false); } int used = --bs->journal.used_sectors[dirty_it->second.journal_sector]; if (used == 0) diff --git a/blockstore_init.cpp b/blockstore_init.cpp index 7db00790..d57d6e25 100644 --- a/blockstore_init.cpp +++ b/blockstore_init.cpp @@ -90,11 +90,11 @@ void blockstore_init_meta::handle_entries(struct clean_disk_entry* entries, int if (clean_it != bs->clean_db.end()) { // free the previous block - allocator_set(bs->data_alloc, clean_it->second.version >> block_order, false); + bs->data_alloc->set(clean_it->second.version >> block_order, false); } else entries_loaded++; - allocator_set(bs->data_alloc, done_cnt+i, true); + bs->data_alloc->set(done_cnt+i, true); bs->clean_db[entries[i].oid] = (struct clean_entry){ .version = entries[i].version, .location = (done_cnt+i) << block_order, diff --git a/blockstore_write.cpp b/blockstore_write.cpp index e0b7c3b6..685bb02d 100644 --- a/blockstore_write.cpp +++ b/blockstore_write.cpp @@ -72,7 +72,7 @@ int blockstore::dequeue_write(blockstore_operation *op) if (op->len == block_size || op->version == 1) { // Big (redirect) write - uint64_t loc = allocator_find_free(data_alloc); + uint64_t loc = data_alloc->find_free(); if (loc == UINT64_MAX) { // no space @@ -83,7 +83,7 @@ int blockstore::dequeue_write(blockstore_operation *op) BS_SUBMIT_GET_SQE(sqe, data); dirty_it->second.location = loc << block_order; dirty_it->second.state = ST_D_SUBMITTED; - allocator_set(data_alloc, loc, true); + data_alloc->set(loc, true); int vcnt = 0; if (op->version == 1 && op->len != block_size) {