Make allocator a class
parent
b8e53f8c67
commit
ff7469ee91
|
@ -1,13 +1,14 @@
|
||||||
|
#include <stdexcept>
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
allocator *allocator_create(uint64_t blocks)
|
allocator::allocator(uint64_t blocks)
|
||||||
{
|
{
|
||||||
if (blocks >= 0x80000000 || blocks <= 1)
|
if (blocks >= 0x80000000 || blocks <= 1)
|
||||||
{
|
{
|
||||||
return NULL;
|
throw std::invalid_argument("blocks");
|
||||||
}
|
}
|
||||||
uint64_t p2 = 1, total = 1;
|
uint64_t p2 = 1, total = 1;
|
||||||
while (p2 * 64 < blocks)
|
while (p2 * 64 < blocks)
|
||||||
|
@ -17,31 +18,30 @@ allocator *allocator_create(uint64_t blocks)
|
||||||
}
|
}
|
||||||
total -= p2;
|
total -= p2;
|
||||||
total += (blocks+63) / 64;
|
total += (blocks+63) / 64;
|
||||||
allocator *buf = (allocator*)memalign(sizeof(uint64_t), (2 + total)*sizeof(uint64_t));
|
mask = new uint64_t[2 + total];
|
||||||
buf->size = blocks;
|
size = blocks;
|
||||||
buf->last_one_mask = (blocks % 64) == 0
|
last_one_mask = (blocks % 64) == 0
|
||||||
? UINT64_MAX
|
? UINT64_MAX
|
||||||
: ~(UINT64_MAX << (64 - blocks % 64));
|
: ~(UINT64_MAX << (64 - blocks % 64));
|
||||||
for (uint64_t i = 0; i < total; i++)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
uint64_t p2 = 1, offset = 0;
|
uint64_t p2 = 1, offset = 0;
|
||||||
while (p2 * 64 < alloc->size)
|
while (p2 * 64 < size)
|
||||||
{
|
{
|
||||||
offset += p2;
|
offset += p2;
|
||||||
p2 = p2 * 64;
|
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 last = offset + cur_addr/64;
|
||||||
uint64_t bit = cur_addr % 64;
|
uint64_t bit = cur_addr % 64;
|
||||||
if (((alloc->mask[last] >> bit) & 1) != value64)
|
if (((mask[last] >> bit) & 1) != value64)
|
||||||
{
|
{
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
alloc->mask[last] = alloc->mask[last] | (1 << bit);
|
mask[last] = mask[last] | (1 << bit);
|
||||||
if (alloc->mask[last] != (!is_last || cur_addr/64 < alloc->size/64
|
if (mask[last] != (!is_last || cur_addr/64 < size/64
|
||||||
? UINT64_MAX : alloc->last_one_mask))
|
? UINT64_MAX : last_one_mask))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alloc->mask[last] = alloc->mask[last] & ~(1 << bit);
|
mask[last] = mask[last] & ~(1 << bit);
|
||||||
if (alloc->mask[last] != 0)
|
if (mask[last] != 0)
|
||||||
{
|
{
|
||||||
break;
|
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;
|
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)
|
for (i = 0, f = 1; i < 64; i++, f <<= 1)
|
||||||
{
|
{
|
||||||
if (!(mask & f))
|
if (!(m & f))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ uint64_t allocator_find_free(allocator *alloc)
|
||||||
return UINT64_MAX;
|
return UINT64_MAX;
|
||||||
}
|
}
|
||||||
addr = (addr * 64) | i;
|
addr = (addr * 64) | i;
|
||||||
if (addr >= alloc->size)
|
if (addr >= size)
|
||||||
{
|
{
|
||||||
// No space
|
// No space
|
||||||
return UINT64_MAX;
|
return UINT64_MAX;
|
||||||
|
|
14
allocator.h
14
allocator.h
|
@ -3,14 +3,14 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// Hierarchical bitmap allocator
|
// Hierarchical bitmap allocator
|
||||||
struct allocator
|
class allocator
|
||||||
{
|
{
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
uint64_t last_one_mask;
|
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);
|
|
||||||
|
|
|
@ -24,9 +24,7 @@ blockstore::blockstore(spp::sparse_hash_map<std::string, std::string> & config,
|
||||||
open_meta(config);
|
open_meta(config);
|
||||||
open_journal(config);
|
open_journal(config);
|
||||||
calc_lengths(config);
|
calc_lengths(config);
|
||||||
data_alloc = allocator_create(block_count);
|
data_alloc = new allocator(block_count);
|
||||||
if (!data_alloc)
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
}
|
||||||
catch (std::exception & e)
|
catch (std::exception & e)
|
||||||
{
|
{
|
||||||
|
@ -46,6 +44,7 @@ blockstore::blockstore(spp::sparse_hash_map<std::string, std::string> & config,
|
||||||
|
|
||||||
blockstore::~blockstore()
|
blockstore::~blockstore()
|
||||||
{
|
{
|
||||||
|
delete data_alloc;
|
||||||
delete flusher;
|
delete flusher;
|
||||||
free(zero_object);
|
free(zero_object);
|
||||||
ringloop->unregister_consumer(ring_consumer);
|
ringloop->unregister_consumer(ring_consumer);
|
||||||
|
|
|
@ -255,7 +255,7 @@ class blockstore
|
||||||
std::vector<obj_ver_id> unsynced_big_writes, unsynced_small_writes;
|
std::vector<obj_ver_id> unsynced_big_writes, unsynced_small_writes;
|
||||||
std::list<blockstore_operation*> in_progress_syncs; // ...and probably here, too
|
std::list<blockstore_operation*> in_progress_syncs; // ...and probably here, too
|
||||||
uint64_t block_count;
|
uint64_t block_count;
|
||||||
allocator *data_alloc;
|
allocator *data_alloc = NULL;
|
||||||
uint8_t *zero_object;
|
uint8_t *zero_object;
|
||||||
|
|
||||||
int meta_fd;
|
int meta_fd;
|
||||||
|
|
|
@ -384,7 +384,7 @@ resume_0:
|
||||||
// Update clean_db and dirty_db, free old data locations
|
// Update clean_db and dirty_db, free old data locations
|
||||||
if (clean_it != bs->clean_db.end() && clean_it->second.location != clean_loc)
|
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] = {
|
bs->clean_db[cur.oid] = {
|
||||||
.version = cur.version,
|
.version = cur.version,
|
||||||
|
@ -395,7 +395,7 @@ resume_0:
|
||||||
{
|
{
|
||||||
if (IS_BIG_WRITE(dirty_it->second.state) && dirty_it->second.location != clean_loc)
|
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];
|
int used = --bs->journal.used_sectors[dirty_it->second.journal_sector];
|
||||||
if (used == 0)
|
if (used == 0)
|
||||||
|
|
|
@ -90,11 +90,11 @@ void blockstore_init_meta::handle_entries(struct clean_disk_entry* entries, int
|
||||||
if (clean_it != bs->clean_db.end())
|
if (clean_it != bs->clean_db.end())
|
||||||
{
|
{
|
||||||
// free the previous block
|
// 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
|
else
|
||||||
entries_loaded++;
|
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){
|
bs->clean_db[entries[i].oid] = (struct clean_entry){
|
||||||
.version = entries[i].version,
|
.version = entries[i].version,
|
||||||
.location = (done_cnt+i) << block_order,
|
.location = (done_cnt+i) << block_order,
|
||||||
|
|
|
@ -72,7 +72,7 @@ int blockstore::dequeue_write(blockstore_operation *op)
|
||||||
if (op->len == block_size || op->version == 1)
|
if (op->len == block_size || op->version == 1)
|
||||||
{
|
{
|
||||||
// Big (redirect) write
|
// Big (redirect) write
|
||||||
uint64_t loc = allocator_find_free(data_alloc);
|
uint64_t loc = data_alloc->find_free();
|
||||||
if (loc == UINT64_MAX)
|
if (loc == UINT64_MAX)
|
||||||
{
|
{
|
||||||
// no space
|
// no space
|
||||||
|
@ -83,7 +83,7 @@ int blockstore::dequeue_write(blockstore_operation *op)
|
||||||
BS_SUBMIT_GET_SQE(sqe, data);
|
BS_SUBMIT_GET_SQE(sqe, data);
|
||||||
dirty_it->second.location = loc << block_order;
|
dirty_it->second.location = loc << block_order;
|
||||||
dirty_it->second.state = ST_D_SUBMITTED;
|
dirty_it->second.state = ST_D_SUBMITTED;
|
||||||
allocator_set(data_alloc, loc, true);
|
data_alloc->set(loc, true);
|
||||||
int vcnt = 0;
|
int vcnt = 0;
|
||||||
if (op->version == 1 && op->len != block_size)
|
if (op->version == 1 && op->len != block_size)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue