redis-cli: introduced --pipe-timeout.

When in --pipe mode, after all the data transfer to the server is
complete, now redis-cli waits at max the specified amount of
seconds (30 by default, use 0 to wait forever) without receiving any
reply at all from the server. After this time limit the operation is
aborted with an error.

That's related to issue #681.
This commit is contained in:
antirez 2013-07-03 12:18:55 +02:00
parent fbb97c6b13
commit 1135e9faa2

View File

@ -58,6 +58,7 @@
#define OUTPUT_RAW 1 #define OUTPUT_RAW 1
#define OUTPUT_CSV 2 #define OUTPUT_CSV 2
#define REDIS_CLI_KEEPALIVE_INTERVAL 15 /* seconds */ #define REDIS_CLI_KEEPALIVE_INTERVAL 15 /* seconds */
#define REDIS_DEFAULT_PIPE_TIMEOUT 30 /* seconds */
static redisContext *context; static redisContext *context;
static struct config { static struct config {
@ -77,6 +78,7 @@ static struct config {
int cluster_reissue_command; int cluster_reissue_command;
int slave_mode; int slave_mode;
int pipe_mode; int pipe_mode;
int pipe_timeout;
int getrdb_mode; int getrdb_mode;
int stat_mode; int stat_mode;
char *rdb_filename; char *rdb_filename;
@ -714,6 +716,8 @@ static int parseOptions(int argc, char **argv) {
config.rdb_filename = argv[++i]; config.rdb_filename = argv[++i];
} else if (!strcmp(argv[i],"--pipe")) { } else if (!strcmp(argv[i],"--pipe")) {
config.pipe_mode = 1; config.pipe_mode = 1;
} else if (!strcmp(argv[i],"--pipe-timeout") && !lastarg) {
config.pipe_timeout = atoi(argv[++i]);
} else if (!strcmp(argv[i],"--bigkeys")) { } else if (!strcmp(argv[i],"--bigkeys")) {
config.bigkeys = 1; config.bigkeys = 1;
} else if (!strcmp(argv[i],"--eval") && !lastarg) { } else if (!strcmp(argv[i],"--eval") && !lastarg) {
@ -785,6 +789,9 @@ static void usage() {
" --slave Simulate a slave showing commands received from the master\n" " --slave Simulate a slave showing commands received from the master\n"
" --rdb <filename> Transfer an RDB dump from remote server to local file.\n" " --rdb <filename> Transfer an RDB dump from remote server to local file.\n"
" --pipe Transfer raw Redis protocol from stdin to server\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"
" Default timeout: %d. Use 0 to wait forever.\n"
" --bigkeys Sample Redis keys looking for big keys\n" " --bigkeys Sample Redis keys looking for big keys\n"
" --eval <file> Send an EVAL command using the Lua script at <file>\n" " --eval <file> Send an EVAL command using the Lua script at <file>\n"
" --help Output this help and exit\n" " --help Output this help and exit\n"
@ -801,7 +808,7 @@ static void usage() {
"When no command is given, redis-cli starts in interactive mode.\n" "When no command is given, redis-cli starts in interactive mode.\n"
"Type \"help\" in interactive mode for information on available commands.\n" "Type \"help\" in interactive mode for information on available commands.\n"
"\n", "\n",
version); version, REDIS_DEFAULT_PIPE_TIMEOUT);
sdsfree(version); sdsfree(version);
exit(1); exit(1);
} }
@ -1119,6 +1126,7 @@ static void pipeMode(void) {
int eof = 0; /* True once we consumed all the standard input. */ int eof = 0; /* True once we consumed all the standard input. */
int done = 0; int done = 0;
char magic[20]; /* Special reply we recognize. */ char magic[20]; /* Special reply we recognize. */
time_t last_read_time = time(NULL);
srand(time(NULL)); srand(time(NULL));
@ -1149,7 +1157,10 @@ static void pipeMode(void) {
strerror(errno)); strerror(errno));
exit(1); exit(1);
} }
if (nread > 0) redisReaderFeed(reader,ibuf,nread); if (nread > 0) {
redisReaderFeed(reader,ibuf,nread);
last_read_time = time(NULL);
}
} while(nread > 0); } while(nread > 0);
/* Consume replies. */ /* Consume replies. */
@ -1235,6 +1246,18 @@ static void pipeMode(void) {
if (obuf_len == 0 && eof) break; if (obuf_len == 0 && eof) break;
} }
} }
/* Handle timeout, that is, we reached EOF, and we are not getting
* replies from the server for a few seconds, nor the final ECHO is
* received. */
if (eof && config.pipe_timeout > 0 &&
time(NULL)-last_read_time > config.pipe_timeout)
{
fprintf(stderr,"No replies for %d seconds: exiting.\n",
config.pipe_timeout);
errors++;
break;
}
} }
redisReaderFree(reader); redisReaderFree(reader);
printf("errors: %lld, replies: %lld\n", errors, replies); printf("errors: %lld, replies: %lld\n", errors, replies);
@ -1490,6 +1513,7 @@ int main(int argc, char **argv) {
config.getrdb_mode = 0; config.getrdb_mode = 0;
config.rdb_filename = NULL; config.rdb_filename = NULL;
config.pipe_mode = 0; config.pipe_mode = 0;
config.pipe_timeout = REDIS_DEFAULT_PIPE_TIMEOUT;
config.bigkeys = 0; config.bigkeys = 0;
config.stdinarg = 0; config.stdinarg = 0;
config.auth = NULL; config.auth = NULL;