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 touch command #782

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
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 값이 μœ νš¨ν•˜μ§€ μ•Šμ€ 경우 |
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");
return;
}

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
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