diff --git a/src/config.c b/src/config.c index bfbe408a652..7910eb98d97 100644 --- a/src/config.c +++ b/src/config.c @@ -163,6 +163,12 @@ configEnum swap_info_supported_enum[] = { {NULL, 0} }; +configEnum swap_info_propagate_mode_enum[] = { + {"ping", SWAP_INFO_PROPAGATE_BY_PING}, + {"swap.info", SWAP_INFO_PROPAGATE_BY_SWAP_INFO}, + {NULL, 0} +}; + /* Output buffer limits presets. */ clientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT] = { {0, 0, 0}, /* normal */ @@ -2947,6 +2953,7 @@ standardConfig configs[] = { createEnumConfig("swap-cuckoo-filter-bit-per-key", NULL, IMMUTABLE_CONFIG, cuckoo_filter_bit_type_enum, server.swap_cuckoo_filter_bit_type, CUCKOO_FILTER_BITS_PER_TAG_8, NULL, NULL), createEnumConfig("swap-ratelimit-policy", NULL, MODIFIABLE_CONFIG, swap_ratelimit_policy_enum, server.swap_ratelimit_policy, SWAP_RATELIMIT_POLICY_PAUSE, NULL, NULL), createEnumConfig("swap-swap-info-supported", NULL, MODIFIABLE_CONFIG, swap_info_supported_enum, server.swap_swap_info_supported, SWAP_INFO_SUPPORTED_AUTO, NULL, NULL), + createEnumConfig("swap-swap-info-propagate-mode", NULL, MODIFIABLE_CONFIG, swap_info_propagate_mode_enum, server.swap_swap_info_propagate_mode, SWAP_INFO_PROPAGATE_BY_PING, NULL, NULL), /* Integer configs */ createIntConfig("databases", NULL, IMMUTABLE_CONFIG, 1, INT_MAX, server.dbnum, 16, INTEGER_CONFIG, NULL, NULL), diff --git a/src/ctrip_swap.c b/src/ctrip_swap.c index 58a24a3c96d..201ad5a6c2d 100644 --- a/src/ctrip_swap.c +++ b/src/ctrip_swap.c @@ -788,6 +788,7 @@ int swapTest(int argc, char **argv, int accurate) { result += swapRordbTest(argc, argv, accurate); result += swapDataBitmapTest(argc, argv, accurate); result += wtdigestTest(argc, argv, accurate); + result += swapReplTest(argc, argv, accurate); return result; } #endif diff --git a/src/ctrip_swap.h b/src/ctrip_swap.h index 5d2e2ca3fb5..592525f8a68 100644 --- a/src/ctrip_swap.h +++ b/src/ctrip_swap.h @@ -1994,10 +1994,18 @@ sds genSwapTtlCompactInfoString(sds info); void swapInfoCommand(client *c); +/* swap info propagate mode */ +#define SWAP_INFO_PROPAGATE_BY_PING 0 +#define SWAP_INFO_PROPAGATE_BY_SWAP_INFO 1 + void swapBuildSwapInfoSstAgeLimitCmd(robj *argv[3], long long sst_age_limit); void swapDestorySwapInfoSstAgeLimitCmd(robj *argv[3]); -void swapPropagateSwapInfo(int argc, robj **argv); +void swapPropagateSwapInfoCmd(int argc, robj **argv); + +sds swapEncodeSwapInfo(int swap_info_argc, sds *swap_info_argv); +sds *swapDecodeSwapInfo(sds argv, int *swap_info_argc); +void swapApplySwapInfo(int swap_info_argc, sds *swap_info_argv); /* Repl */ int submitReplClientRequests(client *c); @@ -2717,6 +2725,7 @@ int swapRordbTest(int argc, char *argv[], int accurate); int roaringBitmapTest(int argc, char *argv[], int accurate); int swapDataBitmapTest(int argc, char **argv, int accurate); int wtdigestTest(int argc, char **argv, int accurate); +int swapReplTest(int argc, char **argv, int accurate); int swapTest(int argc, char **argv, int accurate); diff --git a/src/ctrip_swap_cmd.c b/src/ctrip_swap_cmd.c index 5d74fa3e99f..fffeb4438ed 100644 --- a/src/ctrip_swap_cmd.c +++ b/src/ctrip_swap_cmd.c @@ -1313,15 +1313,13 @@ void swapInfoCommand(client *c) { NULL}; addReplyHelp(c, help); return; - } else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr,"SST-AGE-LIMIT")) { - /* SWAP.INFO SST-AGE-LIMIT */ - long long sst_age_limit = 0; - int res = isObjectRepresentableAsLongLong(c->argv[2], &sst_age_limit); - if (res == C_OK) { - server.swap_ttl_compact_ctx->expire_stats->sst_age_limit = sst_age_limit; + } else { + sds *swap_info_argv = (sds*)zmalloc(sizeof(sds)*c->argc); + for (int i = 0; i < c->argc; i++) { + swap_info_argv[i] = c->argv[i]->ptr; } - addReply(c,shared.ok); - return; + swapApplySwapInfo(c->argc, swap_info_argv); + zfree(swap_info_argv); } addReply(c,shared.ok); diff --git a/src/ctrip_swap_repl.c b/src/ctrip_swap_repl.c index 44ba38b148c..65777facde5 100644 --- a/src/ctrip_swap_repl.c +++ b/src/ctrip_swap_repl.c @@ -415,36 +415,106 @@ bool isSwapInfoSupported(void) { return true; } -/* SWAP.INFO SST-AGE-LIMIT */ +/* The swap.info command, propagate system info to slave. + * SWAP.INFO [ [value] [opt] ...] + * + * subcommand supported: + * SWAP.INFO SST-AGE-LIMIT */ void swapBuildSwapInfoSstAgeLimitCmd(robj *argv[3], long long sst_age_limit) { - argv[0] = shared.swap_info; argv[1] = shared.sst_age_limit; - argv[2] = createStringObjectFromLongLong(sst_age_limit); + argv[2] = createObject(OBJ_STRING, sdsfromlonglong(sst_age_limit)); } void swapDestorySwapInfoSstAgeLimitCmd(robj *argv[3]) { decrRefCount(argv[2]); } -/* The swap.info command, propagate system info to slave. - * SWAP.INFO [ [value] [opt] ...] - * - * subcommand supported: - * SWAP.INFO SST-AGE-LIMIT */ -void swapPropagateSwapInfo(int argc, robj **argv) { +void swapPropagateSwapInfoCmd(int argc, robj **argv) { + + if (server.swap_swap_info_propagate_mode == SWAP_INFO_PROPAGATE_BY_SWAP_INFO) { + if (!isSwapInfoSupported()) return; + replicationFeedSlaves(server.slaves, 0, argv, argc); + return; + } + + /* SWAP_INFO_PROPAGATE_BY_PING */ + sds *argv_str = zmalloc(sizeof(sds) * argc); + for (int i = 0; i < argc; i++) { + argv_str[i] = argv[i]->ptr; + } + + sds ping_argv_str = swapEncodeSwapInfo(argc, argv_str); + + robj *ping_argv[2]; + ping_argv[0] = shared.ping; + ping_argv[1] = createObject(OBJ_STRING, ping_argv_str); + + replicationFeedSlaves(server.slaves,0,ping_argv,2); + decrRefCount(ping_argv[1]); + zfree(argv_str); + return; +} - if (!isSwapInfoSupported()) return; +sds swapEncodeSwapInfo(int swap_info_argc, sds *swap_info_argv) { + return sdsjoinsds(swap_info_argv, swap_info_argc, " ", 1); +} + +sds *swapDecodeSwapInfo(sds argv, int *swap_info_argc) { + return sdssplitlen(argv, sdslen(argv), " ", 1, swap_info_argc); +} - if (argc < 2) { +void swapApplySwapInfo(int swap_info_argc, sds *swap_info_argv) { + + if (strcasecmp(swap_info_argv[0],"swap.info")) { return; - } else if (argc == 3 && !strcasecmp(argv[1]->ptr,"SST-AGE-LIMIT")) { + } + + if (swap_info_argc == 3 && !strcasecmp(swap_info_argv[1],"SST-AGE-LIMIT")) { /* SWAP.INFO SST-AGE-LIMIT */ - goto propagate; + long long sst_age_limit = 0; + if (isSdsRepresentableAsLongLong(swap_info_argv[2],&sst_age_limit) == C_OK) { + server.swap_ttl_compact_ctx->expire_stats->sst_age_limit = sst_age_limit; + } + return; } - return; +} -propagate: - replicationFeedSlaves(server.slaves,0,argv,argc); - return; +#ifdef REDIS_TEST + +int swapReplTest(int argc, char *argv[], int accurate) { + UNUSED(argc); + UNUSED(argv); + UNUSED(accurate); + + int error = 0; + + TEST("swap info: sst-limit-age encode decode") { + sds *swap_info_argv = zmalloc(sizeof(sds) * 3); + swap_info_argv[0] = sdsnew("SWAP.INFO"); + swap_info_argv[1] = sdsnew("SST-AGE-LIMIT"); + swap_info_argv[2] = sdsfromlonglong(1111); + sds swap_info = swapEncodeSwapInfo(3, swap_info_argv); + + int argc = 0; + sds *argv = swapDecodeSwapInfo(swap_info, &argc); + + test_assert(argc == 3); + test_assert(!sdscmp(argv[2], swap_info_argv[2])); + test_assert(!sdscmp(argv[1], swap_info_argv[1])); + test_assert(!sdscmp(argv[0], swap_info_argv[0])); + + sdsfree(swap_info_argv[0]); + sdsfree(swap_info_argv[1]); + sdsfree(swap_info_argv[2]); + zfree(swap_info_argv); + + sdsfree(swap_info); + + sdsfreesplitres(argv, argc); + } + + return error; } + +#endif diff --git a/src/server.c b/src/server.c index 779d0a9a58e..1c5285da4a2 100644 --- a/src/server.c +++ b/src/server.c @@ -2488,9 +2488,10 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { if (server.swap_ttl_compact_enabled) { robj *argv[3]; swapBuildSwapInfoSstAgeLimitCmd(argv, server.swap_ttl_compact_ctx->expire_stats->sst_age_limit); - swapPropagateSwapInfo(3, argv); + swapPropagateSwapInfoCmd(3, argv); swapDestorySwapInfoSstAgeLimitCmd(argv); } + } /* Fire the cron loop modules event. */ @@ -4900,10 +4901,19 @@ void pingCommand(client *c) { else addReplyBulk(c,c->argv[1]); } else { - if (c->argc == 1) + if (c->argc == 1) { addReply(c,shared.pong); - else + } else { + /* extend ping argv for swap.info */ + if (!strncasecmp(c->argv[1]->ptr, "swap.info", 9)) { + int swap_info_argc = 0; + sds *swap_info_argv = swapDecodeSwapInfo(c->argv[1]->ptr, &swap_info_argc); + swapApplySwapInfo(swap_info_argc, swap_info_argv); + sdsfreesplitres(swap_info_argv, swap_info_argc); + } + addReplyBulk(c,c->argv[1]); + } } } diff --git a/src/server.h b/src/server.h index 57ff3466010..7e1733a1ec8 100644 --- a/src/server.h +++ b/src/server.h @@ -2010,6 +2010,7 @@ struct redisServer { /* for swap.info command, which propagate system info to replica */ int swap_swap_info_supported; + int swap_swap_info_propagate_mode; unsigned long long swap_swap_info_slave_period; /* Master send cmd swap.info to the slave every N seconds */ }; diff --git a/tests/swap/unit/swap_info.tcl b/tests/swap/unit/swap_info.tcl index 0efa7236a90..5d51470c658 100644 --- a/tests/swap/unit/swap_info.tcl +++ b/tests/swap/unit/swap_info.tcl @@ -1,4 +1,4 @@ -start_server {tags {"swap.info"}} { +start_server {tags {"swap.info"} overrides {swap-swap-info-propagate-mode {swap.info} }} { test "SST-AGE-LIMIT" { r swap.info SST-AGE-LIMIT 1111 set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] @@ -19,4 +19,45 @@ start_server {tags {"swap.info"}} { assert_equal OK [r swap.info SST-AGE-LIMIT 50 50] assert_equal OK [r swap.info SST-AGE-LIMIT 50 50 50 err] } +} + +start_server {tags {"swap.info"} overrides {swap-swap-info-propagate-mode {ping} }} { + test "SST-AGE-LIMIT with ping" { + r ping "swap.info SST-AGE-LIMIT 1111" + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit 1111 + + r ping "swap.info SST-AGE-LIMIT 0" + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit 0 + + r ping "swap.info SST-AGE-LIMIT -2222" + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit -2222 + } + + test "no error for illegal ping argv of swap.info" { + + r ping "swap.info SST-AGE-LIMIT 666" + + assert_equal "swap.info SST-AGE 111" [r ping "swap.info SST-AGE 111"] + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit 666 + + assert_equal "swap.info SST-AGE" [r ping "swap.info SST-AGE"] + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit 666 + + assert_equal "swap.info" [r ping "swap.info"] + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit 666 + + assert_equal "swap.info ss ss ss ss" [r ping "swap.info ss ss ss ss"] + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit 666 + + assert_equal "swap.info " [r ping "swap.info "] + set sst_age_limit [get_info_property r Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit 666 + } } \ No newline at end of file diff --git a/tests/swap/unit/ttl_compact.tcl b/tests/swap/unit/ttl_compact.tcl index ddf4ba8f49c..dc8cc2495fd 100644 --- a/tests/swap/unit/ttl_compact.tcl +++ b/tests/swap/unit/ttl_compact.tcl @@ -264,7 +264,8 @@ start_server {tags {"ttl-compact master propagate"} overrides {save ""}} { start_server {overrides {swap-repl-rordb-sync {no} swap-debug-evict-keys {0} - swap-ttl-compact-enabled {no} }} { + swap-ttl-compact-enabled {no} + swap-swap-info-propagate-mode {ping} }} { set master_host [srv 0 host] set master_port [srv 0 port] @@ -312,6 +313,14 @@ start_server {tags {"ttl-compact master propagate"} overrides {save ""}} { set sst_age_limit2 [get_info_property $slave Swap swap_ttl_compact sst_age_limit] assert_equal $sst_age_limit1 $sst_age_limit2 + + $master config set swap-swap-info-propagate-mode swap.info + $master swap.info SST-AGE-LIMIT 2222 + + after 1200 + + set sst_age_limit2 [get_info_property $slave Swap swap_ttl_compact sst_age_limit] + assert_equal $sst_age_limit2 2222 } } }