#include "container_ctree.h"
#include "ctree.h"
#include "out.h"
#include "sys_util.h"
#define CHUNK_KEY_PACK(z, c, b, s)\
((uint64_t)(s) << 48 | (uint64_t)(b) << 32 | (uint64_t)(c) << 16 | (z))
#define CHUNK_KEY_GET_ZONE_ID(k)\
((uint16_t)((k & 0xFFFF)))
#define CHUNK_KEY_GET_CHUNK_ID(k)\
((uint16_t)((k & 0xFFFF0000) >> 16))
#define CHUNK_KEY_GET_BLOCK_OFF(k)\
((uint16_t)((k & 0xFFFF00000000) >> 32))
#define CHUNK_KEY_GET_SIZE_IDX(k)\
((uint16_t)((k & 0xFFFF000000000000) >> 48))
struct block_container_ctree {
struct block_container super;
struct ctree *tree;
};
static int
container_ctree_insert_block(struct block_container *bc,
const struct memory_block *m)
{
ASSERT(m->chunk_id < MAX_CHUNK);
ASSERT(m->zone_id < UINT16_MAX);
ASSERTne(m->size_idx, 0);
struct block_container_ctree *c = (struct block_container_ctree *)bc;
uint64_t key = CHUNK_KEY_PACK(m->zone_id, m->chunk_id, m->block_off,
m->size_idx);
return ctree_insert_unlocked(c->tree, key, 0);
}
static int
container_ctree_get_rm_block_bestfit(struct block_container *bc,
struct memory_block *m)
{
uint64_t key = CHUNK_KEY_PACK(m->zone_id, m->chunk_id, m->block_off,
m->size_idx);
struct block_container_ctree *c = (struct block_container_ctree *)bc;
if ((key = ctree_remove_unlocked(c->tree, key, 0)) == 0)
return ENOMEM;
m->chunk_id = CHUNK_KEY_GET_CHUNK_ID(key);
m->zone_id = CHUNK_KEY_GET_ZONE_ID(key);
m->block_off = CHUNK_KEY_GET_BLOCK_OFF(key);
m->size_idx = CHUNK_KEY_GET_SIZE_IDX(key);
memblock_rebuild_state(bc->heap, m);
return 0;
}
static int
container_ctree_get_rm_block_exact(struct block_container *bc,
const struct memory_block *m)
{
uint64_t key = CHUNK_KEY_PACK(m->zone_id, m->chunk_id, m->block_off,
m->size_idx);
struct block_container_ctree *c = (struct block_container_ctree *)bc;
if ((key = ctree_remove_unlocked(c->tree, key, 1)) == 0)
return ENOMEM;
return 0;
}
static int
container_ctree_get_block_exact(struct block_container *bc,
const struct memory_block *m)
{
uint64_t key = CHUNK_KEY_PACK(m->zone_id, m->chunk_id, m->block_off,
m->size_idx);
struct block_container_ctree *c = (struct block_container_ctree *)bc;
return ctree_find_unlocked(c->tree, key) == key ? 0 : ENOMEM;
}
static int
container_ctree_is_empty(struct block_container *bc)
{
struct block_container_ctree *c = (struct block_container_ctree *)bc;
return ctree_is_empty_unlocked(c->tree);
}
static void
container_ctree_rm_all(struct block_container *bc)
{
struct block_container_ctree *c = (struct block_container_ctree *)bc;
ctree_clear_unlocked(c->tree);
}
static void
container_ctree_destroy(struct block_container *bc)
{
struct block_container_ctree *c = (struct block_container_ctree *)bc;
ctree_delete(c->tree);
Free(c);
}
static struct block_container_ops container_ctree_ops = {
.insert = container_ctree_insert_block,
.get_rm_exact = container_ctree_get_rm_block_exact,
.get_rm_bestfit = container_ctree_get_rm_block_bestfit,
.get_exact = container_ctree_get_block_exact,
.is_empty = container_ctree_is_empty,
.rm_all = container_ctree_rm_all,
.destroy = container_ctree_destroy,
};
struct block_container *
container_new_ctree(struct palloc_heap *heap)
{
struct block_container_ctree *bc = Malloc(sizeof(*bc));
if (bc == NULL)
goto error_container_malloc;
bc->super.heap = heap;
bc->super.c_ops = &container_ctree_ops;
bc->tree = ctree_new();
if (bc->tree == NULL)
goto error_ctree_new;
return (struct block_container *)&bc->super;
error_ctree_new:
Free(bc);
error_container_malloc:
return NULL;
}