3333#include "config.h"
3434#include "memcached.h"
3535#include "memcached/extension_loggers.h"
36+ #include "engines/default/item_base.h"
3637#ifdef ENABLE_ZK_INTEGRATION
3738#include "arcus_zk.h"
3839#include "arcus_hb.h"
@@ -2977,7 +2978,7 @@ static char *get_suffix_buffer(conn *c)
29772978}
29782979
29792980static ENGINE_ERROR_CODE
2980- process_get_single(conn *c, char *key, size_t nkey, bool return_cas)
2981+ process_get_single(conn *c, char *key, size_t nkey, bool return_cas, bool* coll )
29812982{
29822983 item *it;
29832984 char *cas_val = NULL;
@@ -2988,6 +2989,9 @@ process_get_single(conn *c, char *key, size_t nkey, bool return_cas)
29882989 if (ret != ENGINE_SUCCESS) {
29892990 it = NULL;
29902991 }
2992+ if (ret == ENGINE_EBADTYPE) {
2993+ *coll = true;
2994+ }
29912995 if (settings.detail_enabled) {
29922996 stats_prefix_record_get(key, nkey, (it != NULL));
29932997 }
@@ -3070,6 +3074,7 @@ static void process_mget_complete(conn *c, bool return_cas)
30703074
30713075 ENGINE_ERROR_CODE ret = ENGINE_SUCCESS;
30723076 token_t *key_tokens;
3077+ bool coll = false;
30733078
30743079 do {
30753080 key_tokens = (token_t*)token_buff_get(&c->thread->token_buff, c->coll_numkeys);
@@ -3087,7 +3092,7 @@ static void process_mget_complete(conn *c, bool return_cas)
30873092 /* do get operation for each key */
30883093 for (int k = 0; k < c->coll_numkeys; k++) {
30893094 ret = process_get_single(c, key_tokens[k].value, key_tokens[k].length,
3090- return_cas);
3095+ return_cas, &coll );
30913096 if (ret != ENGINE_SUCCESS) {
30923097 break; /* ret == ENGINE_ENOMEM*/
30933098 }
@@ -8345,11 +8350,23 @@ static void process_stats_command(conn *c, token_t *tokens, const size_t ntokens
83458350}
83468351
83478352/* ntokens is overwritten here... shrug.. */
8348- static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, bool return_cas)
8353+ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, bool return_cas, bool should_touch )
83498354{
83508355 assert(c != NULL);
8356+
83518357 token_t *key_token = &tokens[KEY_TOKEN];
83528358 ENGINE_ERROR_CODE ret = ENGINE_SUCCESS;
8359+ int64_t exptime = 0;
8360+ bool coll = false;
8361+
8362+ if (should_touch) {
8363+ // For get and touch commands, use first token as exptime
8364+ if (!safe_strtoll(tokens[1].value, &exptime)) {
8365+ out_string(c, "CLIENT_ERROR invalid exptime argument");
8366+ return;
8367+ }
8368+ key_token++;
8369+ }
83538370
83548371 do {
83558372 while (key_token->length != 0) {
@@ -8358,10 +8375,38 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
83588375 }
83598376 /* do get operation for each key */
83608377 ret = process_get_single(c, key_token->value, key_token->length,
8361- return_cas);
8378+ return_cas, &coll );
83628379 if (ret != ENGINE_SUCCESS) {
83638380 break; /* ret == ENGINE_ENOMEM */
83648381 }
8382+
8383+ if (should_touch && !coll) {
8384+ ENGINE_ITEM_ATTR attr_id = ATTR_EXPIRETIME;
8385+ ENGINE_ERROR_CODE gat_ret = ENGINE_SUCCESS;
8386+ item_attr attr_data;
8387+
8388+ attr_data.exptime = realtime(exptime);
8389+ gat_ret = mc_engine.v1->setattr(mc_engine.v0, c, key_token->value, key_token->length,
8390+ &attr_id, 1, &attr_data, 0);
8391+ CONN_CHECK_AND_SET_EWOULDBLOCK(gat_ret, c);
8392+ if (settings.detail_enabled) {
8393+ stats_prefix_record_setattr(key_token->value, key_token->length);
8394+ }
8395+
8396+ if (gat_ret == ENGINE_KEY_ENOENT) {
8397+ STATS_MISSES(c, setattr, key_token->value, key_token->length);
8398+ out_string(c, "CLIENT_ERROR key not found");
8399+ return;
8400+ } else if (gat_ret == ENGINE_EBADVALUE) {
8401+ STATS_CMD_NOKEY(c, setattr);
8402+ out_string(c, "CLIENT_ERROR bad value");
8403+ return;
8404+ } else if (gat_ret != ENGINE_SUCCESS) {
8405+ STATS_CMD_NOKEY(c, setattr);
8406+ handle_unexpected_errorcode_ascii(c, __func__, gat_ret);
8407+ return;
8408+ }
8409+ }
83658410 key_token++;
83668411 }
83678412 if (ret != ENGINE_SUCCESS) break;
@@ -13124,11 +13169,19 @@ static void process_command_ascii(conn *c, char *command, int cmdlen)
1312413169
1312513170 if ((ntokens >= 3) && (strcmp(tokens[COMMAND_TOKEN].value, "get") == 0))
1312613171 {
13127- process_get_command(c, tokens, ntokens, false);
13172+ process_get_command(c, tokens, ntokens, false, false );
1312813173 }
1312913174 else if ((ntokens >= 3) && (strcmp(tokens[COMMAND_TOKEN].value, "gets") == 0))
1313013175 {
13131- process_get_command(c, tokens, ntokens, true);
13176+ process_get_command(c, tokens, ntokens, true, false);
13177+ }
13178+ else if ((ntokens >= 3) && (strcmp(tokens[COMMAND_TOKEN].value, "gat") == 0))
13179+ {
13180+ process_get_command(c, tokens, ntokens, false, true);
13181+ }
13182+ else if ((ntokens >= 3) && (strcmp(tokens[COMMAND_TOKEN].value, "gats") == 0))
13183+ {
13184+ process_get_command(c, tokens, ntokens, true, true);
1313213185 }
1313313186 else if ((ntokens == 4) && (strcmp(tokens[COMMAND_TOKEN].value, "mget") == 0))
1313413187 {
0 commit comments