-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FEATURE: add set offset command #813
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -219,7 +219,6 @@ static void do_set_node_link(set_meta_info *info, | |
|
||
par_node->htab[par_hidx] = node; | ||
par_node->hcnt[par_hidx] = -1; /* child hash node */ | ||
par_node->tot_elem_cnt -= num_found; | ||
par_node->tot_hash_cnt += 1; | ||
} | ||
|
||
|
@@ -288,11 +287,14 @@ static ENGINE_ERROR_CODE do_set_elem_link(set_meta_info *info, set_elem_item *el | |
set_hash_node *node = info->root; | ||
set_elem_item *find; | ||
int hidx = -1; | ||
set_hash_node *parents[100]; | ||
int cur_depth = 0; | ||
|
||
/* set hash value */ | ||
elem->hval = genhash_string_hash(elem->value, elem->nbytes); | ||
|
||
while (node != NULL) { | ||
parents[cur_depth++] = node; | ||
hidx = SET_GET_HASHIDX(elem->hval, node->hdepth); | ||
if (node->hcnt[hidx] >= 0) /* set element hash chain */ | ||
break; | ||
|
@@ -326,6 +328,10 @@ static ENGINE_ERROR_CODE do_set_elem_link(set_meta_info *info, set_elem_item *el | |
node->hcnt[hidx] += 1; | ||
node->tot_elem_cnt += 1; | ||
|
||
for (int i = 0; i < cur_depth-1; i++) { | ||
parents[i]->tot_elem_cnt++; | ||
} | ||
|
||
info->ccnt++; | ||
|
||
if (1) { /* apply memory space */ | ||
|
@@ -396,10 +402,18 @@ static ENGINE_ERROR_CODE do_set_elem_traverse_delete(set_meta_info *info, set_ha | |
set_hash_node *child_node = node->htab[hidx]; | ||
ret = do_set_elem_traverse_delete(info, child_node, hval, val, vlen); | ||
if (ret == ENGINE_SUCCESS) { | ||
if (child_node->tot_hash_cnt == 0 && | ||
child_node->tot_elem_cnt < (SET_MAX_HASHCHAIN_SIZE/2)) { | ||
int64_t sum_of_children = 0; | ||
for (int i = 0; i < SET_HASHTAB_SIZE; i++) { | ||
if (node->hcnt[i] == -1) { | ||
set_hash_node *child = (set_hash_node *)node->htab[i]; | ||
sum_of_children += child->tot_elem_cnt; | ||
} | ||
} | ||
int64_t local_elem_cnt = (int64_t)node->tot_elem_cnt - sum_of_children; | ||
if (child_node->tot_hash_cnt == 0 && local_elem_cnt < (SET_MAX_HASHCHAIN_SIZE/2)) { | ||
do_set_node_unlink(info, node, hidx); | ||
} | ||
node->tot_elem_cnt -= 1; | ||
} | ||
} else { | ||
ret = ENGINE_ELEM_ENOENT; | ||
|
@@ -487,26 +501,43 @@ static uint32_t do_set_elem_traverse_fast(set_meta_info *info, | |
#endif | ||
|
||
static int do_set_elem_traverse_dfs(set_meta_info *info, set_hash_node *node, | ||
const uint32_t count, const bool delete, | ||
set_elem_item **elem_array) | ||
const uint32_t offset, const uint32_t count, const bool delete, | ||
set_elem_item **elem_array, uint32_t *skip_cnt) | ||
{ | ||
int hidx; | ||
int fcnt = 0; /* found count */ | ||
|
||
if (offset && (*skip_cnt) + node->tot_elem_cnt <= offset) { | ||
(*skip_cnt) += node->tot_elem_cnt; | ||
return 0; | ||
} | ||
|
||
if (node->tot_hash_cnt > 0) { | ||
set_hash_node *child_node; | ||
int rcnt; /* request count */ | ||
for (hidx = 0; hidx < SET_HASHTAB_SIZE; hidx++) { | ||
if (node->hcnt[hidx] == -1) { | ||
child_node = (set_hash_node *)node->htab[hidx]; | ||
if (offset && ((*skip_cnt + child_node->tot_elem_cnt) <= offset)) { | ||
(*skip_cnt) += child_node->tot_elem_cnt; | ||
continue; | ||
} | ||
rcnt = (count > 0 ? (count - fcnt) : 0); | ||
fcnt += do_set_elem_traverse_dfs(info, child_node, rcnt, delete, | ||
(elem_array==NULL ? NULL : &elem_array[fcnt])); | ||
fcnt += do_set_elem_traverse_dfs(info, child_node, offset, rcnt, delete, | ||
(elem_array==NULL ? NULL : &elem_array[fcnt]), skip_cnt); | ||
if (delete) { | ||
int sum_of_children = 0; | ||
for (int i = 0; i < SET_HASHTAB_SIZE; i++) { | ||
if (node->hcnt[i] == -1) { | ||
set_hash_node *child = (set_hash_node *)node->htab[i]; | ||
sum_of_children += (int)child->tot_elem_cnt; | ||
} | ||
} | ||
int local_elem_cnt = node->tot_elem_cnt - sum_of_children; | ||
Comment on lines
+529
to
+536
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
offset ์ธ์๋ฅผ ์ง์ ํ๋ ๊ฒฝ์ฐ๋ณด๋ค default ๊ฐ(0)์ผ๋ก ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ ๋ง์ ๊ฒ์ด๋ฏ๋ก, ํ์ฌ PR๊ณผ ๊ฐ์ ๊ตฌํ์ด ์๋๋ฉด offset ๊ธฐ๋ฅ์ด ํฌ๊ฒ ๋นํจ์จ์ ์ผ๋ก ๋์ํ๊ฒ ๋๋์? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ํ์ฌ ๊ตฌํ์ ๋
ธ๋(์๋ธํธ๋ฆฌ) ๋จ์์์๋ ์คํตํ ์ ์๋๋ก ์ด ๋๋ฌธ์ ์ถ๊ฐ ๋ฃจํ ๋น์ฉ์ด ์๊ธฐ๋๋ฐ, ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ์ ์๊ฐ์๋ 2๋ฒ๊ณผ ๊ฐ์ด ๊ตฌํํ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํด ๋ณด์ ๋๋ค. ๋ฌผ๋ก ๋ถ๋ชจ hash_node ์์ค์์ ๊ฑด๋๋ฐ๋ ๊ฒ๋ณด๋ค๋ ๋๋ฆฌ๊ฒ ์ง๋ง, |
||
if (child_node->tot_hash_cnt == 0 && | ||
child_node->tot_elem_cnt < (SET_MAX_HASHCHAIN_SIZE/2)) { | ||
local_elem_cnt < (SET_MAX_HASHCHAIN_SIZE/2)) { | ||
do_set_node_unlink(info, node, hidx); | ||
} | ||
} | ||
} | ||
if (count > 0 && fcnt >= count) | ||
return fcnt; | ||
|
@@ -517,8 +548,17 @@ static int do_set_elem_traverse_dfs(set_meta_info *info, set_hash_node *node, | |
|
||
for (hidx = 0; hidx < SET_HASHTAB_SIZE; hidx++) { | ||
if (node->hcnt[hidx] > 0) { | ||
if (offset && ((*skip_cnt + node->hcnt[hidx]) <= offset)) { | ||
(*skip_cnt) += node->hcnt[hidx]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ์๋์์ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๋ค. ์์ด๋ ๋๋๋ฐ ๊ฐ๋ ์ฑ๊ณผ ํต์ผ์ฑ์ ์ํด์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค. |
||
continue; | ||
} | ||
set_elem_item *elem = node->htab[hidx]; | ||
while (elem != NULL) { | ||
if (offset && (*skip_cnt < offset)) { | ||
*skip_cnt += 1; | ||
elem = (delete ? node->htab[hidx] : elem->next); | ||
continue; | ||
} | ||
if (elem_array) { | ||
elem->refcount++; | ||
elem_array[fcnt] = elem; | ||
|
@@ -561,15 +601,15 @@ static uint32_t do_set_elem_delete(set_meta_info *info, const uint32_t count, | |
assert(cause == ELEM_DELETE_COLL); | ||
uint32_t fcnt = 0; | ||
if (info->root != NULL) { | ||
fcnt = do_set_elem_traverse_dfs(info, info->root, count, true, NULL); | ||
fcnt = do_set_elem_traverse_dfs(info, info->root, 0, count, true, NULL, NULL); | ||
if (info->root->tot_hash_cnt == 0 && info->root->tot_elem_cnt == 0) { | ||
do_set_node_unlink(info, NULL, 0); | ||
} | ||
} | ||
return fcnt; | ||
} | ||
|
||
static uint32_t do_set_elem_get(set_meta_info *info, | ||
static uint32_t do_set_elem_get(set_meta_info *info, const uint32_t offset, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. offset๊ณผ count๋ ๊ฐ์ line์ ์์นํ๋๋ก ํ๋ฉด ์ข๊ฒ ์ต๋๋ค. static uint32_t do_btree_elem_get(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,
btree_elem_item **elem_array,
uint32_t *opcost, bool *potentialbkeytrim) |
||
const uint32_t count, const bool delete, | ||
set_elem_item **elem_array) | ||
{ | ||
|
@@ -579,7 +619,8 @@ static uint32_t do_set_elem_get(set_meta_info *info, | |
if (delete) { | ||
CLOG_ELEM_DELETE_BEGIN((coll_meta_info*)info, count, ELEM_DELETE_NORMAL); | ||
} | ||
fcnt = do_set_elem_traverse_dfs(info, info->root, count, delete, elem_array); | ||
uint32_t skip_cnt = 0; | ||
fcnt = do_set_elem_traverse_dfs(info, info->root, offset, count, delete, elem_array, &skip_cnt); | ||
if (delete && info->root->tot_hash_cnt == 0 && info->root->tot_elem_cnt == 0) { | ||
do_set_node_unlink(info, NULL, 0); | ||
} | ||
|
@@ -792,7 +833,7 @@ ENGINE_ERROR_CODE set_elem_exist(const char *key, const uint32_t nkey, | |
} | ||
|
||
ENGINE_ERROR_CODE set_elem_get(const char *key, const uint32_t nkey, | ||
const uint32_t count, | ||
const uint32_t offset, const uint32_t count, | ||
const bool delete, const bool drop_if_empty, | ||
struct elems_result *eresult, | ||
const void *cookie) | ||
|
@@ -812,7 +853,7 @@ ENGINE_ERROR_CODE set_elem_get(const char *key, const uint32_t nkey, | |
if ((info->mflags & COLL_META_FLAG_READABLE) == 0) { | ||
ret = ENGINE_UNREADABLE; break; | ||
} | ||
if (info->ccnt <= 0) { | ||
if (info->ccnt <= 0 || offset >= info->ccnt) { | ||
ret = ENGINE_ELEM_ENOENT; break; | ||
} | ||
if (count == 0 || info->ccnt < count) { | ||
|
@@ -823,7 +864,7 @@ ENGINE_ERROR_CODE set_elem_get(const char *key, const uint32_t nkey, | |
if (eresult->elem_array == NULL) { | ||
ret = ENGINE_ENOMEM; break; | ||
} | ||
eresult->elem_count = do_set_elem_get(info, count, delete, | ||
eresult->elem_count = do_set_elem_get(info, offset, count, delete, | ||
(set_elem_item**)(eresult->elem_array)); | ||
assert(eresult->elem_count > 0); | ||
if (info->ccnt == 0 && drop_if_empty) { | ||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -5167,7 +5167,7 @@ static void process_bin_sop_get(conn *c) | |||||||||
(req->message.body.delete ? "true" : "false")); | ||||||||||
} | ||||||||||
|
||||||||||
ret = mc_engine.v1->set_elem_get(mc_engine.v0, c, key, nkey, req_count, | ||||||||||
ret = mc_engine.v1->set_elem_get(mc_engine.v0, c, key, nkey, 0, req_count, | ||||||||||
(bool)req->message.body.delete, | ||||||||||
(bool)req->message.body.drop, | ||||||||||
&eresult, c->binary_header.request.vbucket); | ||||||||||
|
@@ -10589,14 +10589,14 @@ out_sop_get_response(conn *c, bool delete, struct elems_result *eresultp) | |||||||||
return ret; | ||||||||||
} | ||||||||||
|
||||||||||
static void process_sop_get(conn *c, char *key, size_t nkey, uint32_t count, | ||||||||||
bool delete, bool drop_if_empty) | ||||||||||
static void process_sop_get(conn *c, char *key, size_t nkey, uint32_t offset, | ||||||||||
uint32_t count, bool delete, bool drop_if_empty) | ||||||||||
{ | ||||||||||
assert(c->ewouldblock == false); | ||||||||||
struct elems_result eresult; | ||||||||||
ENGINE_ERROR_CODE ret; | ||||||||||
|
||||||||||
ret = mc_engine.v1->set_elem_get(mc_engine.v0, c, key, nkey, | ||||||||||
ret = mc_engine.v1->set_elem_get(mc_engine.v0, c, key, nkey, offset, | ||||||||||
count, delete, drop_if_empty, | ||||||||||
&eresult, 0); | ||||||||||
CONN_CHECK_AND_SET_EWOULDBLOCK(ret, c); | ||||||||||
|
@@ -10853,34 +10853,47 @@ static void process_sop_command(conn *c, token_t *tokens, const size_t ntokens) | |||||||||
conn_set_state(c, conn_swallow); | ||||||||||
} | ||||||||||
} | ||||||||||
else if ((ntokens==5 || ntokens==6) && (strcmp(subcommand, "get") == 0)) | ||||||||||
else if ((ntokens >= 5 && ntokens <= 7) && (strcmp(subcommand, "get") == 0)) | ||||||||||
{ | ||||||||||
uint32_t offset = 0; | ||||||||||
uint32_t count = 0; | ||||||||||
bool delete = false; | ||||||||||
bool drop_if_empty = false; | ||||||||||
uint32_t count = 0; | ||||||||||
|
||||||||||
if (! safe_strtoul(tokens[SOP_KEY_TOKEN+1].value, &count)) { | ||||||||||
print_invalid_command(c, tokens, ntokens); | ||||||||||
out_string(c, "CLIENT_ERROR bad command line format"); | ||||||||||
return; | ||||||||||
} | ||||||||||
if (ntokens == 6) { | ||||||||||
if (strcmp(tokens[SOP_KEY_TOKEN+2].value, "delete")==0) { | ||||||||||
delete = true; | ||||||||||
} else if (strcmp(tokens[SOP_KEY_TOKEN+2].value, "drop")==0) { | ||||||||||
int read_ntokens = SOP_KEY_TOKEN + 1; | ||||||||||
int post_ntokens = 1; | ||||||||||
int rest_ntokens = ntokens - read_ntokens - post_ntokens; | ||||||||||
|
||||||||||
if (rest_ntokens > 0) { | ||||||||||
if (strcmp(tokens[read_ntokens+rest_ntokens-1].value, "delete")==0 || | ||||||||||
strcmp(tokens[read_ntokens+rest_ntokens-1].value, "drop")==0) { | ||||||||||
Comment on lines
+10868
to
+10869
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ์์ ํ๋ ๊น์ ์ฝ๋ ์คํ์ผ๋ ํจ๊ป ์ ๋ฆฌํด๋๋ฉด ์ข๊ฒ ์ต๋๋ค.
Suggested change
|
||||||||||
delete = true; | ||||||||||
drop_if_empty = true; | ||||||||||
} else { | ||||||||||
if (strlen(tokens[read_ntokens+rest_ntokens-1].value) == 4) | ||||||||||
drop_if_empty = true; | ||||||||||
rest_ntokens -= 1; | ||||||||||
} | ||||||||||
} | ||||||||||
if (rest_ntokens == 1) { | ||||||||||
if (! safe_strtoul(tokens[read_ntokens].value, &count)) { | ||||||||||
print_invalid_command(c, tokens, ntokens); | ||||||||||
out_string(c, "CLIENT_ERROR bad command line format"); | ||||||||||
return; | ||||||||||
} | ||||||||||
} else if (rest_ntokens == 2) { | ||||||||||
if ((! safe_strtoul(tokens[read_ntokens].value, &offset)) || | ||||||||||
(! safe_strtoul(tokens[read_ntokens+1].value, &count))) { | ||||||||||
print_invalid_command(c, tokens, ntokens); | ||||||||||
out_string(c, "CLIENT_ERROR bad command line format"); | ||||||||||
return; | ||||||||||
} | ||||||||||
} else { | ||||||||||
print_invalid_command(c, tokens, ntokens); | ||||||||||
out_string(c, "CLIENT_ERROR bad command line format"); | ||||||||||
return; | ||||||||||
} | ||||||||||
|
||||||||||
process_sop_get(c, key, nkey, count, delete, drop_if_empty); | ||||||||||
process_sop_get(c, key, nkey, offset, count, delete, drop_if_empty); | ||||||||||
} | ||||||||||
else | ||||||||||
{ | ||||||||||
else { | ||||||||||
print_invalid_command(c, tokens, ntokens); | ||||||||||
out_string(c, "CLIENT_ERROR bad command line format"); | ||||||||||
} | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
100์ ๋ฌด์์ ๊ธฐ์ค์ผ๋ก ํ ํฌ๊ธฐ์ธ๊ฐ์?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ฝ๋์์ ํด์ ํธ๋ฆฌ์ ์ต๋ ๊น์ด์ ๋ํ ์ ๋ณด๊ฐ ์์ด์ ์ ๋นํ ๋๋ํ ๊ฐ์ผ๋ก 100์ ์ค์ ํ์ต๋๋ค.
Collection ํ๋์ ์ต๋ ํฌ๊ธฐ๊ฐ 1,000,000์ผ๋ก ์ค์ ํ ์ ์๋๋ฐ ๊ณ ๋ฅด๊ฒ ๋ถํฌ ๋๋ค๋ ๊ฐ์ ํ์ ํ ๋ ธ๋์ 1024๊ฐ์ element ๊ฐ ์ ์ฅ๋ฉ๋๋ค. ์ด๋, ํ ๋ ธ๋์๋ 16๊ฐ์ bucket์ด ์๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌ์ ๊น์ด๊ฐ 10์ด๋ผ๊ณ ํ ๋ 1024*(16^10) ์ ๋ ์ ์ฅ๋ฉ๋๋ค. ์ด๋ 1,000,000๋ณด๋ค ํจ์ฌ ํฌ๊ธฐ๋ ํ๊ณ worst case๋ฅผ ๊ณ ๋ คํด์ ์ ๋นํ ํฐ ์์ธ depth ๋ฅผ 100์ผ๋ก ์ค์ ํ์ต๋๋ค.
๋ค๋ฅธ ์ฝ๋์์ ํด์ ํธ๋ฆฌ์ ๊น์ด์ ๋ํ ์ ๋ณด๊ฐ ์์ผ๋ฉด ์กฐ์ ํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.