summaryrefslogtreecommitdiff
path: root/src/sentinel.c
diff options
context:
space:
mode:
authorWen Hui <wen.hui.ware@gmail.com>2022-02-08 06:14:42 -0500
committerGitHub <noreply@github.com>2022-02-08 13:14:42 +0200
commit2e1bc942aa00a76ed3b0e5e2678da4ac90071d19 (patch)
tree9b2f888fc8e0b6faee2a5e15b260be10defcec5c /src/sentinel.c
parentb76016a948ecaf475ddda7958776df9bd5cf9621 (diff)
downloadredis-2e1bc942aa00a76ed3b0e5e2678da4ac90071d19.tar.gz
Make INFO command variadic (#6891)
This is an enhancement for INFO command, previously INFO only support one argument for different info section , if user want to get more categories information, either perform INFO all / default or calling INFO for multiple times. **Description of the feature** The goal of adding this feature is to let the user retrieve multiple categories via the INFO command, and still avoid emitting the same section twice. A use case for this is like Redis Sentinel, which periodically calling INFO command to refresh info from monitored Master/Slaves, only Server and Replication part categories are used for parsing information. If the INFO command can return just enough categories that client side needs, it can save a lot of time for client side parsing it as well as network bandwidth. **Implementation** To share code between redis, sentinel, and other users of INFO (DEBUG and modules), we have a new `genInfoSectionDict` function that returns a dict and some boolean flags (e.g. `all`) to the caller (built from user input). Sentinel is later purging unwanted sections from that, and then it is forwarded to the info `genRedisInfoString`. **Usage Examples** INFO Server Replication INFO CPU Memory INFO default commandstats Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/sentinel.c')
-rw-r--r--src/sentinel.c65
1 files changed, 36 insertions, 29 deletions
diff --git a/src/sentinel.c b/src/sentinel.c
index 98121acde..61408c802 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -4099,46 +4099,52 @@ numargserr:
addReplyErrorArity(c);
}
-#define info_section_from_redis(section_name) do { \
- if (defsections || allsections || !strcasecmp(section,section_name)) { \
- sds redissection; \
- if (sections++) info = sdscat(info,"\r\n"); \
- redissection = genRedisInfoString(section_name); \
- info = sdscatlen(info,redissection,sdslen(redissection)); \
- sdsfree(redissection); \
- } \
-} while(0)
+void addInfoSectionsToDict(dict *section_dict, char **sections);
/* SENTINEL INFO [section] */
void sentinelInfoCommand(client *c) {
- if (c->argc > 2) {
- addReplyErrorObject(c,shared.syntaxerr);
- return;
+ char *sentinel_sections[] = {"server", "clients", "cpu", "stats", "sentinel", NULL};
+ int sec_all = 0, sec_everything = 0;
+ static dict *cached_all_info_sectoins = NULL;
+
+ /* Get requested section list. */
+ dict *sections_dict = genInfoSectionDict(c->argv+1, c->argc-1, sentinel_sections, &sec_all, &sec_everything);
+
+ /* Purge unsupported sections from the requested ones. */
+ dictEntry *de;
+ dictIterator *di = dictGetSafeIterator(sections_dict);
+ while((de = dictNext(di)) != NULL) {
+ int i;
+ sds sec = dictGetKey(de);
+ for (i=0; sentinel_sections[i]; i++)
+ if (!strcasecmp(sentinel_sections[i], sec))
+ break;
+ /* section not found? remove it */
+ if (!sentinel_sections[i])
+ dictDelete(sections_dict, sec);
}
+ dictReleaseIterator(di);
- int defsections = 0, allsections = 0;
- char *section = c->argc == 2 ? c->argv[1]->ptr : NULL;
- if (section) {
- allsections = !strcasecmp(section,"all");
- defsections = !strcasecmp(section,"default");
- } else {
- defsections = 1;
+ /* Insert explicit all sections (don't pass these vars to genRedisInfoString) */
+ if (sec_all || sec_everything) {
+ releaseInfoSectionDict(sections_dict);
+ /* We cache this dict as an optimization. */
+ if (!cached_all_info_sectoins) {
+ cached_all_info_sectoins = dictCreate(&stringSetDictType);
+ addInfoSectionsToDict(cached_all_info_sectoins, sentinel_sections);
+ }
+ sections_dict = cached_all_info_sectoins;
}
- int sections = 0;
sds info = sdsempty();
-
- info_section_from_redis("server");
- info_section_from_redis("clients");
- info_section_from_redis("cpu");
- info_section_from_redis("stats");
-
- if (defsections || allsections || !strcasecmp(section,"sentinel")) {
+ info = genRedisInfoString(sections_dict, 0, 0);
+ if (sec_all || (dictFind(sections_dict, "sentinel") != NULL)) {
dictIterator *di;
dictEntry *de;
int master_id = 0;
- if (sections++) info = sdscat(info,"\r\n");
+ if (sdslen(info) != 0)
+ info = sdscat(info,"\r\n");
info = sdscatprintf(info,
"# Sentinel\r\n"
"sentinel_masters:%lu\r\n"
@@ -4171,7 +4177,8 @@ void sentinelInfoCommand(client *c) {
}
dictReleaseIterator(di);
}
-
+ if (sections_dict != cached_all_info_sectoins)
+ releaseInfoSectionDict(sections_dict);
addReplyBulkSds(c, info);
}