diff options
author | Subhi Al Hasan <jodevsa@gmail.com> | 2023-04-04 10:53:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-04 11:53:57 +0300 |
commit | 74b29985ced0d185dd15bde9888f93608ba57c14 (patch) | |
tree | 5c0d7382224469f4cef4faa25cee7c5821ab6b61 /src | |
parent | e1da724117bb842c383e227e57b9c45331f430db (diff) | |
download | redis-74b29985ced0d185dd15bde9888f93608ba57c14.tar.gz |
check for known-slave in sentinel rewrite config (#11775)
Fix the following config file error
```
*** FATAL CONFIG FILE ERROR (Redis 6.2.7) ***
Reading the configuration file, at line 152
>>> 'sentinel known-replica XXXX 127.0.0.1 5001'
Duplicate hostname and port for replica.
```
that is happening when a user uses the legacy key "known-slave" in
the config file and a config rewrite occurs. The config rewrite logic won't
replace the old line "sentinel known-slave XXXX 127.0.0.1 5001" and
would add a new line with "sentinel known-replica XXXX 127.0.0.1 5001"
which results in the error above "Duplicate hostname and port for replica."
example:
Current sentinal.conf
```
...
sentinel known-slave XXXX 127.0.0.1 5001
sentinel example-random-option X
...
```
after the config rewrite logic runs:
```
....
sentinel known-slave XXXX 127.0.0.1 5001
sentinel example-random-option X
# Generated by CONFIG REWRITE
sentinel known-replica XXXX 127.0.0.1 5001
```
This bug only exists in Redis versions >=6.2 because prior to that it was hidden
by the effects of this bug https://github.com/redis/redis/issues/5388 that was fixed
in https://github.com/redis/redis/pull/8271 and was released in versions >=6.2
Diffstat (limited to 'src')
-rw-r--r-- | src/config.c | 5 | ||||
-rw-r--r-- | src/sentinel.c | 7 | ||||
-rw-r--r-- | src/server.h | 2 |
3 files changed, 10 insertions, 4 deletions
diff --git a/src/config.c b/src/config.c index 94fc039e2..9a3f8d969 100644 --- a/src/config.c +++ b/src/config.c @@ -1221,7 +1221,7 @@ struct rewriteConfigState *rewriteConfigReadOldFile(char *path) { * * "line" is either used, or freed, so the caller does not need to free it * in any way. */ -void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) { +int rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force) { sds o = sdsnew(option); list *l = dictFetchValue(state->option_to_line,o); @@ -1231,7 +1231,7 @@ void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *opti /* Option not used previously, and we are not forced to use it. */ sdsfree(line); sdsfree(o); - return; + return 0; } if (l) { @@ -1254,6 +1254,7 @@ void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *opti rewriteConfigAppendLine(state,line); } sdsfree(o); + return 1; } /* Write the long long 'bytes' value as a string in a way that is parsable diff --git a/src/sentinel.c b/src/sentinel.c index b4dead7de..03482fdd2 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -2176,7 +2176,12 @@ void rewriteConfigSentinelOption(struct rewriteConfigState *state) { line = sdscatprintf(sdsempty(), "sentinel known-replica %s %s %d", master->name, announceSentinelAddr(slave_addr), slave_addr->port); - rewriteConfigRewriteLine(state,"sentinel known-replica",line,1); + /* try to replace any known-slave option first if found */ + if (rewriteConfigRewriteLine(state, "sentinel known-slave", sdsdup(line), 0) == 0) { + rewriteConfigRewriteLine(state, "sentinel known-replica", line, 1); + } else { + sdsfree(line); + } /* rewriteConfigMarkAsProcessed is handled after the loop */ } dictReleaseIterator(di2); diff --git a/src/server.h b/src/server.h index dd50e9089..02ec91ee0 100644 --- a/src/server.h +++ b/src/server.h @@ -3171,7 +3171,7 @@ void loadServerConfig(char *filename, char config_from_stdin, char *options); void appendServerSaveParams(time_t seconds, int changes); void resetServerSaveParams(void); struct rewriteConfigState; /* Forward declaration to export API. */ -void rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force); +int rewriteConfigRewriteLine(struct rewriteConfigState *state, const char *option, sds line, int force); void rewriteConfigMarkAsProcessed(struct rewriteConfigState *state, const char *option); int rewriteConfig(char *path, int force_write); void initConfigValues(); |