summaryrefslogtreecommitdiff
path: root/src/redis-cli.c
diff options
context:
space:
mode:
authoryoav-steinberg <yoav@monfort.co.il>2022-01-02 09:39:01 +0200
committerGitHub <noreply@github.com>2022-01-02 09:39:01 +0200
commit1bf6d6f11eb08d98ba3de688d18d805a2d8696d5 (patch)
treee808f1f65487fbeae9eeb281b1d33a1fd8baaf63 /src/redis-cli.c
parent888e92eb5797c1a6ce4c7b89c5814dbe13a8d8e3 (diff)
downloadredis-1bf6d6f11eb08d98ba3de688d18d805a2d8696d5.tar.gz
Generate RDB with Functions only via redis-cli --functions-rdb (#9968)
This is needed in order to ease the deployment of functions for ephemeral cases, where user needs to spin up a server with functions pre-loaded. #### Details: * Added `--functions-rdb` option to _redis-cli_. * Functions only rdb via `REPLCONF rdb-filter-only functions`. This is a placeholder for a space separated inclusion filter for the RDB. In the future can be `REPLCONF rdb-filter-only "functions db:3 key-patten:user*"` and a complementing `rdb-filter-exclude` `REPLCONF` can also be added. * Handle "slave requirements" specification to RDB saving code so we can use the same RDB when different slaves express the same requirements (like functions-only) and not share the RDB when their requirements differ. This is currently just a flags `int`, but can be extended to a more complex structure with various filter fields. * make sure to support filters only in diskless replication mode (not to override the persistence file), we do that by forcing diskless (even if disabled by config) other changes: * some refactoring in rdb.c (extract portion of a big function to a sub-function) * rdb_key_save_delay used in AOFRW too * sendChildInfo takes the number of updated keys (incremental, rather than absolute) Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/redis-cli.c')
-rw-r--r--src/redis-cli.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/src/redis-cli.c b/src/redis-cli.c
index 2fb7d9ef0..397e3bfa8 100644
--- a/src/redis-cli.c
+++ b/src/redis-cli.c
@@ -226,6 +226,7 @@ static struct config {
int pipe_mode;
int pipe_timeout;
int getrdb_mode;
+ int get_functions_rdb_mode;
int stat_mode;
int scan_mode;
int intrinsic_latency_mode;
@@ -1643,6 +1644,9 @@ static int parseOptions(int argc, char **argv) {
} else if (!strcmp(argv[i],"--rdb") && !lastarg) {
config.getrdb_mode = 1;
config.rdb_filename = argv[++i];
+ } else if (!strcmp(argv[i],"--functions-rdb") && !lastarg) {
+ config.get_functions_rdb_mode = 1;
+ config.rdb_filename = argv[++i];
} else if (!strcmp(argv[i],"--pipe")) {
config.pipe_mode = 1;
} else if (!strcmp(argv[i],"--pipe-timeout") && !lastarg) {
@@ -1848,6 +1852,11 @@ static int parseOptions(int argc, char **argv) {
" line interface may not be safe.\n", stderr);
}
+ if (config.get_functions_rdb_mode && config.getrdb_mode) {
+ fprintf(stderr,"Option --functions-rdb and --rdb are mutually exclusive.\n");
+ exit(1);
+ }
+
if (config.stdin_lastarg && config.stdin_tag_arg) {
fprintf(stderr, "Options -x and -X are mutually exclusive.\n");
exit(1);
@@ -1949,6 +1958,8 @@ static void usage(int err) {
" --replica Simulate a replica showing commands received from the master.\n"
" --rdb <filename> Transfer an RDB dump from remote server to local file.\n"
" Use filename of \"-\" to write to stdout.\n"
+" --functions-rdb <filename> Like --rdb but only get the functions (not the keys)\n"
+" when getting the RDB dump file.\n"
" --pipe Transfer raw Redis protocol from stdin to server.\n"
" --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.\n"
" no reply is received within <n> seconds.\n"
@@ -7158,7 +7169,8 @@ static void latencyDistMode(void) {
#define RDB_EOF_MARK_SIZE 40
-void sendReplconf(const char* arg1, const char* arg2) {
+int sendReplconf(const char* arg1, const char* arg2) {
+ int res = 1;
fprintf(stderr, "sending REPLCONF %s %s\n", arg1, arg2);
redisReply *reply = redisCommand(context, "REPLCONF %s %s", arg1, arg2);
@@ -7167,10 +7179,12 @@ void sendReplconf(const char* arg1, const char* arg2) {
fprintf(stderr, "\nI/O error\n");
exit(1);
} else if(reply->type == REDIS_REPLY_ERROR) {
- fprintf(stderr, "REPLCONF %s error: %s\n", arg1, reply->str);
/* non fatal, old versions may not support it */
+ fprintf(stderr, "REPLCONF %s error: %s\n", arg1, reply->str);
+ res = 0;
}
freeReplyObject(reply);
+ return res;
}
void sendCapa() {
@@ -8411,6 +8425,7 @@ int main(int argc, char **argv) {
config.cluster_send_asking = 0;
config.slave_mode = 0;
config.getrdb_mode = 0;
+ config.get_functions_rdb_mode = 0;
config.stat_mode = 0;
config.scan_mode = 0;
config.intrinsic_latency_mode = 0;
@@ -8522,11 +8537,15 @@ int main(int argc, char **argv) {
slaveMode();
}
- /* Get RDB mode. */
- if (config.getrdb_mode) {
+ /* Get RDB/functions mode. */
+ if (config.getrdb_mode || config.get_functions_rdb_mode) {
if (cliConnect(0) == REDIS_ERR) exit(1);
sendCapa();
sendRdbOnly();
+ if (config.get_functions_rdb_mode && !sendReplconf("rdb-filter-only", "functions")) {
+ fprintf(stderr, "Failed requesting functions only RDB from server, aborting\n");
+ exit(1);
+ }
getRDB(NULL);
}