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: touch command #778

Closed
wants to merge 8 commits into from
Closed
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
19 changes: 19 additions & 0 deletions docs/ascii-protocol/ch04-command-key-value.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,22 @@ decr <key> <delta> [<flags> <exptime> <initial>] [noreply]\r\n
| "TYPE_MISMATCH" | 해당 아이템이 key-value 타입이 아님
| "CLIENT_ERROR" | 클라이언트에서 잘못된 질의를 했음을 의미. 이어 나오는 문자열을 통해 오류의 원인을 파악 가능. 예) invalid numeric delta argument, cannot increment or decrement non-numeric value
| "SERVER ERROR" | 서버 측의 오류로 연산하지 못했음을 의미. 이어 나오는 문자열을 통해 오류의 원인을 파악 가능. 예) out of memory

## touch (Item의 expiretime 변경)

key에 해당하는 item을 fetch 하지 않고 expiretime을 재설정하는 명령은 아래와 같다. 이 명령은 모든 item 타입에 대해 적용이 가능하다.

```
touch <key> <exptime> [noreply]\r\n
```

- \<key\> - 대상 item의 key string
- \<exptime\> - 재설정할 expiretime 값

이 명령의 response string과 그 의미는 아래와 같다.

| Response String | 설명 |
| ------------------------ | ------------------------------- |
| "TOUCHED" | 성공 |
| "NOT_FOUND" | key miss |
| "CLIENT_ERROR bad value" | exptime 값이 유효하지 않은 경우 |
2 changes: 0 additions & 2 deletions docs/ascii-protocol/ch10-command-item-attribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Item attributes를 조회하는 getattr 명령과 변경하는 setattr 명령을
ARCUS에서 어떤 item attributes를 제공하는 지를 알고자 한다면,
[Item Attibute 설명](ch03-item-attributes.md)을 참고 바란다.


## getattr (Item Attribute 조회)

Item attributes를 조회하는 getattr 명령은 아래와 같다.
Expand Down Expand Up @@ -36,7 +35,6 @@ END\r\n
| "ATTR_ERROR not found" | 인자로 지정한 attribute가 존재하지 않거나 해당 item 유형에서 지원되지 않는 attribute임.
| "CLIENT_ERROR bad command line format" | protocol syntax 틀림


## setattr (Item Attribute 변경)

Item attributes를 변경하는 setattr 명령은 아래와 같다.
Expand Down
51 changes: 51 additions & 0 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -13085,6 +13085,53 @@ static void process_setattr_command(conn *c, token_t *tokens, const size_t ntoke
}
}

static void process_touch_command(conn *c, token_t *tokens, const size_t ntokens)
{
assert(c != NULL);
assert(c->ewouldblock == false);
char *key = tokens[KEY_TOKEN].value;
size_t nkey = tokens[KEY_TOKEN].length;

if (nkey > KEY_MAX_LENGTH) {
out_string(c, "CLIENT_ERROR bad command line format");
ing-eoking marked this conversation as resolved.
Show resolved Hide resolved
return;
ing-eoking marked this conversation as resolved.
Show resolved Hide resolved
}

ENGINE_ERROR_CODE ret;
item_attr attr_data;
ENGINE_ITEM_ATTR attr_id = ATTR_EXPIRETIME;
int64_t exptime;

set_noreply_maybe(c, tokens, ntokens);

if (! safe_strtoll(tokens[KEY_TOKEN+1].value, &exptime)) {
ret = ENGINE_EBADVALUE;
} else {
attr_data.exptime = realtime(exptime);
ret = mc_engine.v1->setattr(mc_engine.v0, c, key, nkey,
&attr_id, 1, &attr_data, 0);
CONN_CHECK_AND_SET_EWOULDBLOCK(ret, c);
if (settings.detail_enabled) {
stats_prefix_record_setattr(key, nkey);
}
}

switch (ret) {
case ENGINE_SUCCESS:
STATS_HITS(c, setattr, key, nkey);
out_string(c, "TOUCHED");
break;
case ENGINE_KEY_ENOENT:
STATS_MISSES(c, setattr, key, nkey);
out_string(c, "NOT_FOUND");
break;
default:
STATS_CMD_NOKEY(c, setattr);
if (ret == ENGINE_EBADVALUE) out_string(c, "CLIENT_ERROR bad value");
else handle_unexpected_errorcode_ascii(c, __func__, ret);
}
}

static void process_command_ascii(conn *c, char *command, int cmdlen)
{
/* One more token is reserved in tokens strucure
Expand Down Expand Up @@ -13206,6 +13253,10 @@ static void process_command_ascii(conn *c, char *command, int cmdlen)
{
process_config_command(c, tokens, ntokens);
}
else if ((ntokens >= 4 && ntokens <= 5) && (strcmp(tokens[COMMAND_TOKEN].value, "touch") == 0))
{
process_touch_command(c, tokens, ntokens);
}
#ifdef ENABLE_ZK_INTEGRATION
else if ((ntokens >= 3) && (strcmp(tokens[COMMAND_TOKEN].value, "zkensemble") == 0))
{
Expand Down
1 change: 1 addition & 0 deletions t/tlist/engine_default_b.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,4 @@
./t/nested_prefix.t
./t/keyscan.t
./t/prefixscan.t
./t/touch.t
1 change: 1 addition & 0 deletions t/tlist/engine_default_s.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,4 @@
./t/nested_prefix.t
./t/keyscan.t
./t/prefixscan.t
./t/touch.t
81 changes: 81 additions & 0 deletions t/touch.t
ing-eoking marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/perl

use strict;
use Test::More tests =>19;
use FindBin qw($Bin);
use lib "$Bin/lib";
use MemcachedTest;

my $engine = shift;
my $server = get_memcached($engine);
my $sock = $server->sock;

my $cmd;
my $val;
my $rst;
my $expire;

# Initialize
$cmd = "set key 0 0 5"; $val = "datum"; $rst = "STORED";
mem_cmd_is($sock, $cmd, $val, $rst);
$cmd = "lop create lkey 0 0 1 error"; $rst = "CREATED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "sop create skey 0 0 1 error"; $rst = "CREATED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "mop create mkey 0 0 1 error"; $rst = "CREATED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "bop create bkey 0 0 1 error"; $rst = "CREATED";
mem_cmd_is($sock, $cmd, "", $rst);

# Success Cases
# key value
$cmd = "touch key 1"; $rst = "TOUCHED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "getattr key expiretime";
$rst = "ATTR expiretime=1\n"
. "END";
mem_cmd_is($sock, $cmd, "", $rst);
# list
$cmd = "touch lkey 1"; $rst = "TOUCHED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "getattr lkey expiretime";
$rst = "ATTR expiretime=1\n"
. "END";
mem_cmd_is($sock, $cmd, "", $rst);
# set
$cmd = "touch skey 1"; $rst = "TOUCHED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "getattr skey expiretime";
$rst = "ATTR expiretime=1\n"
. "END";
mem_cmd_is($sock, $cmd, "", $rst);
# map
$cmd = "touch mkey 1"; $rst = "TOUCHED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "getattr mkey expiretime";
$rst = "ATTR expiretime=1\n"
. "END";
mem_cmd_is($sock, $cmd, "", $rst);
#btree
$cmd = "touch bkey 1"; $rst = "TOUCHED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "getattr bkey expiretime";
$rst = "ATTR expiretime=1\n"
. "END";
mem_cmd_is($sock, $cmd, "", $rst);

# Fail Cases
# bad value
$cmd = "set key 0 0 5"; $val = "datum"; $rst = "STORED";
mem_cmd_is($sock, $cmd, $val, $rst);
$cmd = "touch key str"; $rst = "CLIENT_ERROR bad value";
mem_cmd_is($sock, $cmd, "", $rst);
# not exist key
$expire = time() - 1;
$cmd = "touch key $expire"; $rst = "TOUCHED";
mem_cmd_is($sock, $cmd, "", $rst);
$cmd = "touch key 1"; $rst = "NOT_FOUND";
mem_cmd_is($sock, $cmd, "", $rst);

# after test
release_memcached($engine, $server);
Loading