Skip to content
80 changes: 58 additions & 22 deletions engines/COMMON/mblock_allocator.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ static void do_mblock_allocator_free_all() {
pool_tail = NULL;
}

static void prepare_eblk_add_elem(eblock_result_t *result) {
if (result->tail_blk == NULL) {
result->tail_blk = result->head_blk;
result->elem_cnt = 0;
} else {
assert(result->elem_cnt > 0);
if (result->elem_cnt % EITEMS_PER_BLOCK == 0)
result->tail_blk = result->tail_blk->next;
}
}

int mblock_allocator_init(size_t nblocks) {
mem_block_t *helper = NULL;
int i;
Expand Down Expand Up @@ -171,32 +182,33 @@ bool mblock_list_alloc(uint32_t blck_cnt, mem_block_t **head_blk, mem_block_t **
total_mblocks += new_cnt;
//pthread_mutex_unlock(&pool_mutex);
if (alloc_cnt < blck_cnt) {
mblock_list_free(alloc_cnt, *head_blk, *tail_blk);
mblock_list_free(alloc_cnt, head_blk, tail_blk);
return false;
}
}

return true;
}

void mblock_list_free(uint32_t blck_cnt, mem_block_t *head_blk, mem_block_t *tail_blk) {
void mblock_list_free(uint32_t blck_cnt, mem_block_t **head_blk, mem_block_t **tail_blk) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mblock_list_free() 함수에서 head_blk와 tail_blk의 data type을 변경할 이유가 없어 보입니다.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

바꾼 의도는 mget같은 연속적인 operation에서 기존 블록에 새 블록을 append할지 아니면 새로운 리스트를 받을지에 대한 판단을 head_blk가 NULL인지 여부로 판단하려고 했고

모든 operation이 eblk_prepare를 통해 블록리스트를 받은 후에는 mblock_list_free를 호출해서 여기서 head_blk를 NULL으로 반환하면 되겠다는 생각때문에 수정했는데 제가 잘못생각한걸까요

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래 글의 의미가 무엇 인지를 분명하게 설명해 주면 좋겠어요.

모든 operation이 eblk_prepare를 통해 블록리스트를 받은 후에는 mblock_list_free를 호출해서 여기서 head_blk를 NULL으로 반환하면 되겠다는 생각

내 의견은

  • mblock_list_alloc()은 mblock list를 allocate하는 함수라서,
    list의 head와 tail pointer를 받아오기 위해 mem_block_t ** 타입이 필요해요.
  • mblock_list_free()는 mblock list를 free하는 함수라서,
    list의 head와 tail pointer 자체를 넘겨주면 되므로, mem_block_t *타입이면 충분해요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일단 수정하면서 multiget과 get의 차이에 대한 판단을 mblock_prepare를 통해 넘어온 eblock_result_t 구조체의 head_blk를 보고 새로운 mblock list를 받거나, 기존 블록 리스트에 더 필요한 mblock들을 append하는 형태대로 수정을 하려고 했고

  • 기존

    • mblock_list_free()함수는 말씀해주신것처럼 free하는 목적으로 head, tail pointer만 넘겨서 반환
  • 변경

    • 의도는 eblk_ret->head_blk를 operation이 끝난 후 NULL로 초기화 해줘야하는데 마땅한 위치를 찾기보다는 get operation 이후엔 모두 free과정을 거치니까 mblock_list_free()함수 내에서 바꿔주면 좋겠다고 판단을 했습니다. mblock_allocator.c 파일내에서 호출되는 경우엔 불필요하긴한데 default engine에서 호출된 mblock_list_free()의 경우 eblk_ret->head_blk를 null로 반환해 주어야 하기때문에 이렇게 수정했습니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prepare 단계에서 block을 붙여서 받을지에 대한 판단을 head_blk == NULL로 하고 있기 때문에,
free하는 단계에서 NULL setting을 해주기 위해선 @jooho812 의견처럼 mem_block_t ** 타입으로
해야될 것 같은데요, 혹시 더 괜찮은 의견이 있으신가요?

만약 free 함수 내부에서 NULL setting을 하지 않는다면, free 함수 호출하고 나서 NULL setting을 밖에서 해주어야 합니다.

//mem_block_t *bye = NULL;
//mem_block_t *bye_helper = NULL;

//pthread_mutex_lock(&pool_mutex);
if (head_blk == NULL || blck_cnt == 0)
if (*head_blk == NULL || blck_cnt == 0)
return;

assert(pool_tail == NULL || pool_tail->next == NULL);
assert(tail_blk->next == NULL);
assert((*tail_blk)->next == NULL);

if (pool_head == NULL) {
pool_head = head_blk;
pool_head = *head_blk;
} else {
pool_tail->next = head_blk;
pool_tail->next = *head_blk;
}
pool_tail = tail_blk;
pool_tail = *tail_blk;

*head_blk = *tail_blk = NULL;
free_mblocks += blck_cnt;
assert(free_mblocks <= total_mblocks);

Expand All @@ -223,17 +235,35 @@ void mblock_list_free(uint32_t blck_cnt, mem_block_t *head_blk, mem_block_t *tai
free(bye_helper);
}*/
}

bool eblk_prepare(eblock_result_t *result, uint32_t elem_count) {
assert(elem_count > 0);
uint32_t blkcnt = ((elem_count - 1) / EITEMS_PER_BLOCK) + 1;
if (!mblock_list_alloc(blkcnt, &result->head_blk, &result->last_blk)) {
result->elem_cnt = 0;
return false;
uint32_t blkcnt;
if (result->head_blk == NULL) { // empty block
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

head_blk이 NULL인 것으로 판단하는 것 보다
flag를 하나 두고 alloc 되었는지 또는 appendMode인지
판단하는게 이해하는데 더 나을 것 같은데 어떤가요?

Copy link
Copy Markdown
Author

@jooho812 jooho812 Sep 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 저렇게 한 의도는 두가지인데

  • 한가지는 appendMode인지 여부를 확인하기 위함도 있고
  • 다른 한가지는 기존에 c->eblk_ret에 블록리스트를 받아 사용후 free해도 아직 블록의 유의미한 주소값이 남아 있게되는데 null로 초기화해주기 위함도 있습니다.

말씀해주신대로 flag를 추가하면 이해하는 측면에서는 더 나아보일 것 같은데, 지금 형태도 나쁘지는 않게 생각이 됩니다.
바꾸는게 나을까요?

blkcnt = ((elem_count - 1) / EITEMS_PER_BLOCK) + 1;
if (!mblock_list_alloc(blkcnt, &result->head_blk, &result->last_blk)) {
result->elem_cnt = 0;
return false;
}
result->tail_blk = NULL;
} else {
mem_block_t *head;
mem_block_t *last;
uint32_t curr_blkcnt = result->blck_cnt;
int alloc_blkcnt;
blkcnt = ((result->elem_cnt + elem_count - 1) / EITEMS_PER_BLOCK) + 1;
alloc_blkcnt = blkcnt - curr_blkcnt;
if (alloc_blkcnt > 0) { // need append block
if (!mblock_list_alloc((alloc_blkcnt), &head, &last))
return false;
result->last_blk->next = head;
result->last_blk = last;
}
}
result->tail_blk = NULL;
result->blck_cnt = blkcnt;
return true;
}

void eblk_truncate(eblock_result_t *result) {
assert(result->last_blk->next == NULL);
/* returns empty blocklist */
Expand All @@ -244,27 +274,33 @@ void eblk_truncate(eblock_result_t *result) {
uint32_t used_nblks = ((result->elem_cnt - 1) / EITEMS_PER_BLOCK) + 1;
uint32_t free_nblks = result->blck_cnt - used_nblks;

mblock_list_free(free_nblks, free_head, free_tail);
mblock_list_free(free_nblks, &free_head, &free_tail);
result->tail_blk->next = NULL;
result->last_blk = result->tail_blk;
result->blck_cnt -= free_nblks;
}
} else { /* ENGINE_ELEM_ENOENT case */
mblock_list_free(result->blck_cnt, result->head_blk, result->last_blk);
mblock_list_free(result->blck_cnt, &result->head_blk, &result->last_blk);
result->head_blk = result->tail_blk = result->last_blk = NULL;
result->elem_cnt = result->blck_cnt = 0;
}
}

void eblk_add_elem(eblock_result_t *result, eitem *elem) {
if (result->tail_blk == NULL) {
result->tail_blk = result->head_blk;
result->elem_cnt = 0;
} else {
assert(result->elem_cnt > 0);
if (result->elem_cnt % EITEMS_PER_BLOCK == 0)
result->tail_blk = result->tail_blk->next;
prepare_eblk_add_elem(result);
result->tail_blk->items[result->elem_cnt++ % EITEMS_PER_BLOCK] = (eitem *)elem;
}

void eblk_add_elem_with_posi(eblock_result_t *result, eitem *elem, int posi) {
mem_block_t *curr_blk = result->head_blk;
int move_block_count = (posi / EITEMS_PER_BLOCK);

while (move_block_count > 0) {
curr_blk = curr_blk->next;
move_block_count--;
}

result->tail_blk->items[result->elem_cnt++ % EITEMS_PER_BLOCK] = (eitem *)elem;
prepare_eblk_add_elem(result);
curr_blk->items[posi % EITEMS_PER_BLOCK] = (eitem *)elem;
result->elem_cnt++;
}
4 changes: 2 additions & 2 deletions engines/COMMON/mblock_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ void mblock_allocator_destroy(void);
void mblock_allocator_stats(mblock_stats *blk_stat);

bool mblock_list_alloc(uint32_t blck_cnt, mem_block_t **head_blk, mem_block_t **tail_blk);
void mblock_list_free(uint32_t blck_cnt, mem_block_t *head_blk, mem_block_t *tail_blk);
void mblock_list_free(uint32_t blck_cnt, mem_block_t **head_blk, mem_block_t **tail_blk);

bool eblk_prepare(eblock_result_t *result, uint32_t elem_count);
void eblk_truncate(eblock_result_t *result);
void eblk_add_elem(eblock_result_t *result, eitem *elem);

void eblk_add_elem_with_posi(eblock_result_t *result, eitem *elem, int posi);
#endif
47 changes: 47 additions & 0 deletions engines/default/default_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,13 +777,23 @@ default_btree_elem_alloc(ENGINE_HANDLE* handle, const void* cookie,
return ret;
}

#ifdef USE_EBLOCK_RESULT
static void
default_btree_elem_release(ENGINE_HANDLE* handle, const void *cookie,
eitem *eitem, EITEM_TYPE type)
{
struct default_engine *engine = get_handle(handle);
btree_elem_release(engine, eitem, type);
}
#else
static void
default_btree_elem_release(ENGINE_HANDLE* handle, const void *cookie,
eitem **eitem_array, const int eitem_count)
{
struct default_engine *engine = get_handle(handle);
btree_elem_release(engine, (btree_elem_item**)eitem_array, eitem_count);
}
#endif

static ENGINE_ERROR_CODE
default_btree_elem_insert(ENGINE_HANDLE* handle, const void* cookie,
Expand Down Expand Up @@ -879,7 +889,11 @@ default_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie,
const bkey_range *bkrange, const eflag_filter *efilter,
const uint32_t offset, const uint32_t req_count,
const bool delete, const bool drop_if_empty,
#ifdef USE_EBLOCK_RESULT
eblock_result_t *eblk_ret,
#else
eitem** eitem_array, uint32_t* eitem_count,
#endif
uint32_t *access_count, uint32_t* flags,
bool* dropped_trimmed, uint16_t vbucket)
{
Expand All @@ -890,7 +904,11 @@ default_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie,
if (delete) ACTION_BEFORE_WRITE(cookie, key, nkey);
ret = btree_elem_get(engine, key, nkey, bkrange, efilter,
offset, req_count, delete, drop_if_empty,
#ifdef USE_EBLOCK_RESULT
eblk_ret,
#else
(btree_elem_item**)eitem_array, eitem_count,
#endif
access_count, flags, dropped_trimmed);
if (delete) ACTION_AFTER_WRITE(cookie, ret);
return ret;
Expand Down Expand Up @@ -932,17 +950,27 @@ default_btree_posi_find_with_get(ENGINE_HANDLE* handle, const void* cookie,
const char *key, const size_t nkey,
const bkey_range *bkrange,
ENGINE_BTREE_ORDER order, const uint32_t count,
#ifdef USE_EBLOCK_RESULT
int *position, eblock_result_t *eblk_ret,
uint32_t *eitem_index,
#else
int *position, eitem **eitem_array,
uint32_t *eitem_count, uint32_t *eitem_index,
#endif
uint32_t *flags, uint16_t vbucket)
{
struct default_engine *engine = get_handle(handle);
ENGINE_ERROR_CODE ret;
VBUCKET_GUARD(engine, vbucket);

ret = btree_posi_find_with_get(engine, key, nkey, bkrange, order, count,
#ifdef USE_EBLOCK_RESULT
position, eblk_ret,
eitem_index, flags);
#else
position, (btree_elem_item**)eitem_array,
eitem_count, eitem_index, flags);
#endif
return ret;
}

Expand All @@ -951,15 +979,23 @@ default_btree_elem_get_by_posi(ENGINE_HANDLE* handle, const void* cookie,
const char *key, const size_t nkey,
ENGINE_BTREE_ORDER order,
uint32_t from_posi, uint32_t to_posi,
#ifdef USE_EBLOCK_RESULT
eblock_result_t *eblk_ret,
#else
eitem **eitem_array, uint32_t *eitem_count,
#endif
uint32_t *flags, uint16_t vbucket)
{
struct default_engine *engine = get_handle(handle);
ENGINE_ERROR_CODE ret;
VBUCKET_GUARD(engine, vbucket);

ret = btree_elem_get_by_posi(engine, key, nkey, order, from_posi, to_posi,
#ifdef USE_EBLOCK_RESULT
eblk_ret,
#else
(btree_elem_item**)eitem_array, eitem_count,
#endif
flags);
return ret;
}
Expand All @@ -973,10 +1009,16 @@ default_btree_elem_smget_old(ENGINE_HANDLE* handle, const void* cookie,
const bkey_range *bkrange,
const eflag_filter *efilter,
const uint32_t offset, const uint32_t count,
#ifdef USE_EBLOCK_RESULT
eblock_result_t *eblk_ret,
uint32_t* kfnd_array,
uint32_t* flag_array,
#else
eitem** eitem_array,
uint32_t* kfnd_array,
uint32_t* flag_array,
uint32_t* eitem_count,
#endif
uint32_t* missed_key_array,
uint32_t* missed_key_count,
bool *trimmed, bool *duplicated,
Expand All @@ -987,8 +1029,13 @@ default_btree_elem_smget_old(ENGINE_HANDLE* handle, const void* cookie,
VBUCKET_GUARD(engine, vbucket);

ret = btree_elem_smget_old(engine, karray, kcount, bkrange, efilter,
#ifdef USE_EBLOCK_RESULT
offset, count, eblk_ret,
kfnd_array, flag_array,
#else
offset, count, (btree_elem_item**)eitem_array,
kfnd_array, flag_array, eitem_count,
#endif
missed_key_array, missed_key_count,
trimmed, duplicated);
return ret;
Expand Down
Loading