From 06d95da4ddc11ae74dd38de1d6b179faca7d9a7d Mon Sep 17 00:00:00 2001 From: jooho812 Date: Tue, 11 Jul 2017 10:05:35 +0900 Subject: [PATCH 01/11] FEATURE : Add block allocator for moere efficient memory management - This feature is applied only on btree collection. --- engines/COMMON/mblock_allocator.c | 13 + engines/COMMON/mblock_allocator.h | 2 +- engines/default/default_engine.c | 48 +++ engines/default/items.c | 217 +++++++++++ engines/default/items.h | 22 ++ engines/demo/demo_engine.c | 23 ++ include/memcached/engine.h | 24 ++ include/memcached/types.h | 40 +- memcached.c | 609 ++++++++++++++++++++++++++++++ memcached.h | 3 + 10 files changed, 992 insertions(+), 9 deletions(-) diff --git a/engines/COMMON/mblock_allocator.c b/engines/COMMON/mblock_allocator.c index 7faae52b8..6e481ee4b 100644 --- a/engines/COMMON/mblock_allocator.c +++ b/engines/COMMON/mblock_allocator.c @@ -223,6 +223,7 @@ 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; @@ -234,6 +235,7 @@ bool eblk_prepare(eblock_result_t *result, uint32_t elem_count) { result->blck_cnt = blkcnt; return true; } + void eblk_truncate(eblock_result_t *result) { assert(result->last_blk->next == NULL); /* returns empty blocklist */ @@ -268,3 +270,14 @@ void eblk_add_elem(eblock_result_t *result, eitem *elem) { 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) { + /* This function should not be used when there are multiple blocks. */ + assert(result->blck_cnt == 1); + if (result->tail_blk == NULL) { + result->tail_blk = result->head_blk; + result->elem_cnt = 0; + } + result->tail_blk->items[posi % EITEMS_PER_BLOCK] = (eitem *)elem; + result->elem_cnt++; +} diff --git a/engines/COMMON/mblock_allocator.h b/engines/COMMON/mblock_allocator.h index 4b16c52ec..a0d361b83 100644 --- a/engines/COMMON/mblock_allocator.h +++ b/engines/COMMON/mblock_allocator.h @@ -34,5 +34,5 @@ void mblock_list_free(uint32_t blck_cnt, mem_block_t *head_blk, mem_block_t *tai 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 diff --git a/engines/default/default_engine.c b/engines/default/default_engine.c index f22b14f16..50db854bc 100644 --- a/engines/default/default_engine.c +++ b/engines/default/default_engine.c @@ -777,6 +777,15 @@ 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) @@ -784,6 +793,7 @@ default_btree_elem_release(ENGINE_HANDLE* handle, const void *cookie, 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, @@ -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) { @@ -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; @@ -932,8 +950,13 @@ 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); @@ -941,8 +964,13 @@ default_btree_posi_find_with_get(ENGINE_HANDLE* handle, const void* cookie, 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; } @@ -950,8 +978,13 @@ static ENGINE_ERROR_CODE default_btree_elem_get_by_posi(ENGINE_HANDLE* handle, const void* cookie, const char *key, const size_t nkey, ENGINE_BTREE_ORDER order, +#ifdef USE_EBLOCK_RESULT + uint32_t from_posi, uint32_t to_posi, + eblock_result_t *eblk_ret, +#else int from_posi, int to_posi, eitem **eitem_array, uint32_t *eitem_count, +#endif uint32_t *flags, uint16_t vbucket) { struct default_engine *engine = get_handle(handle); @@ -959,7 +992,11 @@ default_btree_elem_get_by_posi(ENGINE_HANDLE* handle, const void* cookie, 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; } @@ -973,10 +1010,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, @@ -987,8 +1030,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; diff --git a/engines/default/items.c b/engines/default/items.c index da57cab1e..843bc1ed6 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -2490,6 +2490,20 @@ static void do_btree_elem_free(struct default_engine *engine, btree_elem_item *e do_mem_slot_free(engine, elem, ntotal); } +#ifdef USE_EBLOCK_RESULT +static void do_btree_elem_release(struct default_engine *engine, eitem *eitem) +{ + /* assert(elem->status != BTREE_ITEM_STATUS_FREE); */ + btree_elem_item *elem = (btree_elem_item *)eitem; + if (elem->refcount != 0) { + elem->refcount--; + } + if (elem->refcount == 0 && elem->status == BTREE_ITEM_STATUS_UNLINK) { + elem->status = BTREE_ITEM_STATUS_FREE; + do_btree_elem_free(engine, elem); + } +} +#else static void do_btree_elem_release(struct default_engine *engine, btree_elem_item *elem) { /* assert(elem->status != BTREE_ITEM_STATUS_FREE); */ @@ -2501,6 +2515,7 @@ static void do_btree_elem_release(struct default_engine *engine, btree_elem_item do_btree_elem_free(engine, elem); } } +#endif static inline btree_elem_item *do_btree_get_first_elem(btree_indx_node *node) { @@ -4461,9 +4476,14 @@ static bool do_btree_overlapped_with_trimmed_space(btree_meta_info *info, static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_meta_info *info, const int bkrtype, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t count, const bool delete, +#ifdef USE_EBLOCK_RESULT + eblock_result_t *eblk_ret, +#else btree_elem_item **elem_array, uint32_t *elem_count, +#endif uint32_t *access_count, bool *potentialbkeytrim) { + btree_elem_posi path[BTREE_MAX_DEPTH]; btree_elem_item *elem; uint32_t tot_found = 0; /* total found count */ @@ -4471,6 +4491,14 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ *potentialbkeytrim = false; +#ifdef USE_EBLOCK_RESULT + if (EBLOCK_HEAD(eblk_ret) == NULL) { + uint32_t max_cnt = (EBLOCK_NKEY_COUNT(eblk_ret) > 1) ? max_btree_size : info->ccnt; + uint32_t need_size = (count > 0 && count < max_cnt) ? count : max_cnt; + if (!eblk_prepare(eblk_ret, need_size * EBLOCK_NKEY_COUNT(eblk_ret))) + return ENGINE_ENOMEM; + } +#endif if (info->root == NULL) { if (access_count) *access_count = 0; @@ -4486,7 +4514,12 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ if (offset == 0) { if (efilter == NULL || do_btree_elem_filter(elem, efilter)) { elem->refcount++; +#ifdef USE_EBLOCK_RESULT + eblk_add_elem(eblk_ret, elem); + tot_found++; +#else elem_array[tot_found++] = elem; +#endif if (delete) { do_btree_elem_unlink(engine, info, path, ELEM_DELETE_NORMAL); } @@ -4527,7 +4560,11 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ skip_cnt++; } else { elem->refcount++; +#ifdef USE_EBLOCK_RESULT + eblk_add_elem(eblk_ret, elem); +#else elem_array[tot_found+cur_found] = elem; +#endif if (delete) { stotal += slabs_space_size(engine, do_btree_elem_ntotal(elem)); elem->status = BTREE_ITEM_STATUS_UNLINK; @@ -4606,7 +4643,10 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ if (access_count) *access_count = tot_access; +#ifdef USE_EBLOCK_RESULT +#else *elem_count = tot_found; +#endif if (tot_found > 0) { return ENGINE_SUCCESS; } else { @@ -4837,7 +4877,11 @@ static int do_btree_posi_find(btree_meta_info *info, static int do_btree_elem_batch_get(btree_elem_posi posi, const int count, const bool forward, const bool reverse, +#ifdef USE_EBLOCK_RESULT + eblock_result_t *eblk_ret, int position) +#else btree_elem_item **elem_array) +#endif { btree_elem_item *elem; int nfound = 0; @@ -4848,24 +4892,41 @@ static int do_btree_elem_batch_get(btree_elem_posi posi, const int count, elem = BTREE_GET_ELEM_ITEM(posi.node, posi.indx); elem->refcount++; +#ifdef USE_EBLOCK_RESULT + if (reverse) eblk_add_elem_with_posi(eblk_ret, elem, position+count-nfound-1); + else eblk_add_elem(eblk_ret, elem); +#else if (reverse) elem_array[count-nfound-1] = elem; else elem_array[nfound] = elem; +#endif nfound += 1; } return nfound; } +#ifdef USE_EBLOCK_RESULT +static ENGINE_ERROR_CODE do_btree_posi_find_with_get(btree_meta_info *info, + const int bkrtype, const bkey_range *bkrange, + ENGINE_BTREE_ORDER order, const int count, + eblock_result_t *eblk_ret, int *position, + uint32_t *elem_index) +#else static int do_btree_posi_find_with_get(btree_meta_info *info, const int bkrtype, const bkey_range *bkrange, ENGINE_BTREE_ORDER order, const int count, btree_elem_item **elem_array, uint32_t *elem_count, uint32_t *elem_index) +#endif { btree_elem_posi path[BTREE_MAX_DEPTH]; btree_elem_item *elem; int bpos, ecnt, eidx; +#ifdef USE_EBLOCK_RESULT + if (info->root == NULL) return ENGINE_ELEM_ENOENT; +#else if (info->root == NULL) return -1; /* not found */ +#endif elem = do_btree_find_first(info->root, bkrtype, bkrange, path, true); if (elem != NULL) { @@ -4876,6 +4937,22 @@ static int do_btree_posi_find_with_get(btree_meta_info *info, ecnt = 1; /* elem count */ eidx = (bpos < count) ? bpos : count; /* elem index in elem array */ elem->refcount++; +#ifdef USE_EBLOCK_RESULT + if (!eblk_prepare(eblk_ret, (eidx + count + 1))) + return ENGINE_ENOMEM; + + eblk_add_elem_with_posi(eblk_ret, elem, eidx); + if (order == BTREE_ORDER_ASC) { + ecnt += do_btree_elem_batch_get(path[0], eidx, false, true, eblk_ret, 0); + assert((ecnt-1) == eidx); + ecnt += do_btree_elem_batch_get(path[0], count, true, false, eblk_ret, eidx+1); + } else { + ecnt += do_btree_elem_batch_get(path[0], eidx, true, true, eblk_ret, 0); + assert((ecnt-1) == eidx); + ecnt += do_btree_elem_batch_get(path[0], count, false, false, eblk_ret, eidx+1); + } + eblk_truncate(eblk_ret); +#else elem_array[eidx] = elem; if (order == BTREE_ORDER_ASC) { @@ -4888,16 +4965,27 @@ static int do_btree_posi_find_with_get(btree_meta_info *info, ecnt += do_btree_elem_batch_get(path[0], count, false, false, &elem_array[eidx+1]); } *elem_count = (uint32_t)ecnt; +#endif *elem_index = (uint32_t)eidx; } else { bpos = -1; /* not found */ } +#ifdef USE_EBLOCK_RESULT + *position = bpos; + if (bpos < 0) return ENGINE_ELEM_ENOENT; + else return ENGINE_SUCCESS; +#else return bpos; /* btree_position */ +#endif } static ENGINE_ERROR_CODE do_btree_elem_get_by_posi(btree_meta_info *info, const int index, const uint32_t count, const bool forward, +#ifdef USE_EBLOCK_RESULT + eblock_result_t *eblk_ret) +#else btree_elem_item **elem_array, uint32_t *elem_count) +#endif { btree_elem_posi posi; btree_indx_node *node; @@ -4907,6 +4995,10 @@ static ENGINE_ERROR_CODE do_btree_elem_get_by_posi(btree_meta_info *info, if (info->root == NULL) return ENGINE_ELEM_ENOENT; +#ifdef USE_EBLOCK_RESULT + if (!eblk_prepare(eblk_ret, (count > 0 && count < info->ccnt) ? count : info->ccnt)) + return ENGINE_ENOMEM; +#endif node = info->root; tot_ecnt = 0; while (node->ndepth > 0) { @@ -4924,12 +5016,23 @@ static ENGINE_ERROR_CODE do_btree_elem_get_by_posi(btree_meta_info *info, elem = BTREE_GET_ELEM_ITEM(posi.node, posi.indx); elem->refcount++; +#ifdef USE_EBLOCK_RESULT + eblk_add_elem(eblk_ret, elem); + nfound = 1; + nfound += do_btree_elem_batch_get(posi, count-1, forward, false, eblk_ret, 1); +#else elem_array[0] = elem; nfound = 1; nfound += do_btree_elem_batch_get(posi, count-1, forward, false, &elem_array[nfound]); +#endif +#ifdef USE_EBLOCK_RESULT + eblk_truncate(eblk_ret); + if (nfound > 0) { +#else *elem_count = nfound; if (*elem_count > 0) { +#endif return ENGINE_SUCCESS; } else { return ENGINE_ELEM_ENOENT; @@ -5038,7 +5141,11 @@ static bool do_btree_smget_check_trim(smget_result_t *smres) static void do_btree_smget_adjust_trim(smget_result_t *smres) { +#ifdef USE_EBLOCK_RESULT + eitem **new_trim_elems = smres->trim_elems; +#else eitem **new_trim_elems = &smres->elem_array[smres->elem_count]; +#endif smget_emis_t *new_trim_kinfo = &smres->miss_kinfo[smres->miss_count]; uint32_t new_trim_count = 0; btree_elem_item *tail_elem = NULL; @@ -5053,7 +5160,11 @@ static void do_btree_smget_adjust_trim(smget_result_t *smres) * we might trim the trimmed keys if the bkey-before-trim is behind * the bkey of the last found element. */ +#ifdef USE_EBLOCK_RESULT + tail_elem = (btree_elem_item *)EBLOCK_ELEM_LAST(smres->eblk_ret); +#else tail_elem = smres->elem_array[smres->elem_count-1]; +#endif } for (idx = smres->trim_count-1; idx >= 0; idx--) @@ -5107,6 +5218,10 @@ static void do_btree_smget_adjust_trim(smget_result_t *smres) smres->trim_elems = new_trim_elems; smres->trim_kinfo = new_trim_kinfo; smres->trim_count = new_trim_count; +#ifdef USE_EBLOCK_RESULT + for (i = 0; i < smres->trim_count; i++) + eblk_add_elem(smres->eblk_ret, smres->trim_elems[i]); +#endif } #ifdef JHPARK_OLD_SMGET_INTERFACE @@ -5559,8 +5674,13 @@ do_btree_smget_scan_sort(struct default_engine *engine, static ENGINE_ERROR_CODE do_btree_smget_elem_sort_old(btree_scan_info *btree_scan_buf, uint16_t *sort_sindx_buf, const int sort_sindx_cnt, const int bkrtype, const bkey_range *bkrange, const eflag_filter *efilter, +#ifdef USE_EBLOCK_RESULT + const uint32_t offset, const uint32_t count, eblock_result_t *eblk_ret, + uint32_t *kfnd_array, uint32_t *flag_array, +#else const uint32_t offset, const uint32_t count, btree_elem_item **elem_array, uint32_t *kfnd_array, uint32_t *flag_array, uint32_t *elem_count, +#endif bool *potentialbkeytrim, bool *bkey_duplicated) { btree_meta_info *info; @@ -5571,9 +5691,17 @@ static ENGINE_ERROR_CODE do_btree_smget_elem_sort_old(btree_scan_info *btree_sca int i, cmp_res; int mid, left, right; int skip_count = 0; +#ifdef USE_EBLOCK_RESULT + int elem_count = 0; +#endif int sort_count = sort_sindx_cnt; bool ascending = (bkrtype != BKEY_RANGE_TYPE_DSC ? true : false); +#ifdef USE_EBLOCK_RESULT + if (!eblk_prepare(eblk_ret, count)) + return ENGINE_ENOMEM; +#else *elem_count = 0; +#endif while (sort_count > 0) { curr_idx = sort_sindx_buf[first_idx]; @@ -5583,11 +5711,19 @@ static ENGINE_ERROR_CODE do_btree_smget_elem_sort_old(btree_scan_info *btree_sca skip_count++; } else { /* skip_count == offset */ elem->refcount++; +#ifdef USE_EBLOCK_RESULT + eblk_add_elem(eblk_ret, elem); + kfnd_array[elem_count] = btree_scan_buf[curr_idx].kidx; + flag_array[elem_count] = btree_scan_buf[curr_idx].it->flags; + elem_count += 1; + if (elem_count >= count) break; +#else elem_array[*elem_count] = elem; kfnd_array[*elem_count] = btree_scan_buf[curr_idx].kidx; flag_array[*elem_count] = btree_scan_buf[curr_idx].it->flags; *elem_count += 1; if (*elem_count >= count) break; +#endif } scan_next: @@ -5646,6 +5782,9 @@ static ENGINE_ERROR_CODE do_btree_smget_elem_sort_old(btree_scan_info *btree_sca } sort_sindx_buf[right] = curr_idx; } +#ifdef USE_EBLOCK_RESULT + eblk_truncate(eblk_ret); +#endif return ENGINE_SUCCESS; } @@ -5672,6 +5811,10 @@ do_btree_smget_elem_sort(btree_scan_info *btree_scan_buf, int skip_count = 0; int sort_count = sort_sindx_cnt; bool ascending = (bkrtype != BKEY_RANGE_TYPE_DSC ? true : false); +#ifdef USE_EBLOCK_RESULT + if (!eblk_prepare(smres->eblk_ret, smres->elem_arrsz + smres->keys_arrsz)) /* elem_count + trim_count */ + return ENGINE_ENOMEM; +#endif while (sort_count > 0) { curr_idx = sort_sindx_buf[first_idx]; @@ -5680,7 +5823,11 @@ do_btree_smget_elem_sort(btree_scan_info *btree_scan_buf, if (skip_count < offset) { skip_count++; } else { /* skip_count == offset */ +#ifdef USE_EBLOCK_RESULT + eblk_add_elem(smres->eblk_ret, elem); +#else smres->elem_array[smres->elem_count] = elem; +#endif smres->elem_kinfo[smres->elem_count].kidx = btree_scan_buf[curr_idx].kidx; smres->elem_kinfo[smres->elem_count].flag = btree_scan_buf[curr_idx].it->flags; smres->elem_count += 1; @@ -5771,6 +5918,9 @@ do_btree_smget_elem_sort(btree_scan_info *btree_scan_buf, do_btree_smget_adjust_trim(smres); } } +#ifdef USE_EBLOCK_RESULT + eblk_truncate(smres->eblk_ret); +#endif return ret; } #endif @@ -6892,6 +7042,13 @@ btree_elem_item *btree_elem_alloc(struct default_engine *engine, return elem; } +#ifdef USE_EBLOCK_RESULT +void btree_elem_release(struct default_engine *engine, + eitem *eitem, EITEM_TYPE type) +{ + do_coll_elem_release(engine, eitem, type, do_btree_elem_release); +} +#else void btree_elem_release(struct default_engine *engine, btree_elem_item **elem_array, const int elem_count) { @@ -6906,6 +7063,7 @@ void btree_elem_release(struct default_engine *engine, } pthread_mutex_unlock(&engine->cache_lock); } +#endif ENGINE_ERROR_CODE btree_elem_insert(struct default_engine *engine, const char *key, const size_t nkey, @@ -7084,7 +7242,11 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, 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 btree_elem_item **elem_array, uint32_t *elem_count, +#endif uint32_t *access_count, uint32_t *flags, bool *dropped_trimmed) { @@ -7109,9 +7271,15 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, (info->bktype == BKEY_TYPE_BINARY && bkrange->from_nbkey == 0)) { ret = ENGINE_EBADBKEY; break; } +#ifdef USE_EBLOCK_RESULT + ret = do_btree_elem_get(engine, info, bkrtype, bkrange, efilter, + offset, req_count, delete, + eblk_ret, access_count, &potentialbkeytrim); +#else ret = do_btree_elem_get(engine, info, bkrtype, bkrange, efilter, offset, req_count, delete, elem_array, elem_count, access_count, &potentialbkeytrim); +#endif if (ret == ENGINE_SUCCESS) { if (delete) { if (info->ccnt == 0 && drop_if_empty) { @@ -7128,11 +7296,19 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, } else { if (potentialbkeytrim == true) ret = ENGINE_EBKEYOOR; +#ifdef USE_EBLOCK_RESULT + /* ret = ENGINE_ENOENT or ENGINE_ELEM_ENOENT; */ +#else /* ret = ENGINE_ELEM_ENOENT; */ +#endif } } while (0); do_item_release(engine, it); } +#ifdef USE_EBLOCK_RESULT + if (--EBLOCK_NKEY_COUNT(eblk_ret) < 1 && EBLOCK_HEAD(eblk_ret) != NULL) + eblk_truncate(eblk_ret); +#endif pthread_mutex_unlock(&engine->cache_lock); return ret; } @@ -7209,7 +7385,11 @@ ENGINE_ERROR_CODE btree_posi_find_with_get(struct default_engine *engine, const char *key, const size_t nkey, const bkey_range *bkrange, ENGINE_BTREE_ORDER order, const int count, int *position, +#ifdef USE_EBLOCK_RESULT + eblock_result_t *eblk_ret, +#else btree_elem_item **elem_array, uint32_t *elem_count, +#endif uint32_t *elem_index, uint32_t *flags) { hash_item *it; @@ -7234,11 +7414,17 @@ ENGINE_ERROR_CODE btree_posi_find_with_get(struct default_engine *engine, (info->bktype == BKEY_TYPE_BINARY && bkrange->from_nbkey == 0)) { ret = ENGINE_EBADBKEY; break; } +#ifdef USE_EBLOCK_RESULT + ret = do_btree_posi_find_with_get(info, bkrtype, bkrange, order, count, + eblk_ret, position, elem_index); + if (ret != ENGINE_SUCCESS) break; /* ENGINE_ELEM_ENOENT or ENGINE_ENOMEM */ +#else *position = do_btree_posi_find_with_get(info, bkrtype, bkrange, order, count, elem_array, elem_count, elem_index); if (*position < 0) { ret = ENGINE_ELEM_ENOENT; break; } +#endif *flags = it->flags; } while (0); do_item_release(engine, it); @@ -7249,8 +7435,13 @@ ENGINE_ERROR_CODE btree_posi_find_with_get(struct default_engine *engine, ENGINE_ERROR_CODE btree_elem_get_by_posi(struct default_engine *engine, const char *key, const size_t nkey, +#ifdef USE_EBLOCK_RESULT + ENGINE_BTREE_ORDER order, uint32_t from_posi, uint32_t to_posi, + eblock_result_t *eblk_ret, uint32_t *flags) +#else ENGINE_BTREE_ORDER order, int from_posi, int to_posi, btree_elem_item **elem_array, uint32_t *elem_count, uint32_t *flags) +#endif { hash_item *it; btree_meta_info *info; @@ -7258,7 +7449,10 @@ ENGINE_ERROR_CODE btree_elem_get_by_posi(struct default_engine *engine, uint32_t rqcount; bool forward; +#ifdef USE_EBLOCK_RESULT +#else assert(from_posi >= 0 && to_posi >= 0); +#endif pthread_mutex_lock(&engine->cache_lock); ret = do_btree_item_find(engine, key, nkey, true, &it); @@ -7288,9 +7482,15 @@ ENGINE_ERROR_CODE btree_elem_get_by_posi(struct default_engine *engine, forward = false; rqcount = from_posi - to_posi + 1; } +#ifdef USE_EBLOCK_RESULT + ret = do_btree_elem_get_by_posi(info, from_posi, rqcount, forward, eblk_ret); + if (ret != ENGINE_SUCCESS) /* ret = ENGINE_ELEM_ENOENT or ENGINE_ELEM_ENOENT */ + break; +#else ret = do_btree_elem_get_by_posi(info, from_posi, rqcount, forward, elem_array, elem_count); if (ret != ENGINE_SUCCESS) /* ret == ENGINE_ELEM_ENOENT */ break; +#endif *flags = it->flags; } while (0); do_item_release(engine, it); @@ -7305,8 +7505,13 @@ ENGINE_ERROR_CODE btree_elem_smget_old(struct default_engine *engine, token_t *key_array, const int key_count, 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 btree_elem_item **elem_array, uint32_t *kfnd_array, uint32_t *flag_array, uint32_t *elem_count, +#endif uint32_t *missed_key_array, uint32_t *missed_key_count, bool *trimmed, bool *duplicated) { @@ -7333,10 +7538,17 @@ ENGINE_ERROR_CODE btree_elem_smget_old(struct default_engine *engine, missed_key_array, missed_key_count, duplicated); if (ret == ENGINE_SUCCESS) { /* the 2nd phase: get the sorted elems */ +#ifdef USE_EBLOCK_RESULT + ret = do_btree_smget_elem_sort_old(btree_scan_buf, sort_sindx_buf, sort_sindx_cnt, + bkrtype, bkrange, efilter, offset, count, + eblk_ret, kfnd_array, flag_array, + trimmed, duplicated); +#else ret = do_btree_smget_elem_sort_old(btree_scan_buf, sort_sindx_buf, sort_sindx_cnt, bkrtype, bkrange, efilter, offset, count, elem_array, kfnd_array, flag_array, elem_count, trimmed, duplicated); +#endif for (i = 0; i <= (offset+count); i++) { if (btree_scan_buf[i].it != NULL) do_item_release(engine, btree_scan_buf[i].it); @@ -7368,10 +7580,15 @@ ENGINE_ERROR_CODE btree_elem_smget(struct default_engine *engine, } /* initialize smget result structure */ +#ifdef USE_EBLOCK_RESULT + /* trim_elems, elem_kinfo, miss_kinfo, already init */ + assert(result->trim_elems != NULL); +#else assert(result->elem_array != NULL); result->trim_elems = (eitem *)&result->elem_array[count]; result->elem_kinfo = (smget_ehit_t *)&result->elem_array[count + key_count]; result->miss_kinfo = (smget_emis_t *)&result->elem_kinfo[count]; +#endif result->trim_kinfo = result->miss_kinfo; result->elem_count = 0; result->miss_count = 0; diff --git a/engines/default/items.h b/engines/default/items.h index 02856f20b..4f423a831 100644 --- a/engines/default/items.h +++ b/engines/default/items.h @@ -530,7 +530,11 @@ btree_elem_item *btree_elem_alloc(struct default_engine *engine, const void *cookie); void btree_elem_release(struct default_engine *engine, +#ifdef USE_EBLOCK_RESULT + eitem *eitem, EITEM_TYPE type); +#else btree_elem_item **elem_array, const int elem_count); +#endif ENGINE_ERROR_CODE btree_elem_insert(struct default_engine *engine, const char *key, const size_t nkey, @@ -562,7 +566,11 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, 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 btree_elem_item **elem_array, uint32_t *elem_count, +#endif uint32_t *access_count, uint32_t *flags, bool *dropped_trimmed); @@ -579,13 +587,22 @@ ENGINE_ERROR_CODE btree_posi_find_with_get(struct default_engine *engine, const char *key, const size_t nkey, const bkey_range *bkrange, ENGINE_BTREE_ORDER order, const int count, int *position, +#ifdef USE_EBLOCK_RESULT + eblock_result_t *eblk_ret, +#else btree_elem_item **elem_array, uint32_t *elem_count, +#endif uint32_t *elem_index, uint32_t *flags); ENGINE_ERROR_CODE btree_elem_get_by_posi(struct default_engine *engine, const char *key, const size_t nkey, +#ifdef USE_EBLOCK_RESULT + ENGINE_BTREE_ORDER order, uint32_t from_posi, uint32_t to_posi, + eblock_result_t *eblk_ret, uint32_t *flags); +#else ENGINE_BTREE_ORDER order, int from_posi, int to_posi, btree_elem_item **elem_array, uint32_t *elem_count, uint32_t *flags); +#endif #ifdef SUPPORT_BOP_SMGET #ifdef JHPARK_OLD_SMGET_INTERFACE @@ -594,8 +611,13 @@ ENGINE_ERROR_CODE btree_elem_smget_old(struct default_engine *engine, token_t *key_array, const int key_count, 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 btree_elem_item **elem_array, uint32_t *kfnd_array, uint32_t *flag_array, uint32_t *elem_count, +#endif uint32_t *missed_key_array, uint32_t *missed_key_count, bool *trimmed, bool *duplicated); #endif diff --git a/engines/demo/demo_engine.c b/engines/demo/demo_engine.c index 73c730085..ac33ca138 100644 --- a/engines/demo/demo_engine.c +++ b/engines/demo/demo_engine.c @@ -511,12 +511,21 @@ Demo_btree_elem_alloc(ENGINE_HANDLE* handle, const void* cookie, return ENGINE_ENOTSUP; } +#ifdef USE_EBLOCK_RESULT +static void +Demo_btree_elem_release(ENGINE_HANDLE* handle, const void *cookie, + eitem *eitem, EITEM_TYPE type) +{ + return; +} +#else static void Demo_btree_elem_release(ENGINE_HANDLE* handle, const void *cookie, eitem **eitem_array, const int eitem_count) { return; } +#endif static ENGINE_ERROR_CODE Demo_btree_elem_insert(ENGINE_HANDLE* handle, const void* cookie, @@ -567,7 +576,11 @@ Demo_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) { @@ -599,8 +612,13 @@ Demo_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) { return ENGINE_ENOTSUP; @@ -610,8 +628,13 @@ static ENGINE_ERROR_CODE Demo_btree_elem_get_by_posi(ENGINE_HANDLE* handle, const void* cookie, const char *key, const size_t nkey, ENGINE_BTREE_ORDER order, +#ifdef USE_EBLOCK_RESULT + uint32_t from_posi, uint32_t to_posi, + eblock_result_t *eblk_ret, +#else int from_posi, int to_posi, eitem **eitem_array, uint32_t *eitem_count, +#endif uint32_t *flags, uint16_t vbucket) { return ENGINE_ENOTSUP; diff --git a/include/memcached/engine.h b/include/memcached/engine.h index 9a526e70e..13def15e8 100644 --- a/include/memcached/engine.h +++ b/include/memcached/engine.h @@ -510,7 +510,11 @@ extern "C" { const size_t nbytes, eitem** eitem); void (*btree_elem_release)(ENGINE_HANDLE* handle, const void *cookie, +#ifdef USE_EBLOCK_RESULT + eitem *eitem, EITEM_TYPE type); +#else eitem **eitem_array, const int eitem_count); +#endif ENGINE_ERROR_CODE (*btree_elem_insert)(ENGINE_HANDLE* handle, const void* cookie, const void* key, const int nkey, @@ -551,7 +555,11 @@ extern "C" { 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); @@ -573,15 +581,25 @@ extern "C" { 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); ENGINE_ERROR_CODE (*btree_elem_get_by_posi)(ENGINE_HANDLE *handle, const void* cookie, const char *key, const size_t nkey, ENGINE_BTREE_ORDER order, +#ifdef USE_EBLOCK_RESULT + uint32_t from_posi, uint32_t to_posi, + eblock_result_t *eblk_ret, +#else int from_posi, int to_posi, eitem **eitem_array, uint32_t *eitem_count, +#endif uint32_t *flags, uint16_t vbucket); #ifdef SUPPORT_BOP_SMGET @@ -592,10 +610,16 @@ extern "C" { 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, diff --git a/include/memcached/types.h b/include/memcached/types.h index 81a4fec07..748f14193 100644 --- a/include/memcached/types.h +++ b/include/memcached/types.h @@ -310,6 +310,17 @@ extern "C" { uint32_t flag; /* item flags */ } smget_ehit_t; +#ifdef USE_EBLOCK_RESULT + typedef struct _eblock_result_t { + struct _mem_block_t *head_blk; /* head block pointer */ + struct _mem_block_t *tail_blk; /* tail block pointer */ + struct _mem_block_t *last_blk; /* last block pointer */ + uint32_t elem_cnt; /* element count */ + uint32_t blck_cnt; /* block count */ + uint32_t num_keys; /* for multiget */ + } eblock_result_t; +#endif + /* Key info of the missed/trimmed keys in smget */ typedef struct { uint16_t kidx; /* key index in keys array */ @@ -318,7 +329,11 @@ extern "C" { /* smget result structure */ typedef struct { +#ifdef USE_EBLOCK_RESULT + eblock_result_t *eblk_ret; /* found elements in smget */ +#else eitem **elem_array; /* found elements in smget */ +#endif smget_ehit_t *elem_kinfo; /* key info of found elements */ smget_emis_t *miss_kinfo; /* key info of missed keys */ smget_emis_t *trim_kinfo; /* key info of trimmed keys */ @@ -367,7 +382,19 @@ extern "C" { #ifdef USE_EBLOCK_RESULT #define EITEMS_PER_BLOCK 1023 +#define EBLOCK_HEAD(b) ((b)->head_blk) +#define EBLOCK_ELEM_LAST(b) ((b)->tail_blk->items[(EBLOCK_ELEM_COUNT(b) - 1) % EITEMS_PER_BLOCK]) #define EBLOCK_ELEM_COUNT(b) ((b)->elem_cnt) +#define EBLOCK_NKEY_COUNT(b) ((b)->num_keys) +#define EBLOCK_MGET_INIT(b, k) \ + do { \ + (b)->head_blk = NULL; \ + (b)->tail_blk = NULL; \ + (b)->elem_cnt = 0; \ + (b)->blck_cnt = 0; \ + (b)->num_keys = (k); \ + } while(0) \ + #define EBLOCK_SCAN_INIT(b, s) \ do { \ (s)->blk = (b)->head_blk; \ @@ -375,6 +402,11 @@ extern "C" { (s)->idx = 0; \ } while(0) \ +#define EBLOCK_MSCAN_NEXT(b, s) \ + do { \ + (s)->tot = (b)->elem_cnt; \ + } while(0) \ + #define EBLOCK_SCAN_NEXT(s, e) \ do { \ if ((s)->idx < (s)->tot) { \ @@ -396,14 +428,6 @@ extern "C" { struct _mem_block_t *next; } mem_block_t; - typedef struct _eblock_result_t { - struct _mem_block_t *head_blk; /* head block pointer */ - struct _mem_block_t *tail_blk; /* tail block pointer */ - struct _mem_block_t *last_blk; /* last block pointer */ - uint32_t elem_cnt; /* element count */ - uint32_t blck_cnt; /* block count */ - } eblock_result_t; - typedef struct _eblock_scan_t { mem_block_t *blk; /* current block pointer */ uint32_t tot; /* total element count */ diff --git a/memcached.c b/memcached.c index a90789006..5de71401b 100644 --- a/memcached.c +++ b/memcached.c @@ -810,7 +810,11 @@ static void conn_coll_eitem_free(conn *c) { /* bop */ case OPERATION_BOP_INSERT: case OPERATION_BOP_UPSERT: +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, EITEM_TYPE_SINGLE); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->coll_eitem, 1); +#endif break; case OPERATION_BOP_UPDATE: if (c->coll_eitem != NULL) @@ -819,8 +823,12 @@ static void conn_coll_eitem_free(conn *c) { case OPERATION_BOP_GET: case OPERATION_BOP_PWG: /* position with get */ case OPERATION_BOP_GBP: /* get by position */ +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, c->coll_ecount); free(c->coll_eitem); +#endif if (c->coll_resps != NULL) { free(c->coll_resps); c->coll_resps = NULL; } @@ -832,8 +840,15 @@ static void conn_coll_eitem_free(conn *c) { #ifdef SUPPORT_BOP_SMGET case OPERATION_BOP_SMGET: #endif +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, EITEM_TYPE_BLOCK); + if (c->coll_resps != NULL) { + free(c->coll_resps); c->coll_resps = NULL; + } +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, c->coll_ecount); free(c->coll_eitem); +#endif free(c->coll_strkeys); c->coll_strkeys = NULL; break; #endif @@ -2035,7 +2050,11 @@ static void process_bop_insert_complete(conn *c) { if (strncmp((char*)info.value + info.nbytes - 2, "\r\n", 2) != 0) { // release the btree element +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, EITEM_TYPE_SINGLE); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->coll_eitem, 1); +#endif c->coll_eitem = NULL; out_string(c, "CLIENT_ERROR bad data chunk"); } else { @@ -2055,7 +2074,11 @@ static void process_bop_insert_complete(conn *c) { } // release the btree element inserted. +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, EITEM_TYPE_SINGLE); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->coll_eitem, 1); +#endif c->coll_eitem = NULL; if (settings.detail_enabled) { @@ -2085,15 +2108,23 @@ static void process_bop_insert_complete(conn *c) { (add_iov(c, info.value, info.nbytes) != 0) || (add_iov(c, "TRIMMED\r\n", strlen("TRIMMED\r\n")) != 0)) { +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, + &trim_result.elems, EITEM_TYPE_SINGLE); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, &trim_result.elems, trim_result.count); +#endif if (c->ewouldblock) c->ewouldblock = false; out_string(c, "SERVER_ERROR out of memory writing get response"); } else { /* prepare for writing response */ c->coll_eitem = trim_result.elems; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = trim_result.count; /* trim_result.count == 1 */ +#endif conn_set_state(c, conn_mwrite); } } else { @@ -2200,11 +2231,18 @@ static void process_bop_update_complete(conn *c) #ifdef SUPPORT_BOP_MGET static void process_bop_mget_complete(conn *c) { assert(c->coll_op == OPERATION_BOP_MGET); +#ifdef USE_EBLOCK_RESULT + assert(c->coll_resps != NULL); +#else assert(c->coll_eitem != NULL); +#endif ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; +#ifdef USE_EBLOCK_RESULT +#else eitem **elem_array = (eitem **)c->coll_eitem; uint32_t tot_elem_count = 0; +#endif uint32_t tot_access_count = 0; char delimiter = ','; token_t *key_tokens = (token_t *)((char*)c->coll_strkeys + GET_8ALIGN_SIZE(c->coll_lenkeys)); @@ -2223,7 +2261,14 @@ static void process_bop_mget_complete(conn *c) { bool trimmed; eitem_info info; char *resultptr; +#ifdef USE_EBLOCK_RESULT + char *valuestrp = (char*)c->coll_resps; + eitem *elem; + eblock_scan_t eblk_sc; + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); +#else char *valuestrp = (char*)elem_array + (c->coll_numkeys * c->coll_rcount * sizeof(eitem*)); +#endif int resultlen; int nvaluestr; @@ -2236,6 +2281,9 @@ static void process_bop_mget_complete(conn *c) { c->coll_bkrange.to_nbkey = c->coll_bkrange.from_nbkey; } +#ifdef USE_EBLOCK_RESULT + EBLOCK_MGET_INIT(&c->eblk_ret, c->coll_numkeys); +#endif for (k = 0; k < c->coll_numkeys; k++) { ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, key_tokens[k].value, key_tokens[k].length, @@ -2243,7 +2291,11 @@ static void process_bop_mget_complete(conn *c) { (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), c->coll_roffset, c->coll_rcount, false, false, +#ifdef USE_EBLOCK_RESULT + &c->eblk_ret, +#else &elem_array[tot_elem_count], &cur_elem_count, +#endif &cur_access_count, &flags, &trimmed, 0); if (settings.detail_enabled) { @@ -2253,7 +2305,11 @@ static void process_bop_mget_complete(conn *c) { if (ret == ENGINE_SUCCESS) { sprintf(resultptr, " %s %u %u\r\n", +#ifdef USE_EBLOCK_RESULT + (trimmed==false ? "OK" : "TRIMMED"), htonl(flags), (EBLOCK_ELEM_COUNT(&c->eblk_ret) - cur_elem_count)); +#else (trimmed==false ? "OK" : "TRIMMED"), htonl(flags), cur_elem_count); +#endif if ((add_iov(c, valuestrp, nvaluestr) != 0) || (add_iov(c, key_tokens[k].value, key_tokens[k].length) != 0) || (add_iov(c, resultptr, strlen(resultptr)) != 0)) { @@ -2262,9 +2318,19 @@ static void process_bop_mget_complete(conn *c) { } resultptr += strlen(resultptr); +#ifdef USE_EBLOCK_RESULT + if (k == 0) EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); + else EBLOCK_MSCAN_NEXT(&c->eblk_ret, &eblk_sc); + + for (e = cur_elem_count; e < EBLOCK_ELEM_COUNT(&c->eblk_ret); e++) { + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info); +#else for (e = 0; e < cur_elem_count; e++) { mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[tot_elem_count+e], &info); +#endif sprintf(resultptr, "ELEMENT "); resultlen = strlen(resultptr); resultlen += make_bop_elem_response(resultptr + resultlen, &info); @@ -2277,8 +2343,12 @@ static void process_bop_mget_complete(conn *c) { } if (ret == ENGINE_SUCCESS) { STATS_ELEM_HITS(c, bop_get, key_tokens[k].value, key_tokens[k].length); +#ifdef USE_EBLOCK_RESULT + cur_elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#else tot_elem_count += cur_elem_count; cur_elem_count = 0; +#endif tot_access_count += cur_access_count; cur_access_count = 0; } else { @@ -2303,7 +2373,11 @@ static void process_bop_mget_complete(conn *c) { else sprintf(resultptr, " %s\r\n", "BKEY_MISMATCH"); } else { +#ifdef USE_EBLOCK_RESULT + break; // ENGINE_DISCONNECT or ENGINE_ENOMEM or SEVERE error +#else break; // ENGINE_DISCONNECT or SEVERE error +#endif } if ((add_iov(c, valuestrp, nvaluestr) != 0) || @@ -2323,8 +2397,12 @@ static void process_bop_mget_complete(conn *c) { } } else { // ret != ENGINE_SUCCESS +#ifdef USE_EBLOCK_RESULT + cur_elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#else tot_elem_count += cur_elem_count; cur_elem_count = 0; +#endif tot_access_count += cur_access_count; cur_access_count = 0; } @@ -2334,8 +2412,13 @@ static void process_bop_mget_complete(conn *c) { case ENGINE_SUCCESS: STATS_NOKEY2(c, cmd_bop_mget, bop_mget_oks); /* Remember this command so we can garbage collect it later */ +#ifdef USE_EBLOCK_RESULT + /* c->coll_resps = valuestrp; */ + c->coll_eitem = (void *)&c->eblk_ret; +#else /* c->coll_eitem = (void *)elem_array; */ c->coll_ecount = tot_elem_count; +#endif c->coll_op = OPERATION_BOP_MGET; conn_set_state(c, conn_mwrite); c->msgcurr = 0; @@ -2345,7 +2428,11 @@ static void process_bop_mget_complete(conn *c) { break; case ENGINE_ENOMEM: STATS_NOKEY(c, cmd_bop_mget); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, elem_array, tot_elem_count); +#endif out_string(c, "SERVER_ERROR out of memory writing get response"); break; default: @@ -2360,10 +2447,17 @@ static void process_bop_mget_complete(conn *c) { free((void *)c->coll_strkeys); c->coll_strkeys = NULL; } +#ifdef USE_EBLOCK_RESULT + if (c->coll_resps != NULL) { + free((void *)c->coll_resps); + c->coll_resps = NULL; + } +#else if (c->coll_eitem != NULL) { free((void *)c->coll_eitem); c->coll_eitem = NULL; } +#endif } } #endif @@ -2408,8 +2502,12 @@ static void process_bop_smget_complete_old(conn *c) { uint32_t kmis_count = 0; uint32_t elem_count = 0; +#ifdef USE_EBLOCK_RESULT + uint32_t *kfnd_array = (uint32_t*)c->coll_resps; +#else eitem **elem_array = (eitem **)c->coll_eitem; uint32_t *kfnd_array = (uint32_t*)((char*)elem_array + (smget_count*sizeof(eitem*))); +#endif uint32_t *flag_array = (uint32_t*)((char*)kfnd_array + (smget_count*sizeof(uint32_t))); uint32_t *kmis_array = (uint32_t*)((char*)flag_array + (smget_count*sizeof(uint32_t))); bool trimmed; @@ -2435,14 +2533,25 @@ static void process_bop_smget_complete_old(conn *c) { &c->coll_bkrange, (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), c->coll_roffset, c->coll_rcount, +#ifdef USE_EBLOCK_RESULT + &c->eblk_ret, kfnd_array, flag_array, +#else elem_array, kfnd_array, flag_array, &elem_count, +#endif kmis_array, &kmis_count, &trimmed, &duplicated, 0); } +#ifdef USE_EBLOCK_RESULT + elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#endif switch (ret) { case ENGINE_SUCCESS: { eitem_info info[elem_count+1]; /* elem_count might be 0. */ +#ifdef USE_EBLOCK_RESULT + eitem *elem; + eblock_scan_t eblk_sc; +#endif do { sprintf(respptr, "VALUE %u\r\n", elem_count); @@ -2451,13 +2560,22 @@ static void process_bop_smget_complete_old(conn *c) { } respptr += strlen(respptr); +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); +#endif for (i = 0; i < elem_count; i++) { idx = kfnd_array[i]; if (add_iov(c, keys_array[idx].value, keys_array[idx].length) != 0) { ret = ENGINE_ENOMEM; break; } +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info[i]); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[i], &info[i]); +#endif /* flags */ sprintf(respptr, " %u ", htonl(flag_array[i])); resplen = strlen(respptr); @@ -2504,14 +2622,23 @@ static void process_bop_smget_complete_old(conn *c) { if (ret == ENGINE_SUCCESS) { STATS_NOKEY2(c, cmd_bop_smget, bop_smget_oks); /* Remember this command so we can garbage collect it later */ +#ifdef USE_EBLOCK_RESULT + /* c->coll_resps = (void *)kfnd_array; */ + c->coll_eitem = (void *)&c->eblk_ret; +#else /* c->coll_eitem = (void *)elem_array; */ c->coll_ecount = elem_count; +#endif c->coll_op = OPERATION_BOP_SMGET; conn_set_state(c, conn_mwrite); c->msgcurr = 0; } else { STATS_NOKEY(c, cmd_bop_smget); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, elem_array, elem_count); +#endif out_string(c, "SERVER_ERROR out of memory writing get response"); } } @@ -2519,6 +2646,11 @@ static void process_bop_smget_complete_old(conn *c) { case ENGINE_DISCONNECT: c->state = conn_closing; break; +#ifdef USE_EBLOCK_RESULT + case ENGINE_ENOMEM: + out_string(c, "SERVER_ERROR out of memory getting elements"); + break; +#endif default: STATS_NOKEY(c, cmd_bop_smget); if (ret == ENGINE_EBADVALUE) out_string(c, "CLIENT_ERROR bad data chunk"); @@ -2535,17 +2667,27 @@ static void process_bop_smget_complete_old(conn *c) { free((void *)c->coll_strkeys); c->coll_strkeys = NULL; } +#ifdef USE_EBLOCK_RESULT + if (kfnd_array != NULL) { + free((void *)kfnd_array); + } +#else if (c->coll_eitem != NULL) { free((void *)c->coll_eitem); c->coll_eitem = NULL; } +#endif } } #endif static void process_bop_smget_complete(conn *c) { assert(c->coll_op == OPERATION_BOP_SMGET); +#ifdef USE_EBLOCK_RESULT + assert(c->coll_resps != NULL); +#else assert(c->coll_eitem != NULL); +#endif #ifdef JHPARK_OLD_SMGET_INTERFACE if (c->coll_smgmode == 0) { process_bop_smget_complete_old(c); @@ -2560,8 +2702,14 @@ static void process_bop_smget_complete(conn *c) { int resplen; smget_result_t smres; +#ifdef USE_EBLOCK_RESULT + smres.eblk_ret = &c->eblk_ret; + smres.trim_elems = (eitem **)c->coll_resps; + smres.elem_kinfo = (smget_ehit_t *)&smres.trim_elems[c->coll_numkeys]; +#else smres.elem_array = (eitem **)c->coll_eitem; smres.elem_kinfo = (smget_ehit_t *)&smres.elem_array[c->coll_rcount+c->coll_numkeys]; +#endif smres.miss_kinfo = (smget_emis_t *)&smres.elem_kinfo[c->coll_rcount]; respptr = (char *)&smres.miss_kinfo[c->coll_numkeys]; @@ -2596,6 +2744,10 @@ static void process_bop_smget_complete(conn *c) { case ENGINE_SUCCESS: { eitem_info info[smres.elem_count+1]; /* elem_count might be 0. */ +#ifdef USE_EBLOCK_RESULT + eitem *elem; + eblock_scan_t eblk_sc; +#endif do { /* Change smget response head string: VALUE => ELEMENTS. @@ -2607,9 +2759,18 @@ static void process_bop_smget_complete(conn *c) { } respptr += strlen(respptr); +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(smres.eblk_ret, &eblk_sc); +#endif for (i = 0; i < smres.elem_count; i++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info[i]); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, smres.elem_array[i], &info[i]); +#endif sprintf(respptr, " %u ", htonl(smres.elem_kinfo[i].flag)); resplen = strlen(respptr); resplen += make_bop_elem_response(respptr + resplen, &info[i]); @@ -2675,15 +2836,24 @@ static void process_bop_smget_complete(conn *c) { if (ret == ENGINE_SUCCESS) { STATS_NOKEY2(c, cmd_bop_smget, bop_smget_oks); /* Remember this command so we can garbage collect it later */ +#ifdef USE_EBLOCK_RESULT + /* c->coll_resps = (void *)smres.trim_elems; */ + c->coll_eitem = (void *)smres.eblk_ret; +#else /* c->coll_eitem = (void *)elem_array; */ c->coll_ecount = smres.elem_count+smres.trim_count; +#endif c->coll_op = OPERATION_BOP_SMGET; conn_set_state(c, conn_mwrite); c->msgcurr = 0; } else { STATS_NOKEY(c, cmd_bop_smget); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, smres.eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, smres.elem_array, smres.elem_count+smres.trim_count); +#endif out_string(c, "SERVER_ERROR out of memory writing get response"); } } @@ -2691,6 +2861,11 @@ static void process_bop_smget_complete(conn *c) { case ENGINE_DISCONNECT: c->state = conn_closing; break; +#ifdef USE_EBLOCK_RESULT + case ENGINE_ENOMEM: + out_string(c,"SERVER_ERROR out of memory getting elements"); + break; +#endif default: STATS_NOKEY(c, cmd_bop_smget); if (ret == ENGINE_EBADVALUE) out_string(c, "CLIENT_ERROR bad data chunk"); @@ -2709,10 +2884,17 @@ static void process_bop_smget_complete(conn *c) { free((void *)c->coll_strkeys); c->coll_strkeys = NULL; } +#ifdef USE_EBLOCK_RESULT + if (c->coll_resps != NULL) { + free((void *)c->coll_resps); + c->coll_resps = NULL; + } +#else if (c->coll_eitem != NULL) { free((void *)c->coll_eitem); c->coll_eitem = NULL; } +#endif } } #endif @@ -4092,7 +4274,10 @@ static void process_bin_lop_prepare_nread(conn *c) { c->ritem = (char *)info.value; c->rlbytes = vlen; c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = OPERATION_LOP_INSERT; c->coll_key = key; c->coll_nkey = nkey; @@ -4594,7 +4779,10 @@ static void process_bin_sop_prepare_nread(conn *c) { c->rlbytes = vlen; } c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_key = key; c->coll_nkey = nkey; if (c->cmd == PROTOCOL_BINARY_CMD_SOP_INSERT) { @@ -5166,7 +5354,10 @@ static void process_bin_bop_prepare_nread(conn *c) { c->ritem = (char *)info.value; c->rlbytes = vlen; c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = (c->cmd == PROTOCOL_BINARY_CMD_BOP_INSERT ? OPERATION_BOP_INSERT : OPERATION_BOP_UPSERT); c->coll_key = key; @@ -5266,7 +5457,11 @@ static void process_bin_bop_insert_complete(conn *c) { } /* release the c->coll_eitem reference */ +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, c->coll_eitem, EITEM_TYPE_SINGLE); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->coll_eitem, 1); +#endif c->coll_eitem = NULL; } @@ -5399,7 +5594,10 @@ static void process_bin_bop_update_prepare_nread(conn *c) { if (req->message.body.novalue) { c->coll_eitem = NULL; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 0; +#endif c->coll_key = key; c->coll_nkey = nkey; c->coll_op = OPERATION_BOP_UPDATE; @@ -5428,7 +5626,10 @@ static void process_bin_bop_update_prepare_nread(conn *c) { c->ritem = ((elem_value *)elem)->value; c->rlbytes = vlen; c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_key = key; c->coll_nkey = nkey; c->coll_op = OPERATION_BOP_UPDATE; @@ -5566,13 +5767,19 @@ static void process_bin_bop_get(conn *c) { (req->message.body.delete ? "true" : "false")); } +#ifdef USE_EBLOCK_RESULT +#else eitem **elem_array = NULL; +#endif uint32_t elem_count; uint32_t access_count; uint32_t flags, i; bool dropped_trimmed; int est_count; +#ifdef USE_EBLOCK_RESULT +#else int need_size; +#endif ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; @@ -5581,6 +5788,19 @@ static void process_bin_bop_get(conn *c) { est_count = req->message.body.count; if (est_count % 2) est_count += 1; } +#ifdef USE_EBLOCK_RESULT + EBLOCK_MGET_INIT(&c->eblk_ret, 1); + ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, key, nkey, + bkrange, efilter, + req->message.body.offset, + req->message.body.count, + (bool)req->message.body.delete, + (bool)req->message.body.drop, + &c->eblk_ret, &access_count, + &flags, &dropped_trimmed, + c->binary_header.request.vbucket); + elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#else need_size = est_count * (sizeof(eitem*)+MAX_BKEY_LENG+MAX_EFLAG_LENG+sizeof(uint32_t)); if ((elem_array = (eitem **)malloc(need_size)) == NULL) { write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0); @@ -5596,6 +5816,7 @@ static void process_bin_bop_get(conn *c) { elem_array, &elem_count, &access_count, &flags, &dropped_trimmed, c->binary_header.request.vbucket); +#endif if (ret == ENGINE_EWOULDBLOCK) { c->ewouldblock = true; ret = ENGINE_SUCCESS; @@ -5610,16 +5831,39 @@ static void process_bin_bop_get(conn *c) { case ENGINE_SUCCESS: { protocol_binary_response_bop_get* rsp = (protocol_binary_response_bop_get*)c->wbuf; +#ifdef USE_EBLOCK_RESULT + eitem *elem; + eblock_scan_t eblk_sc; + uint64_t *bkeyptr; + uint32_t *vlenptr; +#else uint64_t *bkeyptr = ((elem_count % 2) == 0 /* for 8 byte align */ ? (uint64_t *)&elem_array[elem_count] : (uint64_t *)&elem_array[elem_count+1]); uint32_t *vlenptr = (uint32_t *)((char*)bkeyptr + (sizeof(uint64_t) * elem_count)); +#endif uint32_t bodylen; +#ifdef USE_EBLOCK_RESULT + int need_size = est_count * (MAX_BKEY_LENG+MAX_EFLAG_LENG+sizeof(uint32_t)); + if ((bkeyptr = (uint64_t *)malloc(need_size)) == NULL) { + ret = ENGINE_ENOMEM; + } else { + vlenptr = (uint32_t *)((char*)bkeyptr + (sizeof(uint64_t) * elem_count)); +#endif eitem_info info[elem_count]; +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); +#endif for (i = 0; i < elem_count; i++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info[i]); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[i], &info[i]); +#endif } bodylen = sizeof(rsp->message.body) + (elem_count * (sizeof(uint64_t)+sizeof(uint32_t))); @@ -5647,17 +5891,30 @@ static void process_bin_bop_get(conn *c) { break; } } +#ifdef USE_EBLOCK_RESULT + } +#endif if (ret == ENGINE_SUCCESS) { STATS_ELEM_HITS(c, bop_get, key, nkey); /* Remember this command so we can garbage collect it later */ +#ifdef USE_EBLOCK_RESULT + c->coll_eitem = (void *)&c->eblk_ret; + c->coll_resps = (void *)bkeyptr; +#else c->coll_eitem = (void *)elem_array; c->coll_ecount = elem_count; +#endif c->coll_op = OPERATION_BOP_GET; conn_set_state(c, conn_mwrite); } else { STATS_NOKEY(c, cmd_bop_get); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->eblk_ret, EITEM_TYPE_BLOCK); + free((void *)bkeyptr); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, elem_array, elem_count); +#endif if (c->ewouldblock) c->ewouldblock = false; write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0); @@ -5682,6 +5939,11 @@ static void process_bin_bop_get(conn *c) { else write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_UNREADABLE, 0); break; +#ifdef USE_EBLOCK_RESULT + case ENGINE_ENOMEM: + write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0); + break; +#endif default: STATS_NOKEY(c, cmd_bop_get); if (ret == ENGINE_EBADTYPE) @@ -5692,9 +5954,12 @@ static void process_bin_bop_get(conn *c) { write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_EINTERNAL, 0); } +#ifdef USE_EBLOCK_RESULT +#else if (ret != ENGINE_SUCCESS && elem_array != NULL) { free((void *)elem_array); } +#endif } static void process_bin_bop_count(conn *c) { @@ -5844,6 +6109,52 @@ static void process_bin_bop_prepare_nread_keys(conn *c) { need_size = elem_array_size; } #endif +#ifdef USE_EBLOCK_RESULT +#ifdef SUPPORT_BOP_SMGET + if (c->cmd == PROTOCOL_BINARY_CMD_BOP_SMGET) { +#ifdef JHPARK_OLD_SMGET_INTERFACE + if (c->coll_smgmode == 0) { + int smget_count; + int kfnd_array_size; + int kmis_array_size; /* key index array where the missed key indexes are to be saved */ + int elem_rshdr_size; /* the size of result header about the found elems */ + int kmis_rshdr_size; /* the size of result header about the missed keys */ + + if (req->message.body.key_count > MAX_SMGET_KEY_COUNT || + (req->message.body.req_offset + req->message.body.req_count) > MAX_SMGET_REQ_COUNT) { + ret = ENGINE_EBADVALUE; break; + } + smget_count = req->message.body.req_offset + req->message.body.req_count; + kfnd_array_size = smget_count * (2*sizeof(uint32_t)); + kmis_array_size = req->message.body.key_count * sizeof(uint32_t); + elem_rshdr_size = smget_count * (sizeof(uint64_t) + (3*sizeof(uint32_t))); + kmis_rshdr_size = req->message.body.key_count * sizeof(uint32_t); + need_size = kfnd_array_size + kmis_array_size + elem_rshdr_size + kmis_rshdr_size; + } else { +#endif + int trim_array_size; /* smget trim element array size */ + int ehit_array_size; /* smget hitted elem array size */ + int emis_array_size; /* element missed keys array size */ + int elem_rshdr_size; /* the size of result header about the found elems */ + int emis_rshdr_size; /* the size of result header about the missed keys */ + + if (req->message.body.key_count > MAX_SMGET_KEY_COUNT || + (req->message.body.req_offset + req->message.body.req_count) > MAX_SMGET_REQ_COUNT) { + ret = ENGINE_EBADVALUE; break; + } + trim_array_size = req->message.body.key_count * sizeof(eitem*); + ehit_array_size = req->message.body.req_count * sizeof(smget_ehit_t); + emis_array_size = req->message.body.key_count * sizeof(smget_emis_t); + elem_rshdr_size = req->message.body.req_count * (sizeof(uint64_t) + (3*sizeof(uint32_t))); + emis_rshdr_size = req->message.body.key_count * sizeof(uint32_t); + need_size = trim_array_size + ehit_array_size + emis_array_size + + elem_rshdr_size + emis_rshdr_size; +#ifdef JHPARK_OLD_SMGET_INTERFACE + } +#endif + } +#endif +#else /* USE_EBLOCK_RESULT */ #ifdef SUPPORT_BOP_SMGET if (c->cmd == PROTOCOL_BINARY_CMD_BOP_SMGET) { #ifdef JHPARK_OLD_SMGET_INTERFACE @@ -5888,6 +6199,7 @@ static void process_bin_bop_prepare_nread_keys(conn *c) { #endif } #endif +#endif /* USE_EBLOCK_RESULT */ assert(need_size > 0); if ((elem = (eitem *)malloc(need_size)) == NULL) { @@ -5913,8 +6225,12 @@ static void process_bin_bop_prepare_nread_keys(conn *c) { case ENGINE_SUCCESS: c->ritem = (char *)c->coll_strkeys; c->rlbytes = vlen; +#ifdef USE_EBLOCK_RESULT + c->coll_resps = (void *)elem; +#else c->coll_eitem = (void *)elem; c->coll_ecount = 0; +#endif c->coll_op = (c->cmd==PROTOCOL_BINARY_CMD_BOP_MGET ? OPERATION_BOP_MGET : OPERATION_BOP_SMGET); conn_set_state(c, conn_nread); c->substate = bin_reading_bop_nread_keys_complete; @@ -5935,7 +6251,11 @@ static void process_bin_bop_prepare_nread_keys(conn *c) { #ifdef SUPPORT_BOP_MGET static void process_bin_bop_mget_complete(conn *c) { assert(c->coll_op == OPERATION_BOP_MGET); +#ifdef USE_EBLOCK_RESULT + assert(c->coll_resps != NULL); +#else assert(c->coll_eitem != NULL); +#endif ENGINE_ERROR_CODE ret = ENGINE_ENOTSUP; write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED, 0); @@ -5945,10 +6265,17 @@ static void process_bin_bop_mget_complete(conn *c) { free((void *)c->coll_strkeys); c->coll_strkeys = NULL; } +#ifdef USE_EBLOCK_RESULT + if (c->coll_resps != NULL) { + free((void *)c->coll_resps); + c->coll_resps = NULL; + } +#else if (c->coll_eitem != NULL) { free((void *)c->coll_eitem); c->coll_eitem = NULL; } +#endif } } #endif @@ -5969,8 +6296,12 @@ static void process_bin_bop_smget_complete_old(conn *c) { uint32_t kmis_count = 0; uint32_t elem_count = 0; +#ifdef USE_EBLOCK_RESULT + uint32_t *kfnd_array = (uint32_t*)c->coll_resps; +#else eitem **elem_array = (eitem **)c->coll_eitem; uint32_t *kfnd_array = (uint32_t*)((char*)elem_array + (smget_count*sizeof(eitem*))); +#endif uint32_t *flag_array = (uint32_t*)((char*)kfnd_array + (smget_count*sizeof(uint32_t))); uint32_t *kmis_array = (uint32_t*)((char*)flag_array + (smget_count*sizeof(uint32_t))); @@ -5997,10 +6328,17 @@ static void process_bin_bop_smget_complete_old(conn *c) { &c->coll_bkrange, (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), c->coll_roffset, c->coll_rcount, +#ifdef USE_EBLOCK_RESULT + &c->eblk_ret, kfnd_array, flag_array, +#else elem_array, kfnd_array, flag_array, &elem_count, +#endif kmis_array, &kmis_count, &trimmed, &duplicated, c->binary_header.request.vbucket); } +#ifdef USE_EBLOCK_RESULT + elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#endif switch (ret) { case ENGINE_SUCCESS: @@ -6013,6 +6351,10 @@ static void process_bin_bop_smget_complete_old(conn *c) { uint32_t *vlenptr; uint32_t *flagptr; uint32_t *klenptr; +#ifdef USE_EBLOCK_RESULT + eitem *elem; + eblock_scan_t eblk_sc; +#endif if (((long)resultptr % 8) != 0) /* NOT aligned */ resultptr += (8 - ((long)resultptr % 8)); @@ -6022,9 +6364,18 @@ static void process_bin_bop_smget_complete_old(conn *c) { klenptr = (uint32_t *)((char*)flagptr + (sizeof(uint32_t) * elem_count)); eitem_info info[elem_count+1]; /* elem_count might be 0. */ +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); +#endif for (i = 0; i < elem_count; i++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info[i]); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[i], &info[i]); +#endif } bodylen = sizeof(rsp->message.body); @@ -6085,15 +6436,26 @@ static void process_bin_bop_smget_complete_old(conn *c) { } if (ret == ENGINE_SUCCESS) { +#ifdef USE_EBLOCK_RESULT + STATS_NOKEY2(c, cmd_bop_smget, bop_smget_oks); + /* Remember this command so we can garbage collect it later */ + /* c->coll_resps = (void *)kfnd_array; */ + c->coll_eitem = (void *)&c->eblk_ret; +#else /* Remember this command so we can garbage collect it later */ /* c->coll_eitem = (void *)elem_array; */ STATS_NOKEY2(c, cmd_bop_smget, bop_smget_oks); c->coll_ecount = elem_count; +#endif c->coll_op = OPERATION_BOP_SMGET; conn_set_state(c, conn_mwrite); } else { STATS_NOKEY(c, cmd_bop_smget); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, elem_array, elem_count); +#endif write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0); } } @@ -6131,7 +6493,11 @@ static void process_bin_bop_smget_complete_old(conn *c) { #endif static void process_bin_bop_smget_complete(conn *c) { +#ifdef USE_EBLOCK_RESULT + assert(c->coll_resps != NULL); +#else assert(c->coll_eitem != NULL); +#endif #ifdef JHPARK_OLD_SMGET_INTERFACE if (c->coll_smgmode == 0) { process_bin_bop_smget_complete_old(c); @@ -6148,8 +6514,14 @@ static void process_bin_bop_smget_complete(conn *c) { * protocol, so we're going to just set them here */ memcpy(vptr + c->coll_lenkeys - 2, "\r\n", 2); +#ifdef USE_EBLOCK_RESULT + smres.eblk_ret = &c->eblk_ret; + smres.trim_elems = (void *)c->coll_resps; + smres.elem_kinfo = (smget_ehit_t *)&smres.trim_elems[c->coll_numkeys]; +#else smres.elem_array = (eitem **)c->coll_eitem; smres.elem_kinfo = (smget_ehit_t *)&smres.elem_array[c->coll_rcount+c->coll_numkeys]; +#endif smres.miss_kinfo = (smget_emis_t *)&smres.elem_kinfo[c->coll_rcount]; resultptr = (char *)&smres.miss_kinfo[c->coll_numkeys]; @@ -6191,6 +6563,10 @@ static void process_bin_bop_smget_complete(conn *c) { uint32_t *vlenptr; uint32_t *flagptr; uint32_t *klenptr; +#ifdef USE_EBLOCK_RESULT + eitem *elem; + eblock_scan_t eblk_sc; +#endif if (((long)resultptr % 8) != 0) /* NOT aligned */ resultptr += (8 - ((long)resultptr % 8)); @@ -6200,9 +6576,18 @@ static void process_bin_bop_smget_complete(conn *c) { klenptr = (uint32_t *)((char*)flagptr + (sizeof(uint32_t) * smres.elem_count)); eitem_info info[smres.elem_count+1]; /* elem_count might be 0. */ +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(smres.eblk_ret, &eblk_sc); +#endif for (i = 0; i < smres.elem_count; i++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info[i]); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, smres.elem_array[i], &info[i]); +#endif } bodylen = sizeof(rsp->message.body); @@ -6279,16 +6664,27 @@ static void process_bin_bop_smget_complete(conn *c) { } if (ret == ENGINE_SUCCESS) { +#ifdef USE_EBLOCK_RESULT + STATS_NOKEY2(c, cmd_bop_smget, bop_smget_oks); + /* Remember this command so we can garbage collect it later */ + /* c->coll_resps = (void *)smres.trim_count */ + c->coll_eitem = (void *)smres.eblk_ret; +#else /* Remember this command so we can garbage collect it later */ /* c->coll_eitem = (void *)elem_array; */ STATS_NOKEY2(c, cmd_bop_smget, bop_smget_oks); c->coll_ecount = smres.elem_count+smres.trim_count; +#endif c->coll_op = OPERATION_BOP_SMGET; conn_set_state(c, conn_mwrite); } else { STATS_NOKEY(c, cmd_bop_smget); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, smres.eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, smres.elem_array, smres.elem_count+smres.trim_count); +#endif write_bin_packet(c, PROTOCOL_BINARY_RESPONSE_ENOMEM, 0); } } @@ -6319,10 +6715,17 @@ static void process_bin_bop_smget_complete(conn *c) { free((void *)c->coll_strkeys); c->coll_strkeys = NULL; } +#ifdef USE_EBLOCK_RESULT + if (c->coll_resps != NULL) { + free((void *)c->coll_resps); + c->coll_resps = NULL; + } +#else if (c->coll_eitem != NULL) { free((void *)c->coll_eitem); c->coll_eitem = NULL; } +#endif } } #endif @@ -9844,6 +10247,7 @@ static void process_lop_get(conn *c, char *key, size_t nkey, #else if (ret != ENGINE_SUCCESS && elem_array != NULL) { free((void *)elem_array); + } #endif } @@ -9871,7 +10275,10 @@ static void process_lop_prepare_nread(conn *c, int cmd, size_t vlen, c->ritem = (char *)info.value; c->rlbytes = vlen; c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = OPERATION_LOP_INSERT; c->coll_key = key; c->coll_nkey = nkey; @@ -10376,7 +10783,10 @@ static void process_sop_prepare_nread(conn *c, int cmd, size_t vlen, char *key, c->rlbytes = vlen; } c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = cmd; c->coll_key = key; c->coll_nkey = nkey; @@ -10600,18 +11010,33 @@ static void process_bop_get(conn *c, char *key, size_t nkey, const uint32_t offset, const uint32_t count, const bool delete, const bool drop_if_empty) { +#ifdef USE_EBLOCK_RESULT +#else eitem **elem_array = NULL; +#endif uint32_t elem_count; uint32_t access_count; uint32_t flags, i; bool dropped_trimmed; +#ifdef USE_EBLOCK_RESULT +#else int est_count; int need_size; +#endif assert(c->ewouldblock == false); ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; +#ifdef USE_EBLOCK_RESULT + EBLOCK_MGET_INIT(&c->eblk_ret, 1); + ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, key, nkey, + bkrange, efilter, offset, count, + delete, drop_if_empty, + &c->eblk_ret, &access_count, + &flags, &dropped_trimmed, 0); + elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#else est_count = MAX_BTREE_SIZE; if (count > 0 && count < MAX_BTREE_SIZE) { est_count = count; @@ -10627,6 +11052,7 @@ static void process_bop_get(conn *c, char *key, size_t nkey, delete, drop_if_empty, elem_array, &elem_count, &access_count, &flags, &dropped_trimmed, 0); +#endif if (ret == ENGINE_EWOULDBLOCK) { c->ewouldblock = true; ret = ENGINE_SUCCESS; @@ -10670,6 +11096,11 @@ static void process_bop_get(conn *c, char *key, size_t nkey, char *respbuf; /* response string buffer */ char *respptr; int resplen; +#ifdef USE_EBLOCK_RESULT + int need_size; + eitem *elem; + eblock_scan_t eblk_sc; +#endif do { need_size = ((2*lenstr_size) + 30) /* response head and tail size */ @@ -10685,9 +11116,18 @@ static void process_bop_get(conn *c, char *key, size_t nkey, } respptr += strlen(respptr); +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); +#endif for (i = 0; i < elem_count; i++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[i], &info); +#endif resplen = make_bop_elem_response(respptr, &info); if ((add_iov(c, respptr, resplen) != 0) || (add_iov(c, info.value, info.nbytes) != 0)) { @@ -10710,15 +11150,23 @@ static void process_bop_get(conn *c, char *key, size_t nkey, if (ret == ENGINE_SUCCESS) { STATS_ELEM_HITS(c, bop_get, key, nkey); +#ifdef USE_EBLOCK_RESULT + c->coll_eitem = (void *)&c->eblk_ret; +#else c->coll_eitem = (void *)elem_array; c->coll_ecount = elem_count; +#endif c->coll_resps = respbuf; c->coll_op = OPERATION_BOP_GET; conn_set_state(c, conn_mwrite); c->msgcurr = 0; } else { /* ENGINE_ENOMEM */ STATS_NOKEY(c, cmd_bop_get); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, elem_array, elem_count); +#endif free(respbuf); if (c->ewouldblock) c->ewouldblock = false; @@ -10741,6 +11189,11 @@ static void process_bop_get(conn *c, char *key, size_t nkey, else if (ret == ENGINE_EBKEYOOR) out_string(c, "OUT_OF_RANGE"); else out_string(c, "UNREADABLE"); break; +#ifdef USE_EBLOCK_RESULT + case ENGINE_ENOMEM: + out_string(c, "SERVER_ERROR out of memory getting elements"); + break; +#endif default: STATS_NOKEY(c, cmd_bop_get); if (ret == ENGINE_EBADTYPE) out_string(c, "TYPE_MISMATCH"); @@ -10749,9 +11202,12 @@ static void process_bop_get(conn *c, char *key, size_t nkey, else handle_unexpected_errorcode_ascii(c, ret); } +#ifdef USE_EBLOCK_RESULT +#else if (ret != ENGINE_SUCCESS && elem_array != NULL) { free((void *)elem_array); } +#endif } static void process_bop_count(conn *c, char *key, size_t nkey, @@ -10864,15 +11320,28 @@ static void process_bop_position(conn *c, char *key, size_t nkey, static void process_bop_pwg(conn *c, char *key, size_t nkey, const bkey_range *bkrange, ENGINE_BTREE_ORDER order, const uint32_t count) { +#ifdef USE_EBLOCK_RESULT +#else eitem **elem_array = NULL; +#endif uint32_t elem_count; uint32_t elem_index; uint32_t flags, i; int position; +#ifdef USE_EBLOCK_RESULT +#else int need_size; +#endif ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; +#ifdef USE_EBLOCK_RESULT + ret = mc_engine.v1->btree_posi_find_with_get(mc_engine.v0, c, key, nkey, + bkrange, order, count, &position, + &c->eblk_ret, &elem_index, + &flags, 0); + elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#else need_size = ((count*2) + 1) * sizeof(eitem*); if ((elem_array = (eitem **)malloc(need_size)) == NULL) { out_string(c, "SERVER_ERROR out of memory"); @@ -10883,6 +11352,7 @@ static void process_bop_pwg(conn *c, char *key, size_t nkey, const bkey_range *b bkrange, order, count, &position, elem_array, &elem_count, &elem_index, &flags, 0); +#endif if (settings.detail_enabled) { stats_prefix_record_bop_pwg(key, nkey, (ret==ENGINE_SUCCESS || ret==ENGINE_ELEM_ENOENT)); @@ -10895,6 +11365,11 @@ static void process_bop_pwg(conn *c, char *key, size_t nkey, const bkey_range *b char *respbuf; /* response string buffer */ char *respptr; int resplen; +#ifdef USE_EBLOCK_RESULT + int need_size; + eitem *elem; + eblock_scan_t eblk_sc; +#endif do { need_size = ((4*lenstr_size) + 30) /* response head and tail size */ @@ -10910,9 +11385,18 @@ static void process_bop_pwg(conn *c, char *key, size_t nkey, const bkey_range *b } respptr += strlen(respptr); +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); +#endif for (i = 0; i < elem_count; i++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[i], &info); +#endif resplen = make_bop_elem_response(respptr, &info); if ((add_iov(c, respptr, resplen) != 0) || (add_iov(c, info.value, info.nbytes) != 0)) { @@ -10931,15 +11415,23 @@ static void process_bop_pwg(conn *c, char *key, size_t nkey, const bkey_range *b if (ret == ENGINE_SUCCESS) { STATS_ELEM_HITS(c, bop_pwg, key, nkey); +#ifdef USE_EBLOCK_RESULT + c->coll_eitem = (void *)&c->eblk_ret; +#else c->coll_eitem = (void *)elem_array; c->coll_ecount = elem_count; +#endif c->coll_resps = respbuf; c->coll_op = OPERATION_BOP_PWG; conn_set_state(c, conn_mwrite); c->msgcurr = 0; } else { /* ENGINE_ENOMEM */ STATS_NOKEY(c, cmd_bop_pwg); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, elem_array, elem_count); +#endif free(respbuf); out_string(c, "SERVER_ERROR out of memory writing get response"); } @@ -10958,6 +11450,11 @@ static void process_bop_pwg(conn *c, char *key, size_t nkey, const bkey_range *b if (ret == ENGINE_KEY_ENOENT) out_string(c, "NOT_FOUND"); else out_string(c, "UNREADABLE"); break; +#ifdef USE_EBLOCK_RESULT + case ENGINE_ENOMEM: + out_string(c, "SERVER_ERROR out of memory getting elements"); + break; +#endif default: STATS_NOKEY(c, cmd_bop_pwg); if (ret == ENGINE_EBADTYPE) out_string(c, "TYPE_MISMATCH"); @@ -10966,25 +11463,40 @@ static void process_bop_pwg(conn *c, char *key, size_t nkey, const bkey_range *b else handle_unexpected_errorcode_ascii(c, ret); } +#ifdef USE_EBLOCK_RESULT +#else if (ret != ENGINE_SUCCESS && elem_array != NULL) { free((void *)elem_array); } +#endif } static void process_bop_gbp(conn *c, char *key, size_t nkey, ENGINE_BTREE_ORDER order, uint32_t from_posi, uint32_t to_posi) { +#ifdef USE_EBLOCK_RESULT +#else eitem **elem_array = NULL; +#endif uint32_t elem_count; uint32_t flags, i; +#ifdef USE_EBLOCK_RESULT +#else int est_count; int need_size; +#endif ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; if (from_posi > MAX_BTREE_SIZE) from_posi = MAX_BTREE_SIZE; if (to_posi > MAX_BTREE_SIZE) to_posi = MAX_BTREE_SIZE; +#ifdef USE_EBLOCK_RESULT + ret = mc_engine.v1->btree_elem_get_by_posi(mc_engine.v0, c, key, nkey, + order, from_posi, to_posi, + &c->eblk_ret, &flags, 0); + elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); +#else est_count = (from_posi <= to_posi ? (to_posi - from_posi + 1) : (from_posi - to_posi + 1)); need_size = est_count * sizeof(eitem*); @@ -10996,6 +11508,7 @@ static void process_bop_gbp(conn *c, char *key, size_t nkey, ENGINE_BTREE_ORDER ret = mc_engine.v1->btree_elem_get_by_posi(mc_engine.v0, c, key, nkey, order, from_posi, to_posi, elem_array, &elem_count, &flags, 0); +#endif if (settings.detail_enabled) { stats_prefix_record_bop_gbp(key, nkey, (ret==ENGINE_SUCCESS || ret==ENGINE_ELEM_ENOENT)); @@ -11026,6 +11539,11 @@ static void process_bop_gbp(conn *c, char *key, size_t nkey, ENGINE_BTREE_ORDER char *respbuf; /* response string buffer */ char *respptr; int resplen; +#ifdef USE_EBLOCK_RESULT + int need_size; + eitem *elem; + eblock_scan_t eblk_sc; +#endif do { need_size = ((2*lenstr_size) + 30) /* response head and tail size */ @@ -11041,9 +11559,18 @@ static void process_bop_gbp(conn *c, char *key, size_t nkey, ENGINE_BTREE_ORDER } respptr += strlen(respptr); +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); +#endif for (i = 0; i < elem_count; i++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[i], &info); +#endif resplen = make_bop_elem_response(respptr, &info); if ((add_iov(c, respptr, resplen) != 0) || (add_iov(c, info.value, info.nbytes) != 0)) { @@ -11062,15 +11589,23 @@ static void process_bop_gbp(conn *c, char *key, size_t nkey, ENGINE_BTREE_ORDER if (ret == ENGINE_SUCCESS) { STATS_ELEM_HITS(c, bop_gbp, key, nkey); +#ifdef USE_EBLOCK_RESULT + c->coll_eitem = (void *)&c->eblk_ret; +#else c->coll_eitem = (void *)elem_array; c->coll_ecount = elem_count; +#endif c->coll_resps = respbuf; c->coll_op = OPERATION_BOP_GBP; conn_set_state(c, conn_mwrite); c->msgcurr = 0; } else { /* ENGINE_ENOMEM */ STATS_NOKEY(c, cmd_bop_gbp); +#ifdef USE_EBLOCK_RESULT + mc_engine.v1->btree_elem_release(mc_engine.v0, c, &c->eblk_ret, EITEM_TYPE_BLOCK); +#else mc_engine.v1->btree_elem_release(mc_engine.v0, c, elem_array, elem_count); +#endif free(respbuf); out_string(c, "SERVER_ERROR out of memory writing get response"); } @@ -11089,6 +11624,11 @@ static void process_bop_gbp(conn *c, char *key, size_t nkey, ENGINE_BTREE_ORDER if (ret == ENGINE_KEY_ENOENT) out_string(c, "NOT_FOUND"); else out_string(c, "UNREADABLE"); break; +#ifdef USE_EBLOCK_RESULT + case ENGINE_ENOMEM: + out_string(c, "SERVER_ERROR out of memory getting elements"); + break; +#endif default: STATS_NOKEY(c, cmd_bop_gbp); if (ret == ENGINE_EBADTYPE) out_string(c, "TYPE_MISMATCH"); @@ -11096,9 +11636,12 @@ static void process_bop_gbp(conn *c, char *key, size_t nkey, ENGINE_BTREE_ORDER else handle_unexpected_errorcode_ascii(c, ret); } +#ifdef USE_EBLOCK_RESULT +#else if (ret != ENGINE_SUCCESS && elem_array != NULL) { free((void *)elem_array); } +#endif } static void process_bop_update_prepare_nread(conn *c, int cmd, char *key, size_t nkey, const int vlen) @@ -11125,7 +11668,10 @@ static void process_bop_update_prepare_nread(conn *c, int cmd, char *key, size_t c->ritem = ((elem_value *)elem)->value; c->rlbytes = vlen; c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = cmd; c->coll_key = key; c->coll_nkey = nkey; @@ -11173,7 +11719,10 @@ static void process_bop_prepare_nread(conn *c, int cmd, char *key, size_t nkey, c->ritem = (char *)info.value; c->rlbytes = vlen; c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = cmd; /* OPERATION_BOP_INSERT | OPERATION_BOP_UPSERT */ c->coll_key = key; c->coll_nkey = nkey; @@ -11203,6 +11752,55 @@ static void process_bop_prepare_nread_keys(conn *c, int cmd, uint32_t vlen, uint ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; int need_size = 0; +#ifdef USE_EBLOCK_RESULT +#ifdef SUPPORT_BOP_MGET + if (cmd == OPERATION_BOP_MGET) { + int bmget_count = c->coll_numkeys * c->coll_rcount; + int respon_hdr_size = c->coll_numkeys * ((lenstr_size*2)+30); + int respon_bdy_size = bmget_count * ((MAX_BKEY_LENG*2+2)+(MAX_EFLAG_LENG*2+2)+lenstr_size+15); + + need_size = respon_hdr_size + respon_bdy_size; + } +#endif +#ifdef SUPPORT_BOP_SMGET + if (cmd == OPERATION_BOP_SMGET) { +#ifdef JHPARK_OLD_SMGET_INTERFACE + if (c->coll_smgmode == 0) { + int smget_count = c->coll_roffset + c->coll_rcount; + int kfnd_array_size; + int kmis_array_size; /* key index array where the missed key indexes are to be saved */ + int respon_hdr_size; /* the size of response head and tail */ + int respon_bdy_size; /* the size of response body */ + + kfnd_array_size = smget_count * (2*sizeof(uint32_t)); + kmis_array_size = c->coll_numkeys * sizeof(uint32_t); + respon_hdr_size = (2*lenstr_size) + 30; /* result head and tail size */ + respon_bdy_size = smget_count * ((MAX_BKEY_LENG*2+2)+(MAX_EFLAG_LENG*2+2)+(lenstr_size*2)+5); /* result body size */ + + need_size = kfnd_array_size + kmis_array_size + respon_hdr_size + respon_bdy_size; + } else { +#endif + int trim_array_size; /* smget trim element array size */ + int ehit_array_size; /* smget hitted elem array size */ + int emis_array_size; /* element missed keys array size */ + int respon_hdr_size; /* the size of response head and tail */ + int respon_bdy_size; /* the size of response body */ + + trim_array_size = c->coll_numkeys * sizeof(eitem*); + ehit_array_size = c->coll_rcount * sizeof(smget_ehit_t); + emis_array_size = c->coll_numkeys * sizeof(smget_emis_t); + respon_hdr_size = (3*lenstr_size) + 50; /* result head and tail size */ + respon_bdy_size = (c->coll_rcount * ((MAX_BKEY_LENG*2+2)+(MAX_EFLAG_LENG*2+2)+(lenstr_size*2)+10)) + + (c->coll_numkeys * ((MAX_EFLAG_LENG*2+2) + 5)); /* result body size */ + need_size = trim_array_size + ehit_array_size + emis_array_size + + respon_hdr_size + respon_bdy_size; +#ifdef JHPARK_OLD_SMGET_INTERFACE + } +#endif + } +#endif + +#else /* USE_EBLOCK_RESULT */ #ifdef SUPPORT_BOP_MGET if (cmd == OPERATION_BOP_MGET) { int bmget_count = c->coll_numkeys * c->coll_rcount; @@ -11250,6 +11848,7 @@ static void process_bop_prepare_nread_keys(conn *c, int cmd, uint32_t vlen, uint #endif } #endif +#endif /* USE_EBLOCK_RESULT */ assert(need_size > 0); if ((elem = (eitem *)malloc(need_size)) == NULL) { @@ -11268,8 +11867,12 @@ static void process_bop_prepare_nread_keys(conn *c, int cmd, uint32_t vlen, uint { c->ritem = (char *)c->coll_strkeys; c->rlbytes = vlen; +#ifdef USE_EBLOCK_RESULT + c->coll_resps = (void *)elem; +#else c->coll_eitem = (void *)elem; c->coll_ecount = 0; +#endif c->coll_op = cmd; conn_set_state(c, conn_nread); } @@ -11683,7 +12286,10 @@ static void process_mop_prepare_nread(conn *c, int cmd, char *key, size_t nkey, } c->rlbytes = vlen; c->coll_eitem = (void *)elem; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = cmd; c->coll_key = key; c->coll_nkey = nkey; @@ -11727,7 +12333,10 @@ static void process_mop_prepare_nread_fields(conn *c, int cmd, char *key, size_t { c->ritem = (char *)c->coll_strkeys; c->rlbytes = flen; +#ifdef USE_EBLOCK_RESULT +#else c->coll_ecount = 1; +#endif c->coll_op = cmd; c->coll_key = key; c->coll_nkey = nkey; diff --git a/memcached.h b/memcached.h index 76bd08b3f..95bd3c4ef 100644 --- a/memcached.h +++ b/memcached.h @@ -495,7 +495,10 @@ struct conn { /* collection processing fields */ void *coll_eitem; char *coll_resps; +#ifdef USE_EBLOCK_RESULT +#else int coll_ecount; +#endif ENGINE_COLL_OPERATION coll_op; char *coll_key; int coll_nkey; From 2c3285bf51f5faa58d436458bb14592a87182028 Mon Sep 17 00:00:00 2001 From: jooho812 Date: Fri, 14 Jul 2017 15:13:51 +0900 Subject: [PATCH 02/11] CLEANUP : change the range type of bop gbp --- engines/default/default_engine.c | 3 +-- engines/default/items.c | 8 +------- engines/default/items.h | 3 +-- engines/demo/demo_engine.c | 3 +-- include/memcached/engine.h | 3 +-- 5 files changed, 5 insertions(+), 15 deletions(-) diff --git a/engines/default/default_engine.c b/engines/default/default_engine.c index 50db854bc..541a82773 100644 --- a/engines/default/default_engine.c +++ b/engines/default/default_engine.c @@ -978,11 +978,10 @@ static ENGINE_ERROR_CODE default_btree_elem_get_by_posi(ENGINE_HANDLE* handle, const void* cookie, const char *key, const size_t nkey, ENGINE_BTREE_ORDER order, -#ifdef USE_EBLOCK_RESULT uint32_t from_posi, uint32_t to_posi, +#ifdef USE_EBLOCK_RESULT eblock_result_t *eblk_ret, #else - int from_posi, int to_posi, eitem **eitem_array, uint32_t *eitem_count, #endif uint32_t *flags, uint16_t vbucket) diff --git a/engines/default/items.c b/engines/default/items.c index 843bc1ed6..6cdbd902c 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -7435,11 +7435,10 @@ ENGINE_ERROR_CODE btree_posi_find_with_get(struct default_engine *engine, ENGINE_ERROR_CODE btree_elem_get_by_posi(struct default_engine *engine, const char *key, const size_t nkey, -#ifdef USE_EBLOCK_RESULT ENGINE_BTREE_ORDER order, uint32_t from_posi, uint32_t to_posi, +#ifdef USE_EBLOCK_RESULT eblock_result_t *eblk_ret, uint32_t *flags) #else - ENGINE_BTREE_ORDER order, int from_posi, int to_posi, btree_elem_item **elem_array, uint32_t *elem_count, uint32_t *flags) #endif { @@ -7449,11 +7448,6 @@ ENGINE_ERROR_CODE btree_elem_get_by_posi(struct default_engine *engine, uint32_t rqcount; bool forward; -#ifdef USE_EBLOCK_RESULT -#else - assert(from_posi >= 0 && to_posi >= 0); -#endif - pthread_mutex_lock(&engine->cache_lock); ret = do_btree_item_find(engine, key, nkey, true, &it); if (ret == ENGINE_SUCCESS) { diff --git a/engines/default/items.h b/engines/default/items.h index 4f423a831..e215102db 100644 --- a/engines/default/items.h +++ b/engines/default/items.h @@ -596,11 +596,10 @@ ENGINE_ERROR_CODE btree_posi_find_with_get(struct default_engine *engine, ENGINE_ERROR_CODE btree_elem_get_by_posi(struct default_engine *engine, const char *key, const size_t nkey, -#ifdef USE_EBLOCK_RESULT ENGINE_BTREE_ORDER order, uint32_t from_posi, uint32_t to_posi, +#ifdef USE_EBLOCK_RESULT eblock_result_t *eblk_ret, uint32_t *flags); #else - ENGINE_BTREE_ORDER order, int from_posi, int to_posi, btree_elem_item **elem_array, uint32_t *elem_count, uint32_t *flags); #endif diff --git a/engines/demo/demo_engine.c b/engines/demo/demo_engine.c index ac33ca138..59d265e4f 100644 --- a/engines/demo/demo_engine.c +++ b/engines/demo/demo_engine.c @@ -628,11 +628,10 @@ static ENGINE_ERROR_CODE Demo_btree_elem_get_by_posi(ENGINE_HANDLE* handle, const void* cookie, const char *key, const size_t nkey, ENGINE_BTREE_ORDER order, -#ifdef USE_EBLOCK_RESULT uint32_t from_posi, uint32_t to_posi, +#ifdef USE_EBLOCK_RESULT eblock_result_t *eblk_ret, #else - int from_posi, int to_posi, eitem **eitem_array, uint32_t *eitem_count, #endif uint32_t *flags, uint16_t vbucket) diff --git a/include/memcached/engine.h b/include/memcached/engine.h index 13def15e8..507adf73a 100644 --- a/include/memcached/engine.h +++ b/include/memcached/engine.h @@ -593,11 +593,10 @@ extern "C" { ENGINE_ERROR_CODE (*btree_elem_get_by_posi)(ENGINE_HANDLE *handle, const void* cookie, const char *key, const size_t nkey, ENGINE_BTREE_ORDER order, -#ifdef USE_EBLOCK_RESULT uint32_t from_posi, uint32_t to_posi, +#ifdef USE_EBLOCK_RESULT eblock_result_t *eblk_ret, #else - int from_posi, int to_posi, eitem **eitem_array, uint32_t *eitem_count, #endif uint32_t *flags, uint16_t vbucket); From 2de0288b92efc4a3e9a5b7686110325ebb98072b Mon Sep 17 00:00:00 2001 From: jooho812 Date: Mon, 17 Jul 2017 14:47:03 +0900 Subject: [PATCH 03/11] CLEANUP : add btree_elem_mget --- engines/default/default_engine.c | 25 ++++- engines/default/items.c | 75 +++++++++++---- engines/default/items.h | 11 ++- engines/demo/demo_engine.c | 16 ++++ include/memcached/engine.h | 11 +++ include/memcached/types.h | 38 +++++--- memcached.c | 153 ++++++++++++++++++++++--------- 7 files changed, 253 insertions(+), 76 deletions(-) diff --git a/engines/default/default_engine.c b/engines/default/default_engine.c index 541a82773..fd9769661 100644 --- a/engines/default/default_engine.c +++ b/engines/default/default_engine.c @@ -905,7 +905,7 @@ default_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, ret = btree_elem_get(engine, key, nkey, bkrange, efilter, offset, req_count, delete, drop_if_empty, #ifdef USE_EBLOCK_RESULT - eblk_ret, + eblk_ret, EBLOCK_RESULT_SINGLE, #else (btree_elem_item**)eitem_array, eitem_count, #endif @@ -914,6 +914,26 @@ default_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, return ret; } +#ifdef USE_EBLOCK_RESULT +static ENGINE_ERROR_CODE +default_btree_elem_mget(ENGINE_HANDLE* handle, const void* cookie, + const token_t *key_tokens, + const bkey_range *bkrange, const eflag_filter *efilter, + const uint32_t offset, const uint32_t req_count, + eblock_result_t *eblk_ret, uint32_t *access_count, + uint16_t vbucket) +{ + struct default_engine *engine = get_handle(handle); + ENGINE_ERROR_CODE ret; + VBUCKET_GUARD(engine, vbucket); + + ret = btree_elem_mget(engine, key_tokens, bkrange, efilter, + offset, req_count, + eblk_ret, access_count); + return ret; +} +#endif + static ENGINE_ERROR_CODE default_btree_elem_count(ENGINE_HANDLE* handle, const void* cookie, const void* key, const int nkey, @@ -1638,6 +1658,9 @@ create_instance(uint64_t interface, GET_SERVER_API get_server_api, .btree_elem_delete = default_btree_elem_delete, .btree_elem_arithmetic = default_btree_elem_arithmetic, .btree_elem_get = default_btree_elem_get, +#ifdef USE_EBLOCK_RESULT + .btree_elem_mget = default_btree_elem_mget, +#endif .btree_elem_count = default_btree_elem_count, .btree_posi_find = default_btree_posi_find, .btree_posi_find_with_get = default_btree_posi_find_with_get, diff --git a/engines/default/items.c b/engines/default/items.c index 6cdbd902c..5aa80047a 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -4477,7 +4477,7 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ const int bkrtype, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t count, const bool delete, #ifdef USE_EBLOCK_RESULT - eblock_result_t *eblk_ret, + eblock_result_t *eblk_ret, EBLOCK_RESULT_TYPE eblk_type, #else btree_elem_item **elem_array, uint32_t *elem_count, #endif @@ -4491,20 +4491,26 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ *potentialbkeytrim = false; -#ifdef USE_EBLOCK_RESULT - if (EBLOCK_HEAD(eblk_ret) == NULL) { - uint32_t max_cnt = (EBLOCK_NKEY_COUNT(eblk_ret) > 1) ? max_btree_size : info->ccnt; - uint32_t need_size = (count > 0 && count < max_cnt) ? count : max_cnt; - if (!eblk_prepare(eblk_ret, need_size * EBLOCK_NKEY_COUNT(eblk_ret))) - return ENGINE_ENOMEM; - } -#endif if (info->root == NULL) { if (access_count) *access_count = 0; return ENGINE_ELEM_ENOENT; } +#ifdef USE_EBLOCK_RESULT + if (eblk_type == EBLOCK_RESULT_SINGLE) { + if (!eblk_prepare(eblk_ret, (count > 0 && count < info->ccnt) ? count : info->ccnt)) + return ENGINE_ENOMEM; + } else { /* EBLOCK_RESULT_MULTI */ + if (EBLOCK_HEAD(eblk_ret) == NULL) { + uint32_t max_cnt = (EBLOCK_NKEY_COUNT(eblk_ret) > 1) ? max_btree_size : info->ccnt; + uint32_t need_size = (count > 0 && count < max_cnt) ? count : max_cnt; + if (!eblk_prepare(eblk_ret, need_size * EBLOCK_NKEY_COUNT(eblk_ret))) + return ENGINE_ENOMEM; + } + } +#endif + assert(info->root->ndepth < BTREE_MAX_DEPTH); elem = do_btree_find_first(info->root, bkrtype, bkrange, path, delete); if (elem != NULL) { @@ -4644,6 +4650,8 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ *access_count = tot_access; #ifdef USE_EBLOCK_RESULT + if (eblk_type == EBLOCK_RESULT_SINGLE) + eblk_truncate(eblk_ret); #else *elem_count = tot_found; #endif @@ -7243,7 +7251,7 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, 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, + eblock_result_t *eblk_ret, EBLOCK_RESULT_TYPE eblk_type, #else btree_elem_item **elem_array, uint32_t *elem_count, #endif @@ -7273,8 +7281,8 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, } #ifdef USE_EBLOCK_RESULT ret = do_btree_elem_get(engine, info, bkrtype, bkrange, efilter, - offset, req_count, delete, - eblk_ret, access_count, &potentialbkeytrim); + offset, req_count, delete, eblk_ret, + eblk_type, access_count, &potentialbkeytrim); #else ret = do_btree_elem_get(engine, info, bkrtype, bkrange, efilter, offset, req_count, delete, elem_array, @@ -7305,14 +7313,49 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, } while (0); do_item_release(engine, it); } -#ifdef USE_EBLOCK_RESULT - if (--EBLOCK_NKEY_COUNT(eblk_ret) < 1 && EBLOCK_HEAD(eblk_ret) != NULL) - eblk_truncate(eblk_ret); -#endif pthread_mutex_unlock(&engine->cache_lock); return ret; } +#ifdef USE_EBLOCK_RESULT +ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, + const token_t *key_tokens, + const bkey_range *bkrange, const eflag_filter *efilter, + const uint32_t offset, const uint32_t req_count, + eblock_result_t *eblk_ret, + uint32_t *access_count) +{ + assert (EBLOCK_HEAD(eblk_ret) == NULL); + ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; + int k; + int nkey = EBLOCK_NKEY_COUNT(eblk_ret); + uint32_t curr_elem_count = 0; + uint32_t curr_access_count = 0; + + for (k = 0; k < nkey; k++) { + ret = btree_elem_get(engine, key_tokens[k].value, key_tokens[k].length, + bkrange, efilter, offset, req_count, false, false, + eblk_ret, EBLOCK_RESULT_MULTI, &curr_access_count, + &eblk_ret->flags[k], &eblk_ret->trimmed[k]); + if (ret == ENGINE_ENOMEM) { /* eblk_prepare failed */ + break; + } else { + eblk_ret->ret[k] = ret; + eblk_ret->mecnt[k] = EBLOCK_ELEM_COUNT(eblk_ret) - curr_elem_count; + curr_elem_count = EBLOCK_ELEM_COUNT(eblk_ret); + access_count += curr_access_count; + curr_access_count = 0; + if (--EBLOCK_NKEY_COUNT(eblk_ret) < 1) { + ret = ENGINE_SUCCESS; + if (EBLOCK_HEAD(eblk_ret) != NULL) + eblk_truncate(eblk_ret); + } + } + } + return ret; +} +#endif + ENGINE_ERROR_CODE btree_elem_count(struct default_engine *engine, const char *key, const size_t nkey, const bkey_range *bkrange, const eflag_filter *efilter, diff --git a/engines/default/items.h b/engines/default/items.h index e215102db..eec8a45e5 100644 --- a/engines/default/items.h +++ b/engines/default/items.h @@ -567,13 +567,22 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, 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, + eblock_result_t *eblk_ret, EBLOCK_RESULT_TYPE eblk_type, #else btree_elem_item **elem_array, uint32_t *elem_count, #endif uint32_t *access_count, uint32_t *flags, bool *dropped_trimmed); +#ifdef USE_EBLOCK_RESULT +ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, + const token_t *key_tokens, + const bkey_range *bkrange, const eflag_filter *efilter, + const uint32_t offset, const uint32_t req_count, + eblock_result_t *eblk_ret, + uint32_t *access_count); +#endif + ENGINE_ERROR_CODE btree_elem_count(struct default_engine *engine, const char *key, const size_t nkey, const bkey_range *bkrange, const eflag_filter *efilter, diff --git a/engines/demo/demo_engine.c b/engines/demo/demo_engine.c index 59d265e4f..db51828fe 100644 --- a/engines/demo/demo_engine.c +++ b/engines/demo/demo_engine.c @@ -587,6 +587,19 @@ Demo_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, return ENGINE_ENOTSUP; } +#ifdef USE_EBLOCK_RESULT +static ENGINE_ERROR_CODE +Demo_btree_elem_mget(ENGINE_HANDLE* handle, const void*cookie, + const token_t *key_tokens, + const bkey_range *bkrange, const eflag_filter *efilter, + const uint32_t offset, const uint32_t req_count, + eblock_result_t *eblk_ret, uint32_t *access_count, + uint16_t vbucket) +{ + return ENGINE_ENOTSUP; +} +#endif + static ENGINE_ERROR_CODE Demo_btree_elem_count(ENGINE_HANDLE* handle, const void* cookie, const void* key, const int nkey, @@ -858,6 +871,9 @@ create_instance(uint64_t interface, GET_SERVER_API get_server_api, .btree_elem_delete = Demo_btree_elem_delete, .btree_elem_arithmetic = Demo_btree_elem_arithmetic, .btree_elem_get = Demo_btree_elem_get, +#ifdef USE_EBLOCK_RESULT + .btree_elem_mget = Demo_btree_elem_mget, +#endif .btree_elem_count = Demo_btree_elem_count, .btree_posi_find = Demo_btree_posi_find, .btree_posi_find_with_get = Demo_btree_posi_find_with_get, diff --git a/include/memcached/engine.h b/include/memcached/engine.h index 507adf73a..3a96c49af 100644 --- a/include/memcached/engine.h +++ b/include/memcached/engine.h @@ -563,6 +563,17 @@ extern "C" { uint32_t* access_count, uint32_t* flags, bool* dropped_trimmed, uint16_t vbucket); +#ifdef USE_EBLOCK_RESULT + ENGINE_ERROR_CODE (*btree_elem_mget)(ENGINE_HANDLE* handle, const void* cookie, + const token_t *key_tokens, + const bkey_range *bkrange, + const eflag_filter *efilter, + const uint32_t offset, + const uint32_t req_count, + eblock_result_t *eblk_ret, + uint32_t *access_count, uint16_t vbucket); +#endif + ENGINE_ERROR_CODE (*btree_elem_count)(ENGINE_HANDLE* handle, const void* cookie, const void* key, const int nkey, const bkey_range *bkrange, diff --git a/include/memcached/types.h b/include/memcached/types.h index 748f14193..edd9cb337 100644 --- a/include/memcached/types.h +++ b/include/memcached/types.h @@ -317,7 +317,13 @@ extern "C" { struct _mem_block_t *last_blk; /* last block pointer */ uint32_t elem_cnt; /* element count */ uint32_t blck_cnt; /* block count */ - uint32_t num_keys; /* for multiget */ + + /* for multiget */ + uint32_t num_keys; /* number of keys */ + uint32_t *mecnt; /* elem count array for individual keys */ + uint32_t *flags; /* flag array for individual keys */ + bool *trimmed; /* trim check array for individual keys */ + ENGINE_ERROR_CODE *ret; /* engine error code for individual keys */ } eblock_result_t; #endif @@ -386,14 +392,18 @@ extern "C" { #define EBLOCK_ELEM_LAST(b) ((b)->tail_blk->items[(EBLOCK_ELEM_COUNT(b) - 1) % EITEMS_PER_BLOCK]) #define EBLOCK_ELEM_COUNT(b) ((b)->elem_cnt) #define EBLOCK_NKEY_COUNT(b) ((b)->num_keys) -#define EBLOCK_MGET_INIT(b, k) \ - do { \ - (b)->head_blk = NULL; \ - (b)->tail_blk = NULL; \ - (b)->elem_cnt = 0; \ - (b)->blck_cnt = 0; \ - (b)->num_keys = (k); \ - } while(0) \ +#define EBLOCK_MGET_INIT(b, k, p) \ + do { \ + (b)->head_blk = NULL; \ + (b)->tail_blk = NULL; \ + (b)->elem_cnt = 0; \ + (b)->blck_cnt = 0; \ + (b)->num_keys = (k); \ + (b)->mecnt = (uint32_t*)(p); \ + (b)->flags = (uint32_t*)((char*)(b)->mecnt + (sizeof(uint32_t)*(k))); \ + (b)->trimmed = (bool*)((char*)(b)->flags + (sizeof(uint32_t)*(k))); \ + (b)->ret = (ENGINE_ERROR_CODE*)((char*)(b)->trimmed + (sizeof(bool)*(k))); \ + } while(0) \ #define EBLOCK_SCAN_INIT(b, s) \ do { \ @@ -402,11 +412,6 @@ extern "C" { (s)->idx = 0; \ } while(0) \ -#define EBLOCK_MSCAN_NEXT(b, s) \ - do { \ - (s)->tot = (b)->elem_cnt; \ - } while(0) \ - #define EBLOCK_SCAN_NEXT(s, e) \ do { \ if ((s)->idx < (s)->tot) { \ @@ -423,6 +428,11 @@ extern "C" { EITEM_TYPE_BLOCK } EITEM_TYPE; + typedef enum { + EBLOCK_RESULT_SINGLE = 1, /* for single get */ + EBLOCK_RESULT_MULTI /* for multi get */ + } EBLOCK_RESULT_TYPE; + typedef struct _mem_block_t { eitem* items[EITEMS_PER_BLOCK]; struct _mem_block_t *next; diff --git a/memcached.c b/memcached.c index 5de71401b..493b28a61 100644 --- a/memcached.c +++ b/memcached.c @@ -2255,20 +2255,114 @@ static void process_bop_mget_complete(conn *c) { } else /* valid key_tokens */ { - uint32_t cur_elem_count = 0; - uint32_t cur_access_count = 0; - uint32_t flags, k, e; - bool trimmed; +#ifdef USE_EBLOCK_RESULT + uint32_t e, k = 0; eitem_info info; char *resultptr; -#ifdef USE_EBLOCK_RESULT - char *valuestrp = (char*)c->coll_resps; + char *valuestrp; + eitem *elem; eblock_scan_t eblk_sc; EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); + int resultlen; + int nvaluestr; + + EBLOCK_MGET_INIT(&c->eblk_ret, c->coll_numkeys, c->coll_resps); + valuestrp = (char*)c->eblk_ret.ret + (sizeof(ENGINE_ERROR_CODE)*c->coll_numkeys); + + sprintf(valuestrp, "VALUE "); nvaluestr = strlen("VALUE "); + resultptr = valuestrp + nvaluestr; + + if (c->coll_bkrange.to_nbkey == BKEY_NULL) { + memcpy(c->coll_bkrange.to_bkey, c->coll_bkrange.from_bkey, + (c->coll_bkrange.from_nbkey==0 ? sizeof(uint64_t) : c->coll_bkrange.from_nbkey)); + c->coll_bkrange.to_nbkey = c->coll_bkrange.from_nbkey; + } + + ret = mc_engine.v1->btree_elem_mget(mc_engine.v0, c, + key_tokens, &c->coll_bkrange, + (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), + c->coll_roffset, c->coll_rcount, + &c->eblk_ret, &tot_access_count, 0); + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); + if (ret == ENGINE_SUCCESS) { + for (k = 0; k < c->coll_numkeys; k++) { + ret = c->eblk_ret.ret[k]; + + if (settings.detail_enabled) { + stats_prefix_record_bop_get(key_tokens[k].value, key_tokens[k].length, + (ret==ENGINE_SUCCESS || ret==ENGINE_ELEM_ENOENT)); + } + + if (ret == ENGINE_SUCCESS) { + sprintf(resultptr, " %s %u %u\r\n", + (c->eblk_ret.trimmed[k]==false ? "OK" : "TRIMMED"), htonl(c->eblk_ret.flags[k]), (c->eblk_ret.mecnt[k])); + if ((add_iov(c, valuestrp, nvaluestr) != 0) || + (add_iov(c, key_tokens[k].value, key_tokens[k].length) != 0) || + (add_iov(c, resultptr, strlen(resultptr)) != 0)) { + STATS_NOKEY(c, cmd_bop_get); + ret = ENGINE_ENOMEM; break; + } + resultptr += strlen(resultptr); + + for (e = 0; e < c->eblk_ret.mecnt[k]; e++) { + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info); + sprintf(resultptr, "ELEMENT "); + resultlen = strlen(resultptr); + resultlen += make_bop_elem_response(resultptr + resultlen, &info); + + if ((add_iov(c, resultptr, resultlen) != 0) || + (add_iov(c, info.value, info.nbytes) != 0)) { + ret = ENGINE_ENOMEM; break; + } + resultptr += resultlen; + } + if (ret == ENGINE_SUCCESS) { + STATS_ELEM_HITS(c, bop_get, key_tokens[k].value, key_tokens[k].length); + } else { + STATS_NOKEY(c, cmd_bop_get); + // ret == ENGINE_ENOMEM + break; + } + } else { + if (ret == ENGINE_ELEM_ENOENT) { + STATS_NONE_HITS(c, bop_get, key_tokens[k].value, key_tokens[k].length); + sprintf(resultptr, " %s\r\n", "NOT_FOUND_ELEMENT"); + } + else if (ret == ENGINE_KEY_ENOENT || ret == ENGINE_EBKEYOOR || ret == ENGINE_UNREADABLE) { + STATS_MISS(c, bop_get, key_tokens[k].value, key_tokens[k].length); + if (ret == ENGINE_KEY_ENOENT) sprintf(resultptr, " %s\r\n", "NOT_FOUND"); + else if (ret == ENGINE_EBKEYOOR) sprintf(resultptr, " %s\r\n", "OUT_OF_RANGE"); + else sprintf(resultptr, " %s\r\n", "UNREADABLE"); + } + else if (ret == ENGINE_EBADTYPE || ret == ENGINE_EBADBKEY) { + STATS_NOKEY(c, cmd_bop_get); + if (ret == ENGINE_EBADTYPE) sprintf(resultptr, " %s\r\n", "TYPE_MISMATCH"); + else sprintf(resultptr, " %s\r\n", "BKEY_MISMATCH"); + } + else { + break; // ENGINE_DISCONNECT or ENGINE_ENOMEM or SEVERE error + } + + if ((add_iov(c, valuestrp, nvaluestr) != 0) || + (add_iov(c, key_tokens[k].value, key_tokens[k].length) != 0) || + (add_iov(c, resultptr, strlen(resultptr)) != 0)) { + ret = ENGINE_ENOMEM; break; + } + resultptr += strlen(resultptr); + } + } + } /* else ret == ENGINE_ENOMEM */ #else + uint32_t cur_elem_count = 0; + uint32_t cur_access_count = 0; + uint32_t flags, k, e; + bool trimmed; + eitem_info info; + char *resultptr; char *valuestrp = (char*)elem_array + (c->coll_numkeys * c->coll_rcount * sizeof(eitem*)); -#endif int resultlen; int nvaluestr; @@ -2281,9 +2375,6 @@ static void process_bop_mget_complete(conn *c) { c->coll_bkrange.to_nbkey = c->coll_bkrange.from_nbkey; } -#ifdef USE_EBLOCK_RESULT - EBLOCK_MGET_INIT(&c->eblk_ret, c->coll_numkeys); -#endif for (k = 0; k < c->coll_numkeys; k++) { ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, key_tokens[k].value, key_tokens[k].length, @@ -2291,11 +2382,7 @@ static void process_bop_mget_complete(conn *c) { (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), c->coll_roffset, c->coll_rcount, false, false, -#ifdef USE_EBLOCK_RESULT - &c->eblk_ret, -#else &elem_array[tot_elem_count], &cur_elem_count, -#endif &cur_access_count, &flags, &trimmed, 0); if (settings.detail_enabled) { @@ -2305,11 +2392,7 @@ static void process_bop_mget_complete(conn *c) { if (ret == ENGINE_SUCCESS) { sprintf(resultptr, " %s %u %u\r\n", -#ifdef USE_EBLOCK_RESULT - (trimmed==false ? "OK" : "TRIMMED"), htonl(flags), (EBLOCK_ELEM_COUNT(&c->eblk_ret) - cur_elem_count)); -#else (trimmed==false ? "OK" : "TRIMMED"), htonl(flags), cur_elem_count); -#endif if ((add_iov(c, valuestrp, nvaluestr) != 0) || (add_iov(c, key_tokens[k].value, key_tokens[k].length) != 0) || (add_iov(c, resultptr, strlen(resultptr)) != 0)) { @@ -2318,19 +2401,9 @@ static void process_bop_mget_complete(conn *c) { } resultptr += strlen(resultptr); -#ifdef USE_EBLOCK_RESULT - if (k == 0) EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); - else EBLOCK_MSCAN_NEXT(&c->eblk_ret, &eblk_sc); - - for (e = cur_elem_count; e < EBLOCK_ELEM_COUNT(&c->eblk_ret); e++) { - EBLOCK_SCAN_NEXT(&eblk_sc, elem); - mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, - elem, &info); -#else for (e = 0; e < cur_elem_count; e++) { mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[tot_elem_count+e], &info); -#endif sprintf(resultptr, "ELEMENT "); resultlen = strlen(resultptr); resultlen += make_bop_elem_response(resultptr + resultlen, &info); @@ -2343,12 +2416,8 @@ static void process_bop_mget_complete(conn *c) { } if (ret == ENGINE_SUCCESS) { STATS_ELEM_HITS(c, bop_get, key_tokens[k].value, key_tokens[k].length); -#ifdef USE_EBLOCK_RESULT - cur_elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); -#else tot_elem_count += cur_elem_count; cur_elem_count = 0; -#endif tot_access_count += cur_access_count; cur_access_count = 0; } else { @@ -2373,11 +2442,7 @@ static void process_bop_mget_complete(conn *c) { else sprintf(resultptr, " %s\r\n", "BKEY_MISMATCH"); } else { -#ifdef USE_EBLOCK_RESULT - break; // ENGINE_DISCONNECT or ENGINE_ENOMEM or SEVERE error -#else break; // ENGINE_DISCONNECT or SEVERE error -#endif } if ((add_iov(c, valuestrp, nvaluestr) != 0) || @@ -2388,6 +2453,7 @@ static void process_bop_mget_complete(conn *c) { resultptr += strlen(resultptr); } } +#endif if (k == c->coll_numkeys) { ret = ENGINE_SUCCESS; sprintf(resultptr, "END\r\n"); @@ -2395,17 +2461,17 @@ static void process_bop_mget_complete(conn *c) { (IS_UDP(c->transport) && build_udp_headers(c) != 0)) { ret = ENGINE_ENOMEM; } - } else { - // ret != ENGINE_SUCCESS #ifdef USE_EBLOCK_RESULT - cur_elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret); + } #else + } else { + // ret != ENGINE_SUCCESS tot_elem_count += cur_elem_count; cur_elem_count = 0; -#endif tot_access_count += cur_access_count; cur_access_count = 0; } +#endif } switch (ret) { @@ -2413,7 +2479,7 @@ static void process_bop_mget_complete(conn *c) { STATS_NOKEY2(c, cmd_bop_mget, bop_mget_oks); /* Remember this command so we can garbage collect it later */ #ifdef USE_EBLOCK_RESULT - /* c->coll_resps = valuestrp; */ + /* c->coll_resps = c->eblk_ret.mecnt; */ c->coll_eitem = (void *)&c->eblk_ret; #else /* c->coll_eitem = (void *)elem_array; */ @@ -5789,7 +5855,6 @@ static void process_bin_bop_get(conn *c) { if (est_count % 2) est_count += 1; } #ifdef USE_EBLOCK_RESULT - EBLOCK_MGET_INIT(&c->eblk_ret, 1); ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, key, nkey, bkrange, efilter, req->message.body.offset, @@ -11029,7 +11094,6 @@ static void process_bop_get(conn *c, char *key, size_t nkey, ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; #ifdef USE_EBLOCK_RESULT - EBLOCK_MGET_INIT(&c->eblk_ret, 1); ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, key, nkey, bkrange, efilter, offset, count, delete, drop_if_empty, @@ -11756,10 +11820,11 @@ static void process_bop_prepare_nread_keys(conn *c, int cmd, uint32_t vlen, uint #ifdef SUPPORT_BOP_MGET if (cmd == OPERATION_BOP_MGET) { int bmget_count = c->coll_numkeys * c->coll_rcount; + int eblk_size = c->coll_numkeys * ((2*sizeof(uint32_t)) + sizeof(bool) + sizeof(ENGINE_ERROR_CODE)); /* elem_count, flags, trimmed, ret */ int respon_hdr_size = c->coll_numkeys * ((lenstr_size*2)+30); int respon_bdy_size = bmget_count * ((MAX_BKEY_LENG*2+2)+(MAX_EFLAG_LENG*2+2)+lenstr_size+15); - need_size = respon_hdr_size + respon_bdy_size; + need_size = eblk_size + respon_hdr_size + respon_bdy_size; } #endif #ifdef SUPPORT_BOP_SMGET From bd09794b434bc430b777c923476d79d7c857ddfb Mon Sep 17 00:00:00 2001 From: jooho812 Date: Thu, 20 Jul 2017 20:21:19 +0900 Subject: [PATCH 04/11] CLEANUP : reflected minwoojin reviews --- engines/default/default_engine.c | 6 +++--- engines/default/items.c | 19 +++++++++---------- engines/default/items.h | 2 +- engines/demo/demo_engine.c | 4 ++-- include/memcached/engine.h | 2 +- include/memcached/types.h | 12 ++++++------ memcached.c | 10 ++++++---- 7 files changed, 28 insertions(+), 27 deletions(-) diff --git a/engines/default/default_engine.c b/engines/default/default_engine.c index fd9769661..2967b5c62 100644 --- a/engines/default/default_engine.c +++ b/engines/default/default_engine.c @@ -920,8 +920,8 @@ default_btree_elem_mget(ENGINE_HANDLE* handle, const void* cookie, const token_t *key_tokens, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, uint32_t *access_count, - uint16_t vbucket) + eblock_result_t *eblk_ret, uint32_t numkeys, + uint32_t *access_count, uint16_t vbucket) { struct default_engine *engine = get_handle(handle); ENGINE_ERROR_CODE ret; @@ -929,7 +929,7 @@ default_btree_elem_mget(ENGINE_HANDLE* handle, const void* cookie, ret = btree_elem_mget(engine, key_tokens, bkrange, efilter, offset, req_count, - eblk_ret, access_count); + eblk_ret, numkeys, access_count); return ret; } #endif diff --git a/engines/default/items.c b/engines/default/items.c index 5aa80047a..d9d2953d5 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -7322,29 +7322,28 @@ ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, const token_t *key_tokens, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, + eblock_result_t *eblk_ret, uint32_t numkeys, uint32_t *access_count) { assert (EBLOCK_HEAD(eblk_ret) == NULL); ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; int k; - int nkey = EBLOCK_NKEY_COUNT(eblk_ret); - uint32_t curr_elem_count = 0; - uint32_t curr_access_count = 0; + uint32_t cur_elem_count = 0; + uint32_t cur_access_count = 0; - for (k = 0; k < nkey; k++) { + for (k = 0; k < numkeys; k++) { ret = btree_elem_get(engine, key_tokens[k].value, key_tokens[k].length, bkrange, efilter, offset, req_count, false, false, - eblk_ret, EBLOCK_RESULT_MULTI, &curr_access_count, + eblk_ret, EBLOCK_RESULT_MULTI, &cur_access_count, &eblk_ret->flags[k], &eblk_ret->trimmed[k]); if (ret == ENGINE_ENOMEM) { /* eblk_prepare failed */ break; } else { eblk_ret->ret[k] = ret; - eblk_ret->mecnt[k] = EBLOCK_ELEM_COUNT(eblk_ret) - curr_elem_count; - curr_elem_count = EBLOCK_ELEM_COUNT(eblk_ret); - access_count += curr_access_count; - curr_access_count = 0; + eblk_ret->cur_ecnt[k] = EBLOCK_ELEM_COUNT(eblk_ret) - cur_elem_count; + cur_elem_count = EBLOCK_ELEM_COUNT(eblk_ret); + access_count += cur_access_count; + cur_access_count = 0; if (--EBLOCK_NKEY_COUNT(eblk_ret) < 1) { ret = ENGINE_SUCCESS; if (EBLOCK_HEAD(eblk_ret) != NULL) diff --git a/engines/default/items.h b/engines/default/items.h index eec8a45e5..e16e5897f 100644 --- a/engines/default/items.h +++ b/engines/default/items.h @@ -579,7 +579,7 @@ ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, const token_t *key_tokens, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, + eblock_result_t *eblk_ret, uint32_t numkeys, uint32_t *access_count); #endif diff --git a/engines/demo/demo_engine.c b/engines/demo/demo_engine.c index db51828fe..a31eacf0d 100644 --- a/engines/demo/demo_engine.c +++ b/engines/demo/demo_engine.c @@ -593,8 +593,8 @@ Demo_btree_elem_mget(ENGINE_HANDLE* handle, const void*cookie, const token_t *key_tokens, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, uint32_t *access_count, - uint16_t vbucket) + eblock_result_t *eblk_ret, uint32_t numkeys, + uint32_t *access_count, uint16_t vbucket) { return ENGINE_ENOTSUP; } diff --git a/include/memcached/engine.h b/include/memcached/engine.h index 3a96c49af..43b081bd1 100644 --- a/include/memcached/engine.h +++ b/include/memcached/engine.h @@ -570,7 +570,7 @@ extern "C" { const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, + eblock_result_t *eblk_ret, uint32_t numkeys, uint32_t *access_count, uint16_t vbucket); #endif diff --git a/include/memcached/types.h b/include/memcached/types.h index e474f2488..71c88848d 100644 --- a/include/memcached/types.h +++ b/include/memcached/types.h @@ -316,12 +316,12 @@ extern "C" { struct _mem_block_t *head_blk; /* head block pointer */ struct _mem_block_t *tail_blk; /* tail block pointer */ struct _mem_block_t *last_blk; /* last block pointer */ - uint32_t elem_cnt; /* element count */ - uint32_t blck_cnt; /* block count */ + uint32_t elem_cnt; /* total element count */ + uint32_t blck_cnt; /* block count */ /* for multiget */ uint32_t num_keys; /* number of keys */ - uint32_t *mecnt; /* elem count array for individual keys */ + uint32_t *cur_ecnt; /* elem count array for individual keys */ uint32_t *flags; /* flag array for individual keys */ bool *trimmed; /* trim check array for individual keys */ ENGINE_ERROR_CODE *ret; /* engine error code for individual keys */ @@ -400,11 +400,11 @@ extern "C" { (b)->elem_cnt = 0; \ (b)->blck_cnt = 0; \ (b)->num_keys = (k); \ - (b)->mecnt = (uint32_t*)(p); \ - (b)->flags = (uint32_t*)((char*)(b)->mecnt + (sizeof(uint32_t)*(k))); \ + (b)->cur_ecnt = (uint32_t*)(p); \ + (b)->flags = (uint32_t*)((char*)(b)->cur_ecnt + (sizeof(uint32_t)*(k))); \ (b)->trimmed = (bool*)((char*)(b)->flags + (sizeof(uint32_t)*(k))); \ (b)->ret = (ENGINE_ERROR_CODE*)((char*)(b)->trimmed + (sizeof(bool)*(k))); \ - } while(0) \ + } while(0) \ #define EBLOCK_SCAN_INIT(b, s) \ do { \ diff --git a/memcached.c b/memcached.c index 46fe0b492..f4c3f2494 100644 --- a/memcached.c +++ b/memcached.c @@ -2257,6 +2257,7 @@ static void process_bop_mget_complete(conn *c) { { #ifdef USE_EBLOCK_RESULT uint32_t e, k = 0; + uint32_t cur_elem_count; eitem_info info; char *resultptr; char *valuestrp; @@ -2283,11 +2284,12 @@ static void process_bop_mget_complete(conn *c) { key_tokens, &c->coll_bkrange, (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), c->coll_roffset, c->coll_rcount, - &c->eblk_ret, &tot_access_count, 0); + &c->eblk_ret, c->coll_numkeys, &tot_access_count, 0); EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); if (ret == ENGINE_SUCCESS) { for (k = 0; k < c->coll_numkeys; k++) { ret = c->eblk_ret.ret[k]; + cur_elem_count = c->eblk_ret.cur_ecnt[k]; if (settings.detail_enabled) { stats_prefix_record_bop_get(key_tokens[k].value, key_tokens[k].length, @@ -2296,7 +2298,7 @@ static void process_bop_mget_complete(conn *c) { if (ret == ENGINE_SUCCESS) { sprintf(resultptr, " %s %u %u\r\n", - (c->eblk_ret.trimmed[k]==false ? "OK" : "TRIMMED"), htonl(c->eblk_ret.flags[k]), (c->eblk_ret.mecnt[k])); + (c->eblk_ret.trimmed[k]==false ? "OK" : "TRIMMED"), htonl(c->eblk_ret.flags[k]), cur_elem_count); if ((add_iov(c, valuestrp, nvaluestr) != 0) || (add_iov(c, key_tokens[k].value, key_tokens[k].length) != 0) || (add_iov(c, resultptr, strlen(resultptr)) != 0)) { @@ -2305,7 +2307,7 @@ static void process_bop_mget_complete(conn *c) { } resultptr += strlen(resultptr); - for (e = 0; e < c->eblk_ret.mecnt[k]; e++) { + for (e = 0; e < cur_elem_count; e++) { EBLOCK_SCAN_NEXT(&eblk_sc, elem); mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem, &info); @@ -2479,7 +2481,7 @@ static void process_bop_mget_complete(conn *c) { STATS_NOKEY2(c, cmd_bop_mget, bop_mget_oks); /* Remember this command so we can garbage collect it later */ #ifdef USE_EBLOCK_RESULT - /* c->coll_resps = c->eblk_ret.mecnt; */ + /* c->coll_resps = c->eblk_ret.cur_ecnt; */ c->coll_eitem = (void *)&c->eblk_ret; #else /* c->coll_eitem = (void *)elem_array; */ From 5cb240be861c405a7566c315741a45b44a075e5c Mon Sep 17 00:00:00 2001 From: jooho812 Date: Mon, 24 Jul 2017 20:15:36 +0900 Subject: [PATCH 05/11] CLEANUP : reflected minwoojin review --- engines/default/default_engine.c | 10 +++++----- engines/default/items.c | 18 +++++++++--------- engines/default/items.h | 4 ++-- engines/demo/demo_engine.c | 4 ++-- include/memcached/engine.h | 3 ++- memcached.c | 4 ++-- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/engines/default/default_engine.c b/engines/default/default_engine.c index 2967b5c62..b813a5400 100644 --- a/engines/default/default_engine.c +++ b/engines/default/default_engine.c @@ -917,19 +917,19 @@ default_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, #ifdef USE_EBLOCK_RESULT static ENGINE_ERROR_CODE default_btree_elem_mget(ENGINE_HANDLE* handle, const void* cookie, - const token_t *key_tokens, + const token_t *key_tokens, const uint32_t numkeys, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, uint32_t numkeys, + eblock_result_t *eblk_ret, uint32_t *access_count, uint16_t vbucket) { struct default_engine *engine = get_handle(handle); ENGINE_ERROR_CODE ret; VBUCKET_GUARD(engine, vbucket); - ret = btree_elem_mget(engine, key_tokens, bkrange, efilter, - offset, req_count, - eblk_ret, numkeys, access_count); + ret = btree_elem_mget(engine, key_tokens, numkeys, bkrange, + efilter, offset, req_count, + eblk_ret, access_count); return ret; } #endif diff --git a/engines/default/items.c b/engines/default/items.c index d9d2953d5..7a00e24bf 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -4886,7 +4886,7 @@ static int do_btree_posi_find(btree_meta_info *info, static int do_btree_elem_batch_get(btree_elem_posi posi, const int count, const bool forward, const bool reverse, #ifdef USE_EBLOCK_RESULT - eblock_result_t *eblk_ret, int position) + eblock_result_t *eblk_ret) #else btree_elem_item **elem_array) #endif @@ -4901,7 +4901,7 @@ static int do_btree_elem_batch_get(btree_elem_posi posi, const int count, elem = BTREE_GET_ELEM_ITEM(posi.node, posi.indx); elem->refcount++; #ifdef USE_EBLOCK_RESULT - if (reverse) eblk_add_elem_with_posi(eblk_ret, elem, position+count-nfound-1); + if (reverse) eblk_add_elem_with_posi(eblk_ret, elem, count-nfound-1); else eblk_add_elem(eblk_ret, elem); #else if (reverse) elem_array[count-nfound-1] = elem; @@ -4951,13 +4951,13 @@ static int do_btree_posi_find_with_get(btree_meta_info *info, eblk_add_elem_with_posi(eblk_ret, elem, eidx); if (order == BTREE_ORDER_ASC) { - ecnt += do_btree_elem_batch_get(path[0], eidx, false, true, eblk_ret, 0); + ecnt += do_btree_elem_batch_get(path[0], eidx, false, true, eblk_ret); assert((ecnt-1) == eidx); - ecnt += do_btree_elem_batch_get(path[0], count, true, false, eblk_ret, eidx+1); + ecnt += do_btree_elem_batch_get(path[0], count, true, false, eblk_ret); } else { - ecnt += do_btree_elem_batch_get(path[0], eidx, true, true, eblk_ret, 0); + ecnt += do_btree_elem_batch_get(path[0], eidx, true, true, eblk_ret); assert((ecnt-1) == eidx); - ecnt += do_btree_elem_batch_get(path[0], count, false, false, eblk_ret, eidx+1); + ecnt += do_btree_elem_batch_get(path[0], count, false, false, eblk_ret); } eblk_truncate(eblk_ret); #else @@ -5027,7 +5027,7 @@ static ENGINE_ERROR_CODE do_btree_elem_get_by_posi(btree_meta_info *info, #ifdef USE_EBLOCK_RESULT eblk_add_elem(eblk_ret, elem); nfound = 1; - nfound += do_btree_elem_batch_get(posi, count-1, forward, false, eblk_ret, 1); + nfound += do_btree_elem_batch_get(posi, count-1, forward, false, eblk_ret); #else elem_array[0] = elem; nfound = 1; @@ -7319,10 +7319,10 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, #ifdef USE_EBLOCK_RESULT ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, - const token_t *key_tokens, + const token_t *key_tokens, const uint32_t numkeys, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, uint32_t numkeys, + eblock_result_t *eblk_ret, uint32_t *access_count) { assert (EBLOCK_HEAD(eblk_ret) == NULL); diff --git a/engines/default/items.h b/engines/default/items.h index e16e5897f..2c910ab42 100644 --- a/engines/default/items.h +++ b/engines/default/items.h @@ -576,10 +576,10 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, #ifdef USE_EBLOCK_RESULT ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, - const token_t *key_tokens, + const token_t *key_tokens, const uint32_t numkeys, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, uint32_t numkeys, + eblock_result_t *eblk_ret, uint32_t *access_count); #endif diff --git a/engines/demo/demo_engine.c b/engines/demo/demo_engine.c index a31eacf0d..7722d7714 100644 --- a/engines/demo/demo_engine.c +++ b/engines/demo/demo_engine.c @@ -590,10 +590,10 @@ Demo_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, #ifdef USE_EBLOCK_RESULT static ENGINE_ERROR_CODE Demo_btree_elem_mget(ENGINE_HANDLE* handle, const void*cookie, - const token_t *key_tokens, + const token_t *key_tokens, uint32_t numkeys, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, uint32_t numkeys, + eblock_result_t *eblk_ret, uint32_t *access_count, uint16_t vbucket) { return ENGINE_ENOTSUP; diff --git a/include/memcached/engine.h b/include/memcached/engine.h index 43b081bd1..ce5529fee 100644 --- a/include/memcached/engine.h +++ b/include/memcached/engine.h @@ -566,11 +566,12 @@ extern "C" { #ifdef USE_EBLOCK_RESULT ENGINE_ERROR_CODE (*btree_elem_mget)(ENGINE_HANDLE* handle, const void* cookie, const token_t *key_tokens, + const uint32_t numkeys, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, uint32_t numkeys, + eblock_result_t *eblk_ret, uint32_t *access_count, uint16_t vbucket); #endif diff --git a/memcached.c b/memcached.c index f4c3f2494..a6e50a529 100644 --- a/memcached.c +++ b/memcached.c @@ -2281,10 +2281,10 @@ static void process_bop_mget_complete(conn *c) { } ret = mc_engine.v1->btree_elem_mget(mc_engine.v0, c, - key_tokens, &c->coll_bkrange, + key_tokens, c->coll_numkeys, &c->coll_bkrange, (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), c->coll_roffset, c->coll_rcount, - &c->eblk_ret, c->coll_numkeys, &tot_access_count, 0); + &c->eblk_ret, &tot_access_count, 0); EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); if (ret == ENGINE_SUCCESS) { for (k = 0; k < c->coll_numkeys; k++) { From c110481adea099a1b5865782ddb84f61266b7a11 Mon Sep 17 00:00:00 2001 From: jooho812 Date: Wed, 16 Aug 2017 12:08:32 +0900 Subject: [PATCH 06/11] CLEANUP : reflected minwoojin review3 --- memcached.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memcached.c b/memcached.c index a6e50a529..2f639ed28 100644 --- a/memcached.c +++ b/memcached.c @@ -11853,7 +11853,7 @@ static void process_bop_prepare_nread_keys(conn *c, int cmd, uint32_t vlen, uint #ifdef JHPARK_OLD_SMGET_INTERFACE if (c->coll_smgmode == 0) { int smget_count = c->coll_roffset + c->coll_rcount; - int kfnd_array_size; + int kfnd_array_size; /* key index array where the find key indexes are to be saved */ int kmis_array_size; /* key index array where the missed key indexes are to be saved */ int respon_hdr_size; /* the size of response head and tail */ int respon_bdy_size; /* the size of response body */ From 9d37f89b2e837a2ad6ee01d90f17c94f374972d6 Mon Sep 17 00:00:00 2001 From: jooho812 Date: Fri, 18 Aug 2017 18:04:40 +0900 Subject: [PATCH 07/11] CLEANUP : reflected jhpark816 review --- engines/COMMON/mblock_allocator.c | 46 ++++++--- engines/COMMON/mblock_allocator.h | 2 +- engines/default/default_engine.c | 25 +---- engines/default/items.c | 96 +++++-------------- engines/default/items.h | 11 +-- engines/demo/demo_engine.c | 16 ---- include/memcached/engine.h | 12 --- include/memcached/types.h | 27 +----- memcached.c | 149 +++++++++--------------------- 9 files changed, 106 insertions(+), 278 deletions(-) diff --git a/engines/COMMON/mblock_allocator.c b/engines/COMMON/mblock_allocator.c index 6e481ee4b..ab1753c66 100644 --- a/engines/COMMON/mblock_allocator.c +++ b/engines/COMMON/mblock_allocator.c @@ -171,7 +171,7 @@ 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; } } @@ -179,24 +179,25 @@ bool mblock_list_alloc(uint32_t blck_cnt, mem_block_t **head_blk, mem_block_t ** 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) { //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); @@ -226,12 +227,29 @@ void mblock_list_free(uint32_t blck_cnt, mem_block_t *head_blk, mem_block_t *tai 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 + 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 *tmp_head; + mem_block_t *tmp_last; + uint32_t curr_blkcnt = result->blck_cnt; + uint32_t curr_elemcnt = result->elem_cnt; + blkcnt = ((result->elem_cnt + elem_count - 1) / EITEMS_PER_BLOCK) + 1; + if (blkcnt > curr_blkcnt) { // need append block + if (!mblock_list_alloc((blkcnt - curr_blkcnt), &tmp_head, &tmp_last)) { + result->elem_cnt = curr_elemcnt; + return false; + } + result->last_blk->next = tmp_head; + result->last_blk = tmp_last; + } } - result->tail_blk = NULL; result->blck_cnt = blkcnt; return true; } @@ -246,13 +264,13 @@ 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; } diff --git a/engines/COMMON/mblock_allocator.h b/engines/COMMON/mblock_allocator.h index a0d361b83..cab22f266 100644 --- a/engines/COMMON/mblock_allocator.h +++ b/engines/COMMON/mblock_allocator.h @@ -29,7 +29,7 @@ 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); diff --git a/engines/default/default_engine.c b/engines/default/default_engine.c index b813a5400..541a82773 100644 --- a/engines/default/default_engine.c +++ b/engines/default/default_engine.c @@ -905,7 +905,7 @@ default_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, ret = btree_elem_get(engine, key, nkey, bkrange, efilter, offset, req_count, delete, drop_if_empty, #ifdef USE_EBLOCK_RESULT - eblk_ret, EBLOCK_RESULT_SINGLE, + eblk_ret, #else (btree_elem_item**)eitem_array, eitem_count, #endif @@ -914,26 +914,6 @@ default_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, return ret; } -#ifdef USE_EBLOCK_RESULT -static ENGINE_ERROR_CODE -default_btree_elem_mget(ENGINE_HANDLE* handle, const void* cookie, - const token_t *key_tokens, const uint32_t numkeys, - const bkey_range *bkrange, const eflag_filter *efilter, - const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, - uint32_t *access_count, uint16_t vbucket) -{ - struct default_engine *engine = get_handle(handle); - ENGINE_ERROR_CODE ret; - VBUCKET_GUARD(engine, vbucket); - - ret = btree_elem_mget(engine, key_tokens, numkeys, bkrange, - efilter, offset, req_count, - eblk_ret, access_count); - return ret; -} -#endif - static ENGINE_ERROR_CODE default_btree_elem_count(ENGINE_HANDLE* handle, const void* cookie, const void* key, const int nkey, @@ -1658,9 +1638,6 @@ create_instance(uint64_t interface, GET_SERVER_API get_server_api, .btree_elem_delete = default_btree_elem_delete, .btree_elem_arithmetic = default_btree_elem_arithmetic, .btree_elem_get = default_btree_elem_get, -#ifdef USE_EBLOCK_RESULT - .btree_elem_mget = default_btree_elem_mget, -#endif .btree_elem_count = default_btree_elem_count, .btree_posi_find = default_btree_posi_find, .btree_posi_find_with_get = default_btree_posi_find_with_get, diff --git a/engines/default/items.c b/engines/default/items.c index 7a00e24bf..2b5738a9f 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -4477,7 +4477,7 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ const int bkrtype, const bkey_range *bkrange, const eflag_filter *efilter, const uint32_t offset, const uint32_t count, const bool delete, #ifdef USE_EBLOCK_RESULT - eblock_result_t *eblk_ret, EBLOCK_RESULT_TYPE eblk_type, + eblock_result_t *eblk_ret, #else btree_elem_item **elem_array, uint32_t *elem_count, #endif @@ -4498,17 +4498,8 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ } #ifdef USE_EBLOCK_RESULT - if (eblk_type == EBLOCK_RESULT_SINGLE) { - if (!eblk_prepare(eblk_ret, (count > 0 && count < info->ccnt) ? count : info->ccnt)) - return ENGINE_ENOMEM; - } else { /* EBLOCK_RESULT_MULTI */ - if (EBLOCK_HEAD(eblk_ret) == NULL) { - uint32_t max_cnt = (EBLOCK_NKEY_COUNT(eblk_ret) > 1) ? max_btree_size : info->ccnt; - uint32_t need_size = (count > 0 && count < max_cnt) ? count : max_cnt; - if (!eblk_prepare(eblk_ret, need_size * EBLOCK_NKEY_COUNT(eblk_ret))) - return ENGINE_ENOMEM; - } - } + if (!eblk_prepare(eblk_ret, (count > 0 && count < info->ccnt) ? count : info->ccnt)) + return ENGINE_ENOMEM; #endif assert(info->root->ndepth < BTREE_MAX_DEPTH); @@ -4650,8 +4641,7 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ *access_count = tot_access; #ifdef USE_EBLOCK_RESULT - if (eblk_type == EBLOCK_RESULT_SINGLE) - eblk_truncate(eblk_ret); + eblk_truncate(eblk_ret); #else *elem_count = tot_found; #endif @@ -7251,7 +7241,7 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, 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, EBLOCK_RESULT_TYPE eblk_type, + eblock_result_t *eblk_ret, #else btree_elem_item **elem_array, uint32_t *elem_count, #endif @@ -7281,8 +7271,8 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, } #ifdef USE_EBLOCK_RESULT ret = do_btree_elem_get(engine, info, bkrtype, bkrange, efilter, - offset, req_count, delete, eblk_ret, - eblk_type, access_count, &potentialbkeytrim); + offset, req_count, delete, + eblk_ret, access_count, &potentialbkeytrim); #else ret = do_btree_elem_get(engine, info, bkrtype, bkrange, efilter, offset, req_count, delete, elem_array, @@ -7317,44 +7307,6 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, return ret; } -#ifdef USE_EBLOCK_RESULT -ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, - const token_t *key_tokens, const uint32_t numkeys, - const bkey_range *bkrange, const eflag_filter *efilter, - const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, - uint32_t *access_count) -{ - assert (EBLOCK_HEAD(eblk_ret) == NULL); - ENGINE_ERROR_CODE ret = ENGINE_SUCCESS; - int k; - uint32_t cur_elem_count = 0; - uint32_t cur_access_count = 0; - - for (k = 0; k < numkeys; k++) { - ret = btree_elem_get(engine, key_tokens[k].value, key_tokens[k].length, - bkrange, efilter, offset, req_count, false, false, - eblk_ret, EBLOCK_RESULT_MULTI, &cur_access_count, - &eblk_ret->flags[k], &eblk_ret->trimmed[k]); - if (ret == ENGINE_ENOMEM) { /* eblk_prepare failed */ - break; - } else { - eblk_ret->ret[k] = ret; - eblk_ret->cur_ecnt[k] = EBLOCK_ELEM_COUNT(eblk_ret) - cur_elem_count; - cur_elem_count = EBLOCK_ELEM_COUNT(eblk_ret); - access_count += cur_access_count; - cur_access_count = 0; - if (--EBLOCK_NKEY_COUNT(eblk_ret) < 1) { - ret = ENGINE_SUCCESS; - if (EBLOCK_HEAD(eblk_ret) != NULL) - eblk_truncate(eblk_ret); - } - } - } - return ret; -} -#endif - ENGINE_ERROR_CODE btree_elem_count(struct default_engine *engine, const char *key, const size_t nkey, const bkey_range *bkrange, const eflag_filter *efilter, @@ -7946,25 +7898,27 @@ static void do_coll_elem_release(struct default_engine *engine, eitem *item, EIT pthread_mutex_unlock(&engine->cache_lock); } else if (type == EITEM_TYPE_BLOCK) { eblock_result_t *eblk_ret = (eblock_result_t *)item; - uint32_t elem_count = EBLOCK_ELEM_COUNT(eblk_ret); - uint32_t lock_count, i, j; - eblock_scan_t eblk_sc; - eitem *elem; - - EBLOCK_SCAN_INIT(eblk_ret, &eblk_sc); - for (i = 0; i < elem_count; i += lock_count) { - lock_count = (elem_count-i) < 100 - ? (elem_count-i) : 100; - pthread_mutex_lock(&engine->cache_lock); - for (j = 0; j < lock_count; j++) { - EBLOCK_SCAN_NEXT(&eblk_sc, elem); - elem_release_func(engine, elem); + if (eblk_ret->head_blk != NULL) { //validate check + uint32_t elem_count = EBLOCK_ELEM_COUNT(eblk_ret); + uint32_t lock_count, i, j; + eblock_scan_t eblk_sc; + eitem *elem; + + EBLOCK_SCAN_INIT(eblk_ret, &eblk_sc); + for (i = 0; i < elem_count; i += lock_count) { + lock_count = (elem_count-i) < 100 + ? (elem_count-i) : 100; + pthread_mutex_lock(&engine->cache_lock); + for (j = 0; j < lock_count; j++) { + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + elem_release_func(engine, elem); + } + pthread_mutex_unlock(&engine->cache_lock); } + pthread_mutex_lock(&engine->cache_lock); + mblock_list_free(eblk_ret->blck_cnt, &eblk_ret->head_blk, &eblk_ret->tail_blk); pthread_mutex_unlock(&engine->cache_lock); } - pthread_mutex_lock(&engine->cache_lock); - mblock_list_free(eblk_ret->blck_cnt, eblk_ret->head_blk, eblk_ret->tail_blk); - pthread_mutex_unlock(&engine->cache_lock); } } #endif diff --git a/engines/default/items.h b/engines/default/items.h index 2c910ab42..e215102db 100644 --- a/engines/default/items.h +++ b/engines/default/items.h @@ -567,22 +567,13 @@ ENGINE_ERROR_CODE btree_elem_get(struct default_engine *engine, 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, EBLOCK_RESULT_TYPE eblk_type, + eblock_result_t *eblk_ret, #else btree_elem_item **elem_array, uint32_t *elem_count, #endif uint32_t *access_count, uint32_t *flags, bool *dropped_trimmed); -#ifdef USE_EBLOCK_RESULT -ENGINE_ERROR_CODE btree_elem_mget(struct default_engine *engine, - const token_t *key_tokens, const uint32_t numkeys, - const bkey_range *bkrange, const eflag_filter *efilter, - const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, - uint32_t *access_count); -#endif - ENGINE_ERROR_CODE btree_elem_count(struct default_engine *engine, const char *key, const size_t nkey, const bkey_range *bkrange, const eflag_filter *efilter, diff --git a/engines/demo/demo_engine.c b/engines/demo/demo_engine.c index 7722d7714..59d265e4f 100644 --- a/engines/demo/demo_engine.c +++ b/engines/demo/demo_engine.c @@ -587,19 +587,6 @@ Demo_btree_elem_get(ENGINE_HANDLE* handle, const void* cookie, return ENGINE_ENOTSUP; } -#ifdef USE_EBLOCK_RESULT -static ENGINE_ERROR_CODE -Demo_btree_elem_mget(ENGINE_HANDLE* handle, const void*cookie, - const token_t *key_tokens, uint32_t numkeys, - const bkey_range *bkrange, const eflag_filter *efilter, - const uint32_t offset, const uint32_t req_count, - eblock_result_t *eblk_ret, - uint32_t *access_count, uint16_t vbucket) -{ - return ENGINE_ENOTSUP; -} -#endif - static ENGINE_ERROR_CODE Demo_btree_elem_count(ENGINE_HANDLE* handle, const void* cookie, const void* key, const int nkey, @@ -871,9 +858,6 @@ create_instance(uint64_t interface, GET_SERVER_API get_server_api, .btree_elem_delete = Demo_btree_elem_delete, .btree_elem_arithmetic = Demo_btree_elem_arithmetic, .btree_elem_get = Demo_btree_elem_get, -#ifdef USE_EBLOCK_RESULT - .btree_elem_mget = Demo_btree_elem_mget, -#endif .btree_elem_count = Demo_btree_elem_count, .btree_posi_find = Demo_btree_posi_find, .btree_posi_find_with_get = Demo_btree_posi_find_with_get, diff --git a/include/memcached/engine.h b/include/memcached/engine.h index ce5529fee..507adf73a 100644 --- a/include/memcached/engine.h +++ b/include/memcached/engine.h @@ -563,18 +563,6 @@ extern "C" { uint32_t* access_count, uint32_t* flags, bool* dropped_trimmed, uint16_t vbucket); -#ifdef USE_EBLOCK_RESULT - ENGINE_ERROR_CODE (*btree_elem_mget)(ENGINE_HANDLE* handle, const void* cookie, - const token_t *key_tokens, - const uint32_t numkeys, - const bkey_range *bkrange, - const eflag_filter *efilter, - const uint32_t offset, - const uint32_t req_count, - eblock_result_t *eblk_ret, - uint32_t *access_count, uint16_t vbucket); -#endif - ENGINE_ERROR_CODE (*btree_elem_count)(ENGINE_HANDLE* handle, const void* cookie, const void* key, const int nkey, const bkey_range *bkrange, diff --git a/include/memcached/types.h b/include/memcached/types.h index 71c88848d..22fe5f438 100644 --- a/include/memcached/types.h +++ b/include/memcached/types.h @@ -318,13 +318,6 @@ extern "C" { struct _mem_block_t *last_blk; /* last block pointer */ uint32_t elem_cnt; /* total element count */ uint32_t blck_cnt; /* block count */ - - /* for multiget */ - uint32_t num_keys; /* number of keys */ - uint32_t *cur_ecnt; /* elem count array for individual keys */ - uint32_t *flags; /* flag array for individual keys */ - bool *trimmed; /* trim check array for individual keys */ - ENGINE_ERROR_CODE *ret; /* engine error code for individual keys */ } eblock_result_t; #endif @@ -389,22 +382,8 @@ extern "C" { #ifdef USE_EBLOCK_RESULT #define EITEMS_PER_BLOCK 1023 -#define EBLOCK_HEAD(b) ((b)->head_blk) #define EBLOCK_ELEM_LAST(b) ((b)->tail_blk->items[(EBLOCK_ELEM_COUNT(b) - 1) % EITEMS_PER_BLOCK]) #define EBLOCK_ELEM_COUNT(b) ((b)->elem_cnt) -#define EBLOCK_NKEY_COUNT(b) ((b)->num_keys) -#define EBLOCK_MGET_INIT(b, k, p) \ - do { \ - (b)->head_blk = NULL; \ - (b)->tail_blk = NULL; \ - (b)->elem_cnt = 0; \ - (b)->blck_cnt = 0; \ - (b)->num_keys = (k); \ - (b)->cur_ecnt = (uint32_t*)(p); \ - (b)->flags = (uint32_t*)((char*)(b)->cur_ecnt + (sizeof(uint32_t)*(k))); \ - (b)->trimmed = (bool*)((char*)(b)->flags + (sizeof(uint32_t)*(k))); \ - (b)->ret = (ENGINE_ERROR_CODE*)((char*)(b)->trimmed + (sizeof(bool)*(k))); \ - } while(0) \ #define EBLOCK_SCAN_INIT(b, s) \ do { \ @@ -413,12 +392,14 @@ extern "C" { (s)->idx = 0; \ } while(0) \ +#define EBLOCK_SCAN_RESET(b, s) ((s)->tot = (b)->elem_cnt) + #define EBLOCK_SCAN_NEXT(s, e) \ do { \ if ((s)->idx < (s)->tot) { \ - (e) = ((s)->blk)->items[(s)->idx % EITEMS_PER_BLOCK]; \ - if ((((s)->idx)++ % EITEMS_PER_BLOCK) == (EITEMS_PER_BLOCK - 1)) \ + if (((s)->idx % EITEMS_PER_BLOCK) == 0 && ((s)->idx != 0)) \ (s)->blk = ((s)->blk)->next; \ + (e) = ((s)->blk)->items[(s)->idx++ % EITEMS_PER_BLOCK]; \ } else { \ (e) = NULL; \ } \ diff --git a/memcached.c b/memcached.c index 2f639ed28..70edde4aa 100644 --- a/memcached.c +++ b/memcached.c @@ -2241,8 +2241,8 @@ static void process_bop_mget_complete(conn *c) { #ifdef USE_EBLOCK_RESULT #else eitem **elem_array = (eitem **)c->coll_eitem; - uint32_t tot_elem_count = 0; #endif + uint32_t tot_elem_count = 0; uint32_t tot_access_count = 0; char delimiter = ','; token_t *key_tokens = (token_t *)((char*)c->coll_strkeys + GET_8ALIGN_SIZE(c->coll_lenkeys)); @@ -2255,116 +2255,20 @@ static void process_bop_mget_complete(conn *c) { } else /* valid key_tokens */ { -#ifdef USE_EBLOCK_RESULT - uint32_t e, k = 0; - uint32_t cur_elem_count; - eitem_info info; - char *resultptr; - char *valuestrp; - - eitem *elem; - eblock_scan_t eblk_sc; - EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); - int resultlen; - int nvaluestr; - - EBLOCK_MGET_INIT(&c->eblk_ret, c->coll_numkeys, c->coll_resps); - valuestrp = (char*)c->eblk_ret.ret + (sizeof(ENGINE_ERROR_CODE)*c->coll_numkeys); - - sprintf(valuestrp, "VALUE "); nvaluestr = strlen("VALUE "); - resultptr = valuestrp + nvaluestr; - - if (c->coll_bkrange.to_nbkey == BKEY_NULL) { - memcpy(c->coll_bkrange.to_bkey, c->coll_bkrange.from_bkey, - (c->coll_bkrange.from_nbkey==0 ? sizeof(uint64_t) : c->coll_bkrange.from_nbkey)); - c->coll_bkrange.to_nbkey = c->coll_bkrange.from_nbkey; - } - - ret = mc_engine.v1->btree_elem_mget(mc_engine.v0, c, - key_tokens, c->coll_numkeys, &c->coll_bkrange, - (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), - c->coll_roffset, c->coll_rcount, - &c->eblk_ret, &tot_access_count, 0); - EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); - if (ret == ENGINE_SUCCESS) { - for (k = 0; k < c->coll_numkeys; k++) { - ret = c->eblk_ret.ret[k]; - cur_elem_count = c->eblk_ret.cur_ecnt[k]; - - if (settings.detail_enabled) { - stats_prefix_record_bop_get(key_tokens[k].value, key_tokens[k].length, - (ret==ENGINE_SUCCESS || ret==ENGINE_ELEM_ENOENT)); - } - - if (ret == ENGINE_SUCCESS) { - sprintf(resultptr, " %s %u %u\r\n", - (c->eblk_ret.trimmed[k]==false ? "OK" : "TRIMMED"), htonl(c->eblk_ret.flags[k]), cur_elem_count); - if ((add_iov(c, valuestrp, nvaluestr) != 0) || - (add_iov(c, key_tokens[k].value, key_tokens[k].length) != 0) || - (add_iov(c, resultptr, strlen(resultptr)) != 0)) { - STATS_NOKEY(c, cmd_bop_get); - ret = ENGINE_ENOMEM; break; - } - resultptr += strlen(resultptr); - - for (e = 0; e < cur_elem_count; e++) { - EBLOCK_SCAN_NEXT(&eblk_sc, elem); - mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, - elem, &info); - sprintf(resultptr, "ELEMENT "); - resultlen = strlen(resultptr); - resultlen += make_bop_elem_response(resultptr + resultlen, &info); - - if ((add_iov(c, resultptr, resultlen) != 0) || - (add_iov(c, info.value, info.nbytes) != 0)) { - ret = ENGINE_ENOMEM; break; - } - resultptr += resultlen; - } - if (ret == ENGINE_SUCCESS) { - STATS_ELEM_HITS(c, bop_get, key_tokens[k].value, key_tokens[k].length); - } else { - STATS_NOKEY(c, cmd_bop_get); - // ret == ENGINE_ENOMEM - break; - } - } else { - if (ret == ENGINE_ELEM_ENOENT) { - STATS_NONE_HITS(c, bop_get, key_tokens[k].value, key_tokens[k].length); - sprintf(resultptr, " %s\r\n", "NOT_FOUND_ELEMENT"); - } - else if (ret == ENGINE_KEY_ENOENT || ret == ENGINE_EBKEYOOR || ret == ENGINE_UNREADABLE) { - STATS_MISS(c, bop_get, key_tokens[k].value, key_tokens[k].length); - if (ret == ENGINE_KEY_ENOENT) sprintf(resultptr, " %s\r\n", "NOT_FOUND"); - else if (ret == ENGINE_EBKEYOOR) sprintf(resultptr, " %s\r\n", "OUT_OF_RANGE"); - else sprintf(resultptr, " %s\r\n", "UNREADABLE"); - } - else if (ret == ENGINE_EBADTYPE || ret == ENGINE_EBADBKEY) { - STATS_NOKEY(c, cmd_bop_get); - if (ret == ENGINE_EBADTYPE) sprintf(resultptr, " %s\r\n", "TYPE_MISMATCH"); - else sprintf(resultptr, " %s\r\n", "BKEY_MISMATCH"); - } - else { - break; // ENGINE_DISCONNECT or ENGINE_ENOMEM or SEVERE error - } - - if ((add_iov(c, valuestrp, nvaluestr) != 0) || - (add_iov(c, key_tokens[k].value, key_tokens[k].length) != 0) || - (add_iov(c, resultptr, strlen(resultptr)) != 0)) { - ret = ENGINE_ENOMEM; break; - } - resultptr += strlen(resultptr); - } - } - } /* else ret == ENGINE_ENOMEM */ -#else uint32_t cur_elem_count = 0; uint32_t cur_access_count = 0; uint32_t flags, k, e; bool trimmed; eitem_info info; char *resultptr; +#ifdef USE_EBLOCK_RESULT + char *valuestrp = c->coll_resps; + bool eblk_scan_init = false; + eitem *elem; + eblock_scan_t eblk_sc; +#else char *valuestrp = (char*)elem_array + (c->coll_numkeys * c->coll_rcount * sizeof(eitem*)); +#endif int resultlen; int nvaluestr; @@ -2377,7 +2281,20 @@ static void process_bop_mget_complete(conn *c) { c->coll_bkrange.to_nbkey = c->coll_bkrange.from_nbkey; } +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); //dummy initialization +#endif for (k = 0; k < c->coll_numkeys; k++) { +#ifdef USE_EBLOCK_RESULT + ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, + key_tokens[k].value, key_tokens[k].length, + &c->coll_bkrange, + (c->coll_efilter.ncompval==0 ? NULL : &c->coll_efilter), + c->coll_roffset, c->coll_rcount, + false, false, + &c->eblk_ret, + &cur_access_count, &flags, &trimmed, 0); +#else ret = mc_engine.v1->btree_elem_get(mc_engine.v0, c, key_tokens[k].value, key_tokens[k].length, &c->coll_bkrange, @@ -2386,6 +2303,7 @@ static void process_bop_mget_complete(conn *c) { false, false, &elem_array[tot_elem_count], &cur_elem_count, &cur_access_count, &flags, &trimmed, 0); +#endif if (settings.detail_enabled) { stats_prefix_record_bop_get(key_tokens[k].value, key_tokens[k].length, @@ -2393,6 +2311,9 @@ static void process_bop_mget_complete(conn *c) { } if (ret == ENGINE_SUCCESS) { +#ifdef USE_EBLOCK_RESULT + cur_elem_count = EBLOCK_ELEM_COUNT(&c->eblk_ret) - tot_elem_count; +#endif sprintf(resultptr, " %s %u %u\r\n", (trimmed==false ? "OK" : "TRIMMED"), htonl(flags), cur_elem_count); if ((add_iov(c, valuestrp, nvaluestr) != 0) || @@ -2403,9 +2324,25 @@ static void process_bop_mget_complete(conn *c) { } resultptr += strlen(resultptr); +#ifdef USE_EBLOCK_RESULT + if (cur_elem_count > 0) { + if (eblk_scan_init == false) { + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); + eblk_scan_init = true; + } else { + EBLOCK_SCAN_RESET(&c->eblk_ret, &eblk_sc); + } + } +#endif for (e = 0; e < cur_elem_count; e++) { +#ifdef USE_EBLOCK_RESULT + EBLOCK_SCAN_NEXT(&eblk_sc, elem); + mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, + elem, &info); +#else mc_engine.v1->get_elem_info(mc_engine.v0, c, ITEM_TYPE_BTREE, elem_array[tot_elem_count+e], &info); +#endif sprintf(resultptr, "ELEMENT "); resultlen = strlen(resultptr); resultlen += make_bop_elem_response(resultptr + resultlen, &info); @@ -2455,7 +2392,6 @@ static void process_bop_mget_complete(conn *c) { resultptr += strlen(resultptr); } } -#endif if (k == c->coll_numkeys) { ret = ENGINE_SUCCESS; sprintf(resultptr, "END\r\n"); @@ -11841,11 +11777,10 @@ static void process_bop_prepare_nread_keys(conn *c, int cmd, uint32_t vlen, uint #ifdef SUPPORT_BOP_MGET if (cmd == OPERATION_BOP_MGET) { int bmget_count = c->coll_numkeys * c->coll_rcount; - int eblk_size = c->coll_numkeys * ((2*sizeof(uint32_t)) + sizeof(bool) + sizeof(ENGINE_ERROR_CODE)); /* elem_count, flags, trimmed, ret */ int respon_hdr_size = c->coll_numkeys * ((lenstr_size*2)+30); int respon_bdy_size = bmget_count * ((MAX_BKEY_LENG*2+2)+(MAX_EFLAG_LENG*2+2)+lenstr_size+15); - need_size = eblk_size + respon_hdr_size + respon_bdy_size; + need_size = respon_hdr_size + respon_bdy_size; } #endif #ifdef SUPPORT_BOP_SMGET From 6341ad46859116b244b09d091721ef8c67a168cd Mon Sep 17 00:00:00 2001 From: jooho812 Date: Fri, 18 Aug 2017 19:05:36 +0900 Subject: [PATCH 08/11] CLEANUP : reflected minwoojin review --- engines/COMMON/mblock_allocator.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/engines/COMMON/mblock_allocator.c b/engines/COMMON/mblock_allocator.c index ab1753c66..736e04e18 100644 --- a/engines/COMMON/mblock_allocator.c +++ b/engines/COMMON/mblock_allocator.c @@ -236,18 +236,15 @@ bool eblk_prepare(eblock_result_t *result, uint32_t elem_count) { } result->tail_blk = NULL; } else { - mem_block_t *tmp_head; - mem_block_t *tmp_last; + mem_block_t *head; + mem_block_t *last; uint32_t curr_blkcnt = result->blck_cnt; - uint32_t curr_elemcnt = result->elem_cnt; blkcnt = ((result->elem_cnt + elem_count - 1) / EITEMS_PER_BLOCK) + 1; if (blkcnt > curr_blkcnt) { // need append block - if (!mblock_list_alloc((blkcnt - curr_blkcnt), &tmp_head, &tmp_last)) { - result->elem_cnt = curr_elemcnt; + if (!mblock_list_alloc((blkcnt - curr_blkcnt), &head, &last)) return false; - } - result->last_blk->next = tmp_head; - result->last_blk = tmp_last; + result->last_blk->next = head; + result->last_blk = last; } } result->blck_cnt = blkcnt; From 88bdb04d79d8e67bc4eb36fe0b5dc5166678f0e1 Mon Sep 17 00:00:00 2001 From: jooho812 Date: Mon, 21 Aug 2017 11:55:05 +0900 Subject: [PATCH 09/11] CLEANUP : reflected reviews --- engines/COMMON/mblock_allocator.c | 6 ++++-- engines/default/items.c | 5 +++-- include/memcached/types.h | 10 +++++++++- memcached.c | 11 ++--------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/engines/COMMON/mblock_allocator.c b/engines/COMMON/mblock_allocator.c index 736e04e18..53dfdef9a 100644 --- a/engines/COMMON/mblock_allocator.c +++ b/engines/COMMON/mblock_allocator.c @@ -239,9 +239,11 @@ bool eblk_prepare(eblock_result_t *result, uint32_t elem_count) { 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; - if (blkcnt > curr_blkcnt) { // need append block - if (!mblock_list_alloc((blkcnt - curr_blkcnt), &head, &last)) + 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; diff --git a/engines/default/items.c b/engines/default/items.c index 2b5738a9f..67323c592 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -4934,11 +4934,11 @@ static int do_btree_posi_find_with_get(btree_meta_info *info, ecnt = 1; /* elem count */ eidx = (bpos < count) ? bpos : count; /* elem index in elem array */ - elem->refcount++; #ifdef USE_EBLOCK_RESULT if (!eblk_prepare(eblk_ret, (eidx + count + 1))) return ENGINE_ENOMEM; + elem->refcount++; eblk_add_elem_with_posi(eblk_ret, elem, eidx); if (order == BTREE_ORDER_ASC) { ecnt += do_btree_elem_batch_get(path[0], eidx, false, true, eblk_ret); @@ -4951,6 +4951,7 @@ static int do_btree_posi_find_with_get(btree_meta_info *info, } eblk_truncate(eblk_ret); #else + elem->refcount++; elem_array[eidx] = elem; if (order == BTREE_ORDER_ASC) { @@ -4994,7 +4995,7 @@ static ENGINE_ERROR_CODE do_btree_elem_get_by_posi(btree_meta_info *info, if (info->root == NULL) return ENGINE_ELEM_ENOENT; #ifdef USE_EBLOCK_RESULT - if (!eblk_prepare(eblk_ret, (count > 0 && count < info->ccnt) ? count : info->ccnt)) + if (!eblk_prepare(eblk_ret, (count < info->ccnt) ? count : info->ccnt)) return ENGINE_ENOMEM; #endif node = info->root; diff --git a/include/memcached/types.h b/include/memcached/types.h index 22fe5f438..c77296238 100644 --- a/include/memcached/types.h +++ b/include/memcached/types.h @@ -392,7 +392,15 @@ extern "C" { (s)->idx = 0; \ } while(0) \ -#define EBLOCK_SCAN_RESET(b, s) ((s)->tot = (b)->elem_cnt) +#define EBLOCK_SCAN_RESET(f, b, s) \ + do { \ + if ((f) == false) { \ + (s)->blk = (b)->head_blk; \ + (s)->idx = 0; \ + (f) = true; \ + } \ + (s)->tot = (b)->elem_cnt; \ + } while(0) \ #define EBLOCK_SCAN_NEXT(s, e) \ do { \ diff --git a/memcached.c b/memcached.c index 70edde4aa..e0f4f1f65 100644 --- a/memcached.c +++ b/memcached.c @@ -2282,7 +2282,7 @@ static void process_bop_mget_complete(conn *c) { } #ifdef USE_EBLOCK_RESULT - EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); //dummy initialization + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); #endif for (k = 0; k < c->coll_numkeys; k++) { #ifdef USE_EBLOCK_RESULT @@ -2325,14 +2325,7 @@ static void process_bop_mget_complete(conn *c) { resultptr += strlen(resultptr); #ifdef USE_EBLOCK_RESULT - if (cur_elem_count > 0) { - if (eblk_scan_init == false) { - EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); - eblk_scan_init = true; - } else { - EBLOCK_SCAN_RESET(&c->eblk_ret, &eblk_sc); - } - } + EBLOCK_SCAN_RESET(eblk_scan_init, &c->eblk_ret, &eblk_sc); #endif for (e = 0; e < cur_elem_count; e++) { #ifdef USE_EBLOCK_RESULT From 17aaf07cc6be913266d84bc01ce95415460fa13a Mon Sep 17 00:00:00 2001 From: jooho812 Date: Wed, 23 Aug 2017 16:26:52 +0900 Subject: [PATCH 10/11] CLEANUP : modified eblk_add_elem_with_posi --- engines/COMMON/mblock_allocator.c | 36 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/engines/COMMON/mblock_allocator.c b/engines/COMMON/mblock_allocator.c index 53dfdef9a..fea8cfc53 100644 --- a/engines/COMMON/mblock_allocator.c +++ b/engines/COMMON/mblock_allocator.c @@ -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; @@ -276,25 +287,20 @@ void eblk_truncate(eblock_result_t *result) { } 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) { - /* This function should not be used when there are multiple blocks. */ - assert(result->blck_cnt == 1); - if (result->tail_blk == NULL) { - result->tail_blk = result->head_blk; - result->elem_cnt = 0; + 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[posi % EITEMS_PER_BLOCK] = (eitem *)elem; + + prepare_eblk_add_elem(result); + curr_blk->items[posi % EITEMS_PER_BLOCK] = (eitem *)elem; result->elem_cnt++; } From c8e71d8381a4aa3767ef7dd84649e852675f89b0 Mon Sep 17 00:00:00 2001 From: jooho812 Date: Tue, 12 Sep 2017 13:49:59 +0900 Subject: [PATCH 11/11] CLEANUP : reflected minwoojin review --- engines/default/items.c | 1 - include/memcached/types.h | 3 ++- memcached.c | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/engines/default/items.c b/engines/default/items.c index 67323c592..a3cbed71c 100644 --- a/engines/default/items.c +++ b/engines/default/items.c @@ -4483,7 +4483,6 @@ static ENGINE_ERROR_CODE do_btree_elem_get(struct default_engine *engine, btree_ #endif uint32_t *access_count, bool *potentialbkeytrim) { - btree_elem_posi path[BTREE_MAX_DEPTH]; btree_elem_item *elem; uint32_t tot_found = 0; /* total found count */ diff --git a/include/memcached/types.h b/include/memcached/types.h index c77296238..1c5137cd3 100644 --- a/include/memcached/types.h +++ b/include/memcached/types.h @@ -405,8 +405,9 @@ extern "C" { #define EBLOCK_SCAN_NEXT(s, e) \ do { \ if ((s)->idx < (s)->tot) { \ - if (((s)->idx % EITEMS_PER_BLOCK) == 0 && ((s)->idx != 0)) \ + if (((s)->idx % EITEMS_PER_BLOCK) == 0 && ((s)->idx != 0)) { \ (s)->blk = ((s)->blk)->next; \ + } \ (e) = ((s)->blk)->items[(s)->idx++ % EITEMS_PER_BLOCK]; \ } else { \ (e) = NULL; \ diff --git a/memcached.c b/memcached.c index e0f4f1f65..4de73ac14 100644 --- a/memcached.c +++ b/memcached.c @@ -5827,6 +5827,7 @@ static void process_bin_bop_get(conn *c) { case ENGINE_SUCCESS: { protocol_binary_response_bop_get* rsp = (protocol_binary_response_bop_get*)c->wbuf; + eitem_info info[elem_count]; #ifdef USE_EBLOCK_RESULT eitem *elem; eblock_scan_t eblk_sc; @@ -5846,10 +5847,7 @@ static void process_bin_bop_get(conn *c) { ret = ENGINE_ENOMEM; } else { vlenptr = (uint32_t *)((char*)bkeyptr + (sizeof(uint64_t) * elem_count)); -#endif - eitem_info info[elem_count]; -#ifdef USE_EBLOCK_RESULT - EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); + EBLOCK_SCAN_INIT(&c->eblk_ret, &eblk_sc); #endif for (i = 0; i < elem_count; i++) { #ifdef USE_EBLOCK_RESULT