Merge commit '76d57161d960f27ac92765118e3b80fef8847b8f' into redis_6_merge

Former-commit-id: 320bc3c0329ff9e5a980b79426b719addae381cf
This commit is contained in:
John Sully 2020-04-14 21:04:42 -04:00
commit aa48225a76
14 changed files with 115 additions and 12 deletions

1
.gitignore vendored
View File

@ -40,3 +40,4 @@ deps/lua/src/liblua.a
*.dSYM *.dSYM
Makefile.dep Makefile.dep
.vscode/* .vscode/*
.idea/*

View File

@ -30,7 +30,7 @@ New features and improvements:
* ACL LOG: log denied commands, keys accesses and authentications. * ACL LOG: log denied commands, keys accesses and authentications.
* Client side caching redesigned. Now we use keys not caching slots. * Client side caching redesigned. Now we use keys not caching slots.
* Client side caching: Broadcasting mode implemented. * Client side caching: Broadcasting mode implemented.
* Client side caching: OPTIN/OUTPUT modes implemented. * Client side caching: OPTIN/OPTOUT modes implemented.
* Remove RDB files used for replication in persistence-less instances (option). * Remove RDB files used for replication in persistence-less instances (option).
Fixes (only selected ones, see commits for all the fixes): Fixes (only selected ones, see commits for all the fixes):

View File

@ -21,7 +21,7 @@ So what usually happens is either:
The result is a pollution of binaries without line editing support. The result is a pollution of binaries without line editing support.
So I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporing line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to Linenoise if not. So I spent more or less two hours doing a reality check resulting in this little library: is it *really* needed for a line editing library to be 20k lines of code? Apparently not, it is possibe to get a very small, zero configuration, trivial to embed library, that solves the problem. Smaller programs will just include this, supporting line editing out of the box. Larger programs may use this little library or just checking with configure if readline/libedit is available and resorting to Linenoise if not.
## Terminals, in 2010. ## Terminals, in 2010.
@ -126,6 +126,24 @@ Linenoise has direct support for persisting the history into an history
file. The functions `linenoiseHistorySave` and `linenoiseHistoryLoad` do file. The functions `linenoiseHistorySave` and `linenoiseHistoryLoad` do
just that. Both functions return -1 on error and 0 on success. just that. Both functions return -1 on error and 0 on success.
## Mask mode
Sometimes it is useful to allow the user to type passwords or other
secrets that should not be displayed. For such situations linenoise supports
a "mask mode" that will just replace the characters the user is typing
with `*` characters, like in the following example:
$ ./linenoise_example
hello> get mykey
echo: 'get mykey'
hello> /mask
hello> *********
You can enable and disable mask mode using the following two functions:
void linenoiseMaskModeEnable(void);
void linenoiseMaskModeDisable(void);
## Completion ## Completion
Linenoise supports completion, which is the ability to complete the user Linenoise supports completion, which is the ability to complete the user
@ -222,3 +240,8 @@ Sometimes you may want to clear the screen as a result of something the
user typed. You can do this by calling the following function: user typed. You can do this by calling the following function:
void linenoiseClearScreen(void); void linenoiseClearScreen(void);
## Related projects
* [Linenoise NG](https://github.com/arangodb/linenoise-ng) is a fork of Linenoise that aims to add more advanced features like UTF-8 support, Windows support and other features. Uses C++ instead of C as development language.
* [Linenoise-swift](https://github.com/andybest/linenoise-swift) is a reimplementation of Linenoise written in Swift.

View File

@ -55,6 +55,7 @@ int main(int argc, char **argv) {
* *
* The typed string is returned as a malloc() allocated string by * The typed string is returned as a malloc() allocated string by
* linenoise, so the user needs to free() it. */ * linenoise, so the user needs to free() it. */
while((line = linenoise("hello> ")) != NULL) { while((line = linenoise("hello> ")) != NULL) {
/* Do something with the string. */ /* Do something with the string. */
if (line[0] != '\0' && line[0] != '/') { if (line[0] != '\0' && line[0] != '/') {
@ -65,6 +66,10 @@ int main(int argc, char **argv) {
/* The "/historylen" command will change the history len. */ /* The "/historylen" command will change the history len. */
int len = atoi(line+11); int len = atoi(line+11);
linenoiseHistorySetMaxLen(len); linenoiseHistorySetMaxLen(len);
} else if (!strncmp(line, "/mask", 5)) {
linenoiseMaskModeEnable();
} else if (!strncmp(line, "/unmask", 7)) {
linenoiseMaskModeDisable();
} else if (line[0] == '/') { } else if (line[0] == '/') {
printf("Unreconized command: %s\n", line); printf("Unreconized command: %s\n", line);
} }

View File

@ -125,6 +125,7 @@ static linenoiseHintsCallback *hintsCallback = NULL;
static linenoiseFreeHintsCallback *freeHintsCallback = NULL; static linenoiseFreeHintsCallback *freeHintsCallback = NULL;
static struct termios orig_termios; /* In order to restore at exit.*/ static struct termios orig_termios; /* In order to restore at exit.*/
static int maskmode = 0; /* Show "***" instead of input. For passwords. */
static int rawmode = 0; /* For atexit() function to check if restore is needed*/ static int rawmode = 0; /* For atexit() function to check if restore is needed*/
static int mlmode = 0; /* Multi line mode. Default is single line. */ static int mlmode = 0; /* Multi line mode. Default is single line. */
static int atexit_registered = 0; /* Register atexit just 1 time. */ static int atexit_registered = 0; /* Register atexit just 1 time. */
@ -197,6 +198,19 @@ FILE *lndebug_fp = NULL;
/* ======================= Low level terminal handling ====================== */ /* ======================= Low level terminal handling ====================== */
/* Enable "mask mode". When it is enabled, instead of the input that
* the user is typing, the terminal will just display a corresponding
* number of asterisks, like "****". This is useful for passwords and other
* secrets that should not be displayed. */
void linenoiseMaskModeEnable(void) {
maskmode = 1;
}
/* Disable mask mode. */
void linenoiseMaskModeDisable(void) {
maskmode = 0;
}
/* Set if to use or not the multi line mode. */ /* Set if to use or not the multi line mode. */
void linenoiseSetMultiLine(int ml) { void linenoiseSetMultiLine(int ml) {
mlmode = ml; mlmode = ml;
@ -485,6 +499,8 @@ void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
if (bold == 1 && color == -1) color = 37; if (bold == 1 && color == -1) color = 37;
if (color != -1 || bold != 0) if (color != -1 || bold != 0)
snprintf(seq,64,"\033[%d;%d;49m",bold,color); snprintf(seq,64,"\033[%d;%d;49m",bold,color);
else
seq[0] = '\0';
abAppend(ab,seq,strlen(seq)); abAppend(ab,seq,strlen(seq));
abAppend(ab,hint,hintlen); abAppend(ab,hint,hintlen);
if (color != -1 || bold != 0) if (color != -1 || bold != 0)
@ -523,7 +539,11 @@ static void refreshSingleLine(struct linenoiseState *l) {
abAppend(&ab,seq,strlen(seq)); abAppend(&ab,seq,strlen(seq));
/* Write the prompt and the current buffer content */ /* Write the prompt and the current buffer content */
abAppend(&ab,l->prompt,strlen(l->prompt)); abAppend(&ab,l->prompt,strlen(l->prompt));
abAppend(&ab,buf,len); if (maskmode == 1) {
while (len--) abAppend(&ab,"*",1);
} else {
abAppend(&ab,buf,len);
}
/* Show hits if any. */ /* Show hits if any. */
refreshShowHints(&ab,l,plen); refreshShowHints(&ab,l,plen);
/* Erase to right */ /* Erase to right */
@ -577,7 +597,12 @@ static void refreshMultiLine(struct linenoiseState *l) {
/* Write the prompt and the current buffer content */ /* Write the prompt and the current buffer content */
abAppend(&ab,l->prompt,strlen(l->prompt)); abAppend(&ab,l->prompt,strlen(l->prompt));
abAppend(&ab,l->buf,l->len); if (maskmode == 1) {
unsigned int i;
for (i = 0; i < l->len; i++) abAppend(&ab,"*",1);
} else {
abAppend(&ab,l->buf,l->len);
}
/* Show hits if any. */ /* Show hits if any. */
refreshShowHints(&ab,l,plen); refreshShowHints(&ab,l,plen);
@ -645,7 +670,8 @@ int linenoiseEditInsert(struct linenoiseState *l, char c) {
if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) { if ((!mlmode && l->plen+l->len < l->cols && !hintsCallback)) {
/* Avoid a full update of the line in the /* Avoid a full update of the line in the
* trivial case. */ * trivial case. */
if (write(l->ofd,&c,1) == -1) return -1; char d = (maskmode==1) ? '*' : c;
if (write(l->ofd,&d,1) == -1) return -1;
} else { } else {
refreshLine(l); refreshLine(l);
} }

View File

@ -65,6 +65,8 @@ int linenoiseHistoryLoad(const char *filename);
void linenoiseClearScreen(void); void linenoiseClearScreen(void);
void linenoiseSetMultiLine(int ml); void linenoiseSetMultiLine(int ml);
void linenoisePrintKeyCodes(void); void linenoisePrintKeyCodes(void);
void linenoiseMaskModeEnable(void);
void linenoiseMaskModeDisable(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -142,7 +142,8 @@ tcp-keepalive 300
# server to connected clients, masters or cluster peers. These files should be # server to connected clients, masters or cluster peers. These files should be
# PEM formatted. # PEM formatted.
# #
# tls-cert-file redis.crt tls-key-file redis.key # tls-cert-file redis.crt
# tls-key-file redis.key
# Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange: # Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange:
# #
@ -175,8 +176,7 @@ tcp-keepalive 300
# tls-cluster yes # tls-cluster yes
# Explicitly specify TLS versions to support. Allowed values are case insensitive # Explicitly specify TLS versions to support. Allowed values are case insensitive
# and include "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" (OpenSSL >= 1.1.1) or # and include "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" (OpenSSL >= 1.1.1)
# "default" which is currently >= TLSv1.1.
# #
# tls-protocols TLSv1.2 # tls-protocols TLSv1.2

View File

@ -681,6 +681,7 @@ extern "C" void ProcessEventCore(aeEventLoop *eventLoop, aeFileEvent *fe, int ma
LOCK_IF_NECESSARY(fe, AE_READ_THREADSAFE); LOCK_IF_NECESSARY(fe, AE_READ_THREADSAFE);
fe->rfileProc(eventLoop,fd,fe->clientData,mask | (fe->mask & AE_READ_THREADSAFE)); fe->rfileProc(eventLoop,fd,fe->clientData,mask | (fe->mask & AE_READ_THREADSAFE));
fired++; fired++;
fe = &eventLoop->events[fd]; /* Refresh in case of resize. */
} }
/* Fire the writable event. */ /* Fire the writable event. */

View File

@ -85,7 +85,7 @@ int THPGetAnonHugePagesSize(void) {
/* ---------------------------- Latency API --------------------------------- */ /* ---------------------------- Latency API --------------------------------- */
/* Latency monitor initialization. We just need to create the dictionary /* Latency monitor initialization. We just need to create the dictionary
* of time series, each time serie is craeted on demand in order to avoid * of time series, each time serie is created on demand in order to avoid
* having a fixed list to maintain. */ * having a fixed list to maintain. */
void latencyMonitorInit(void) { void latencyMonitorInit(void) {
g_pserver->latency_events = dictCreate(&latencyTimeSeriesDictType,NULL); g_pserver->latency_events = dictCreate(&latencyTimeSeriesDictType,NULL);

View File

@ -1262,6 +1262,8 @@ static int parseOptions(int argc, char **argv) {
config.dbnum = atoi(argv[++i]); config.dbnum = atoi(argv[++i]);
} else if (!strcmp(argv[i], "--no-auth-warning")) { } else if (!strcmp(argv[i], "--no-auth-warning")) {
config.no_auth_warning = 1; config.no_auth_warning = 1;
} else if (!strcmp(argv[i], "--askpass")) {
config.askpass = 1;
} else if ((!strcmp(argv[i],"-a") || !strcmp(argv[i],"--pass")) } else if ((!strcmp(argv[i],"-a") || !strcmp(argv[i],"--pass"))
&& !lastarg) && !lastarg)
{ {
@ -1502,6 +1504,9 @@ static void usage(void) {
" (if both are used, this argument takes predecence).\n" " (if both are used, this argument takes predecence).\n"
" --user <username> Used to send ACL style 'AUTH username pass'. Needs -a.\n" " --user <username> Used to send ACL style 'AUTH username pass'. Needs -a.\n"
" --pass <password> Alias of -a for consistency with the new --user option.\n" " --pass <password> Alias of -a for consistency with the new --user option.\n"
" --askpass Force user to input password with mask from STDIN.\n"
" If this argument is used, '-a' and " REDIS_CLI_AUTH_ENV "\n"
" environment variable will be ignored.\n"
" -u <uri> Server URI.\n" " -u <uri> Server URI.\n"
" -r <repeat> Execute specified command N times.\n" " -r <repeat> Execute specified command N times.\n"
" -i <interval> When -r is used, waits <interval> seconds per command.\n" " -i <interval> When -r is used, waits <interval> seconds per command.\n"
@ -6748,6 +6753,13 @@ static void intrinsicLatencyMode(void) {
} }
} }
static sds askPassword() {
linenoiseMaskModeEnable();
sds auth = linenoise("Please input password: ");
linenoiseMaskModeDisable();
return auth;
}
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Program main() * Program main()
*--------------------------------------------------------------------------- */ *--------------------------------------------------------------------------- */
@ -6785,6 +6797,7 @@ int main(int argc, char **argv) {
config.hotkeys = 0; config.hotkeys = 0;
config.stdinarg = 0; config.stdinarg = 0;
config.auth = NULL; config.auth = NULL;
config.askpass = 0;
config.user = NULL; config.user = NULL;
config.eval = NULL; config.eval = NULL;
config.eval_ldb = 0; config.eval_ldb = 0;
@ -6826,6 +6839,10 @@ int main(int argc, char **argv) {
parseEnv(); parseEnv();
if (config.askpass) {
config.auth = askPassword();
}
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
if (config.tls) { if (config.tls) {
ERR_load_crypto_strings(); ERR_load_crypto_strings();
@ -6951,4 +6968,4 @@ int main(int argc, char **argv) {
} else { } else {
return noninteractive(argc,convertToSds(argc,argv)); return noninteractive(argc,convertToSds(argc,argv));
} }
} }

View File

@ -163,6 +163,7 @@ extern struct config {
int hotkeys; int hotkeys;
int stdinarg; /* get last arg from stdin. (-x option) */ int stdinarg; /* get last arg from stdin. (-x option) */
char *auth; char *auth;
int askpass;
char *user; char *user;
int output; /* output mode, see OUTPUT_* defines */ int output; /* output mode, see OUTPUT_* defines */
sds mb_delim; sds mb_delim;

View File

@ -114,6 +114,27 @@ start_server {} {
} }
} }
# wait for all the slaves to be in sync with the master
set master_ofs [status $R($master_id) master_repl_offset]
wait_for_condition 500 100 {
$master_ofs == [status $R(0) master_repl_offset] &&
$master_ofs == [status $R(1) master_repl_offset] &&
$master_ofs == [status $R(2) master_repl_offset] &&
$master_ofs == [status $R(3) master_repl_offset] &&
$master_ofs == [status $R(4) master_repl_offset]
} else {
if {$debug_msg} {
for {set j 0} {$j < 5} {incr j} {
puts "$j: sync_full: [status $R($j) sync_full]"
puts "$j: id1 : [status $R($j) master_replid]:[status $R($j) master_repl_offset]"
puts "$j: id2 : [status $R($j) master_replid2]:[status $R($j) second_repl_offset]"
puts "$j: backlog : firstbyte=[status $R($j) repl_backlog_first_byte_offset] len=[status $R($j) repl_backlog_histlen]"
puts "---"
}
}
fail "Slaves are not in sync with the master after too long time."
}
# Put down the old master so that it cannot generate more # Put down the old master so that it cannot generate more
# replication stream, this way in the next master switch, the time at # replication stream, this way in the next master switch, the time at
# which we move slaves away is not important, each will have full # which we move slaves away is not important, each will have full

View File

@ -159,9 +159,12 @@ proc start_server {options {code undefined}} {
if {$::external} { if {$::external} {
if {[llength $::servers] == 0} { if {[llength $::servers] == 0} {
set srv {} set srv {}
# In test_server_main(tests/test_helper.tcl:215~218), increase the value of start_port
# and assign it to ::port through the `--port` option, so we need to reduce it.
set baseport [expr {$::port-100}]
dict set srv "host" $::host dict set srv "host" $::host
dict set srv "port" $::port dict set srv "port" $baseport
set client [redis $::host $::port 0 $::tls] set client [redis $::host $baseport 0 $::tls]
dict set srv "client" $client dict set srv "client" $client
$client select 9 $client select 9

View File

@ -510,6 +510,9 @@ for {set j 0} {$j < [llength $argv]} {incr j} {
} elseif {$opt eq {--host}} { } elseif {$opt eq {--host}} {
set ::external 1 set ::external 1
set ::host $arg set ::host $arg
# If we use an external server, we can only set numclients to 1,
# otherwise the port will be miscalculated.
set ::numclients 1
incr j incr j
} elseif {$opt eq {--port}} { } elseif {$opt eq {--port}} {
set ::port $arg set ::port $arg