mirror of https://mirror.osredm.com/root/redis.git
Enabled -x option (Read last argument from STDIN) on redis-benchmark (#9130)
Add the -x option (Read last argument from STDIN) on redis-benchmark. Other changes: To be able to use the code from redis-cli some helper methods were moved to cli_common.(h|c) Co-authored-by: Oran Agra <oran@redislabs.com>
This commit is contained in:
parent
432c92d8df
commit
4aa927d16d
|
@ -28,11 +28,16 @@
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fmacros.h"
|
||||||
#include "cli_common.h"
|
#include "cli_common.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <hiredis.h>
|
#include <hiredis.h>
|
||||||
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||||
#include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */
|
#include <sds.h> /* use sds.h from hiredis, so that only one set of sds functions will be present in the binary */
|
||||||
|
#include <unistd.h>
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
@ -192,3 +197,65 @@ int cliSecureInit()
|
||||||
#endif
|
#endif
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create an sds from stdin */
|
||||||
|
sds readArgFromStdin(void) {
|
||||||
|
char buf[1024];
|
||||||
|
sds arg = sdsempty();
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
int nread = read(fileno(stdin),buf,1024);
|
||||||
|
|
||||||
|
if (nread == 0) break;
|
||||||
|
else if (nread == -1) {
|
||||||
|
perror("Reading from standard input");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
arg = sdscatlen(arg,buf,nread);
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create an sds array from argv, either as-is or by dequoting every
|
||||||
|
* element. When quoted is non-zero, may return a NULL to indicate an
|
||||||
|
* invalid quoted string.
|
||||||
|
*
|
||||||
|
* The caller should free the resulting array of sds strings with
|
||||||
|
* sdsfreesplitres().
|
||||||
|
*/
|
||||||
|
sds *getSdsArrayFromArgv(int argc,char **argv, int quoted) {
|
||||||
|
sds *res = sds_malloc(sizeof(sds) * argc);
|
||||||
|
|
||||||
|
for (int j = 0; j < argc; j++) {
|
||||||
|
if (quoted) {
|
||||||
|
sds unquoted = unquoteCString(argv[j]);
|
||||||
|
if (!unquoted) {
|
||||||
|
while (--j >= 0) sdsfree(res[j]);
|
||||||
|
sds_free(res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
res[j] = unquoted;
|
||||||
|
} else {
|
||||||
|
res[j] = sdsnew(argv[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unquote a null-terminated string and return it as a binary-safe sds. */
|
||||||
|
sds unquoteCString(char *str) {
|
||||||
|
int count;
|
||||||
|
sds *unquoted = sdssplitargs(str, &count);
|
||||||
|
sds res = NULL;
|
||||||
|
|
||||||
|
if (unquoted && count == 1) {
|
||||||
|
res = unquoted[0];
|
||||||
|
unquoted[0] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unquoted)
|
||||||
|
sdsfreesplitres(unquoted, count);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define __CLICOMMON_H
|
#define __CLICOMMON_H
|
||||||
|
|
||||||
#include <hiredis.h>
|
#include <hiredis.h>
|
||||||
|
#include <sdscompat.h> /* Use hiredis' sds compat header that maps sds calls to their hi_ variants */
|
||||||
|
|
||||||
typedef struct cliSSLconfig {
|
typedef struct cliSSLconfig {
|
||||||
/* Requested SNI, or NULL */
|
/* Requested SNI, or NULL */
|
||||||
|
@ -22,29 +23,16 @@ typedef struct cliSSLconfig {
|
||||||
char* ciphersuites;
|
char* ciphersuites;
|
||||||
} cliSSLconfig;
|
} cliSSLconfig;
|
||||||
|
|
||||||
/* Wrapper around redisSecureConnection to avoid hiredis_ssl dependencies if
|
|
||||||
* not building with TLS support.
|
|
||||||
*/
|
|
||||||
int cliSecureConnection(redisContext *c, cliSSLconfig config, const char **err);
|
int cliSecureConnection(redisContext *c, cliSSLconfig config, const char **err);
|
||||||
|
|
||||||
/* Wrapper around hiredis to allow arbitrary reads and writes.
|
|
||||||
*
|
|
||||||
* We piggybacks on top of hiredis to achieve transparent TLS support,
|
|
||||||
* and use its internal buffers so it can co-exist with commands
|
|
||||||
* previously/later issued on the connection.
|
|
||||||
*
|
|
||||||
* Interface is close to enough to read()/write() so things should mostly
|
|
||||||
* work transparently.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Write a raw buffer through a redisContext. If we already have something
|
|
||||||
* in the buffer (leftovers from hiredis operations) it will be written
|
|
||||||
* as well.
|
|
||||||
*/
|
|
||||||
ssize_t cliWriteConn(redisContext *c, const char *buf, size_t buf_len);
|
ssize_t cliWriteConn(redisContext *c, const char *buf, size_t buf_len);
|
||||||
|
|
||||||
/* Wrapper around OpenSSL (libssl and libcrypto) initialisation.
|
|
||||||
*/
|
|
||||||
int cliSecureInit();
|
int cliSecureInit();
|
||||||
|
|
||||||
|
sds readArgFromStdin(void);
|
||||||
|
|
||||||
|
sds *getSdsArrayFromArgv(int argc,char **argv, int quoted);
|
||||||
|
|
||||||
|
sds unquoteCString(char *str);
|
||||||
|
|
||||||
#endif /* __CLICOMMON_H */
|
#endif /* __CLICOMMON_H */
|
||||||
|
|
|
@ -110,6 +110,7 @@ static struct config {
|
||||||
int dbnum;
|
int dbnum;
|
||||||
sds dbnumstr;
|
sds dbnumstr;
|
||||||
char *tests;
|
char *tests;
|
||||||
|
int stdinarg; /* get last arg from stdin. (-x option) */
|
||||||
char *auth;
|
char *auth;
|
||||||
const char *user;
|
const char *user;
|
||||||
int precision;
|
int precision;
|
||||||
|
@ -1399,7 +1400,7 @@ static void genBenchmarkRandomData(char *data, int count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns number of consumed options. */
|
/* Returns number of consumed options. */
|
||||||
int parseOptions(int argc, const char **argv) {
|
int parseOptions(int argc, char **argv) {
|
||||||
int i;
|
int i;
|
||||||
int lastarg;
|
int lastarg;
|
||||||
int exit_status = 1;
|
int exit_status = 1;
|
||||||
|
@ -1430,6 +1431,8 @@ int parseOptions(int argc, const char **argv) {
|
||||||
} else if (!strcmp(argv[i],"-s")) {
|
} else if (!strcmp(argv[i],"-s")) {
|
||||||
if (lastarg) goto invalid;
|
if (lastarg) goto invalid;
|
||||||
config.hostsocket = strdup(argv[++i]);
|
config.hostsocket = strdup(argv[++i]);
|
||||||
|
} else if (!strcmp(argv[i],"-x")) {
|
||||||
|
config.stdinarg = 1;
|
||||||
} else if (!strcmp(argv[i],"-a") ) {
|
} else if (!strcmp(argv[i],"-a") ) {
|
||||||
if (lastarg) goto invalid;
|
if (lastarg) goto invalid;
|
||||||
config.auth = strdup(argv[++i]);
|
config.auth = strdup(argv[++i]);
|
||||||
|
@ -1576,6 +1579,7 @@ usage:
|
||||||
" -t <tests> Only run the comma separated list of tests. The test\n"
|
" -t <tests> Only run the comma separated list of tests. The test\n"
|
||||||
" names are the same as the ones produced as output.\n"
|
" names are the same as the ones produced as output.\n"
|
||||||
" -I Idle mode. Just open N idle connections and wait.\n"
|
" -I Idle mode. Just open N idle connections and wait.\n"
|
||||||
|
" -x Read last argument from STDIN.\n"
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
" --tls Establish a secure TLS connection.\n"
|
" --tls Establish a secure TLS connection.\n"
|
||||||
" --sni <host> Server name indication for TLS.\n"
|
" --sni <host> Server name indication for TLS.\n"
|
||||||
|
@ -1673,7 +1677,7 @@ int test_is_selected(char *name) {
|
||||||
return strstr(config.tests,buf) != NULL;
|
return strstr(config.tests,buf) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int i;
|
int i;
|
||||||
char *data, *cmd, *tag;
|
char *data, *cmd, *tag;
|
||||||
int len;
|
int len;
|
||||||
|
@ -1706,6 +1710,7 @@ int main(int argc, const char **argv) {
|
||||||
config.hostsocket = NULL;
|
config.hostsocket = NULL;
|
||||||
config.tests = NULL;
|
config.tests = NULL;
|
||||||
config.dbnum = 0;
|
config.dbnum = 0;
|
||||||
|
config.stdinarg = 0;
|
||||||
config.auth = NULL;
|
config.auth = NULL;
|
||||||
config.precision = DEFAULT_LATENCY_PRECISION;
|
config.precision = DEFAULT_LATENCY_PRECISION;
|
||||||
config.num_threads = 0;
|
config.num_threads = 0;
|
||||||
|
@ -1812,14 +1817,24 @@ int main(int argc, const char **argv) {
|
||||||
title = sdscatlen(title, " ", 1);
|
title = sdscatlen(title, " ", 1);
|
||||||
title = sdscatlen(title, (char*)argv[i], strlen(argv[i]));
|
title = sdscatlen(title, (char*)argv[i], strlen(argv[i]));
|
||||||
}
|
}
|
||||||
|
sds *sds_args = getSdsArrayFromArgv(argc, argv, 0);
|
||||||
|
if (!sds_args) {
|
||||||
|
printf("Invalid quoted string\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (config.stdinarg) {
|
||||||
|
sds_args = sds_realloc(sds_args,(argc + 1) * sizeof(sds));
|
||||||
|
sds_args[argc] = readArgFromStdin();
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
len = redisFormatCommandArgv(&cmd,argc,argv,NULL);
|
len = redisFormatCommandArgv(&cmd,argc,(const char**)sds_args,NULL);
|
||||||
// adjust the datasize to the parsed command
|
// adjust the datasize to the parsed command
|
||||||
config.datasize = len;
|
config.datasize = len;
|
||||||
benchmark(title,cmd,len);
|
benchmark(title,cmd,len);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
} while(config.loop);
|
} while(config.loop);
|
||||||
|
sdsfreesplitres(sds_args, argc);
|
||||||
|
|
||||||
if (config.redis_config != NULL) freeRedisConfig(config.redis_config);
|
if (config.redis_config != NULL) freeRedisConfig(config.redis_config);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -775,23 +775,6 @@ static void freeHintsCallback(void *ptr) {
|
||||||
* Networking / parsing
|
* Networking / parsing
|
||||||
*--------------------------------------------------------------------------- */
|
*--------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Unquote a null-terminated string and return it as a binary-safe sds. */
|
|
||||||
static sds unquoteCString(char *str) {
|
|
||||||
int count;
|
|
||||||
sds *unquoted = sdssplitargs(str, &count);
|
|
||||||
sds res = NULL;
|
|
||||||
|
|
||||||
if (unquoted && count == 1) {
|
|
||||||
res = unquoted[0];
|
|
||||||
unquoted[0] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unquoted)
|
|
||||||
sdsfreesplitres(unquoted, count);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send AUTH command to the server */
|
/* Send AUTH command to the server */
|
||||||
static int cliAuth(redisContext *ctx, char *user, char *auth) {
|
static int cliAuth(redisContext *ctx, char *user, char *auth) {
|
||||||
redisReply *reply;
|
redisReply *reply;
|
||||||
|
@ -1879,23 +1862,6 @@ static void parseEnv() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static sds readArgFromStdin(void) {
|
|
||||||
char buf[1024];
|
|
||||||
sds arg = sdsempty();
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
int nread = read(fileno(stdin),buf,1024);
|
|
||||||
|
|
||||||
if (nread == 0) break;
|
|
||||||
else if (nread == -1) {
|
|
||||||
perror("Reading from standard input");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
arg = sdscatlen(arg,buf,nread);
|
|
||||||
}
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(int err) {
|
static void usage(int err) {
|
||||||
sds version = cliVersion();
|
sds version = cliVersion();
|
||||||
FILE *target = err ? stderr: stdout;
|
FILE *target = err ? stderr: stdout;
|
||||||
|
@ -2043,30 +2009,6 @@ static int confirmWithYes(char *msg, int ignore_force) {
|
||||||
return (nread != 0 && !strcmp("yes", buf));
|
return (nread != 0 && !strcmp("yes", buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create an sds array from argv, either as-is or by dequoting every
|
|
||||||
* element. When quoted is non-zero, may return a NULL to indicate an
|
|
||||||
* invalid quoted string.
|
|
||||||
*/
|
|
||||||
static sds *getSdsArrayFromArgv(int argc, char **argv, int quoted) {
|
|
||||||
sds *res = sds_malloc(sizeof(sds) * argc);
|
|
||||||
|
|
||||||
for (int j = 0; j < argc; j++) {
|
|
||||||
if (quoted) {
|
|
||||||
sds unquoted = unquoteCString(argv[j]);
|
|
||||||
if (!unquoted) {
|
|
||||||
while (--j >= 0) sdsfree(res[j]);
|
|
||||||
sds_free(res);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
res[j] = unquoted;
|
|
||||||
} else {
|
|
||||||
res[j] = sdsnew(argv[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int issueCommandRepeat(int argc, char **argv, long repeat) {
|
static int issueCommandRepeat(int argc, char **argv, long repeat) {
|
||||||
while (1) {
|
while (1) {
|
||||||
if (config.cluster_reissue_command || context == NULL ||
|
if (config.cluster_reissue_command || context == NULL ||
|
||||||
|
|
Loading…
Reference in New Issue