Skip to content
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

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 56 additions & 15 deletions engines/default/coll_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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];
Copy link
Collaborator

Choose a reason for hiding this comment

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

100์€ ๋ฌด์—‡์„ ๊ธฐ์ค€์œผ๋กœ ํ•œ ํฌ๊ธฐ์ธ๊ฐ€์š”?

Copy link
Author

@jeesup0103 jeesup0103 Dec 30, 2024

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์œผ๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
๋‹ค๋ฅธ ์ฝ”๋“œ์—์„œ ํ•ด์‹œ ํŠธ๋ฆฌ์˜ ๊นŠ์ด์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉด ์กฐ์ • ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

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

tot_elem_cnt์˜ ์˜๋ฏธ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด์„œ ์ด์ „์— ์—†๋˜ loop๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

offset ์ธ์ž๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒฝ์šฐ๋ณด๋‹ค default ๊ฐ’(0)์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ์„ ๊ฒƒ์ด๋ฏ€๋กœ,
offset ๊ธฐ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๊ตฌํ˜„์—์„œ ์ถ”๊ฐ€ ๋น„์šฉ์„ ์ง€๋ถˆํ•˜๋Š” ํ˜•ํƒœ๋Š” ํ”ผํ–ˆ์œผ๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ PR๊ณผ ๊ฐ™์€ ๊ตฌํ˜„์ด ์•„๋‹ˆ๋ฉด offset ๊ธฐ๋Šฅ์ด ํฌ๊ฒŒ ๋น„ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋‚˜์š”?

Copy link
Author

Choose a reason for hiding this comment

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

ํ˜„์žฌ ๊ตฌํ˜„์€ ๋…ธ๋“œ(์„œ๋ธŒํŠธ๋ฆฌ) ๋‹จ์œ„์—์„œ๋„ ์Šคํ‚ตํ•  ์ˆ˜ ์žˆ๋„๋ก tot_elem_cnt์˜ ์˜๋ฏธ๋ฅผ โ€œ์„œ๋ธŒํŠธ๋ฆฌ element ์ „์ฒด ๊ฐœ์ˆ˜โ€๋กœ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ์œ„์™€ ๊ฐ™์ด ํ˜„์žฌ ๋…ธ๋“œ์˜ element ๊ฐœ์ˆ˜๋ฅผ ์•Œ์•„์•ผ ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋•Œ๋ฌธ์— ์ถ”๊ฐ€ ๋ฃจํ”„ ๋น„์šฉ์ด ์ƒ๊ธฐ๋Š”๋ฐ, ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  1. tot_elem_cnt๋ฅผ ์›๋ž˜๋Œ€๋กœ ๋‘๊ณ , ์ƒˆ ๋ณ€์ˆ˜ tree_elem_cnt๋ฅผ ๋งŒ๋“ค์–ด ์„œ๋ธŒํŠธ๋ฆฌ element ๊ฐœ์ˆ˜๋ฅผ ๊ด€๋ฆฌ
    • ์žฅ์ : ๋…ธ๋“œ(์„œ๋ธŒํŠธ๋ฆฌ) ๋‹จ์œ„ ์Šคํ‚ต ๊ฐ€๋Šฅ
    • ๋‹จ์ : ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜ ๊ด€๋ฆฌ
  2. ๋…ธ๋“œ ๋‹จ์œ„ ์Šคํ‚ต์„ ํ•˜์ง€ ์•Š๊ณ  ํ•ด์‹œ ๋ฒ„ํ‚ท(์ฒด์ธ) ๋‹จ์œ„์—์„œ๋งŒ ์Šคํ‚ต (tot_elem_cnt๋ฅผ ๊ทธ๋Œ€๋กœ ์œ ์ง€)
    • ์žฅ์ : ์ถ”๊ฐ€ ๋ณ€์ˆ˜ ์—†์Œ
    • ๋‹จ์ : offset ํƒ์ƒ‰์ด ๋Š๋ ค์ง

Copy link
Collaborator

Choose a reason for hiding this comment

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

์ œ ์ƒ๊ฐ์—๋Š” 2๋ฒˆ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

๋ฌผ๋ก  ๋ถ€๋ชจ hash_node ์ˆ˜์ค€์—์„œ ๊ฑด๋„ˆ๋›ฐ๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ๋Š๋ฆฌ๊ฒ ์ง€๋งŒ,
์ตœ์†Œํ•œ ๊ธฐ์กด์— ๋ชจ๋“  ๋…ธ๋“œ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•  ๊ฒƒ์ด๊ณ ,
์•„๋งˆ 2๋ฒˆ ๋ฐฉ์‹์—์„œ๋Š” ๊ธฐ์กด ๋กœ์ง์„ ๊ฑฐ์˜ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ตœ์†Œํ•œ์˜ ์ˆ˜์ •์œผ๋กœ offset ๊ธฐ๋Šฅ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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;
Expand All @@ -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];
Copy link
Collaborator

Choose a reason for hiding this comment

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

์•„๋ž˜์—์„œ *skip_cnt += 1; ํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์—ฌ๊ธฐ์„œ๋„ ๊ด„ํ˜ธ ์—†์–ด๋„ ๋˜์ฃ ?

Copy link
Author

Choose a reason for hiding this comment

The 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;
Expand Down Expand Up @@ -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,
Copy link
Collaborator

Choose a reason for hiding this comment

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

offset๊ณผ count๋Š” ๊ฐ™์€ line์— ์œ„์น˜ํ•˜๋„๋ก ํ•˜๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.
btree ์ฐธ๊ณ  ๋ฐ”๋ž๋‹ˆ๋‹ค.

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)
{
Expand All @@ -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);
}
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion engines/default/coll_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ ENGINE_ERROR_CODE set_elem_exist(const char *key, const uint32_t nkey,
bool *exist);

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);
Expand Down
4 changes: 2 additions & 2 deletions engines/default/default_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ default_set_elem_exist(ENGINE_HANDLE* handle, const void* cookie,
static ENGINE_ERROR_CODE
default_set_elem_get(ENGINE_HANDLE* handle, const void* cookie,
const void* key, const int 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, uint16_t vbucket)
{
Expand All @@ -674,7 +674,7 @@ default_set_elem_get(ENGINE_HANDLE* handle, const void* cookie,

if (delete) ACTION_BEFORE_WRITE(cookie, key, nkey);
else ACTION_BEFORE_READ(cookie, key, nkey);
ret = set_elem_get(key, nkey, count, delete, drop_if_empty,
ret = set_elem_get(key, nkey, offset, count, delete, drop_if_empty,
eresult, cookie);
if (delete) ACTION_AFTER_WRITE(cookie, engine, ret);
return ret;
Expand Down
2 changes: 1 addition & 1 deletion engines/demo/demo_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ Demo_set_elem_exist(ENGINE_HANDLE* handle, const void* cookie,
static ENGINE_ERROR_CODE
Demo_set_elem_get(ENGINE_HANDLE* handle, const void* cookie,
const void* key, const int 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, uint16_t vbucket)
{
Expand Down
2 changes: 1 addition & 1 deletion include/memcached/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ extern "C" {

ENGINE_ERROR_CODE (*set_elem_get)(ENGINE_HANDLE* handle, const void* cookie,
const void* key, const int 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, uint16_t vbucket);

Expand Down
55 changes: 34 additions & 21 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

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

์ˆ˜์ •ํ•˜๋Š” ๊น€์— ์ฝ”๋“œ ์Šคํƒ€์ผ๋„ ํ•จ๊ป˜ ์ •๋ฆฌํ•ด๋‘๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

Suggested change
if (strcmp(tokens[read_ntokens+rest_ntokens-1].value, "delete")==0 ||
strcmp(tokens[read_ntokens+rest_ntokens-1].value, "drop")==0) {
if (strcmp(tokens[read_ntokens+rest_ntokens-1].value, "delete") == 0 ||
strcmp(tokens[read_ntokens+rest_ntokens-1].value, "drop") == 0) {

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");
}
Expand Down