From ce00f8758d61c2e05578311a5919f6c7edd7092b Mon Sep 17 00:00:00 2001 From: Naveen Albert Date: Tue, 15 Mar 2022 01:41:29 +0000 Subject: [PATCH] func_db: Add function to return cardinality at prefix Adds the DB_KEYCOUNT function, which can be used to retrieve the number of keys at a given prefix in AstDB. ASTERISK-29968 #close Change-Id: Ib2393b77b7e962dbaae6192f8576bc3f6ba92d09 --- doc/CHANGES-staging/func_db.txt | 6 +++ funcs/func_db.c | 72 +++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 doc/CHANGES-staging/func_db.txt diff --git a/doc/CHANGES-staging/func_db.txt b/doc/CHANGES-staging/func_db.txt new file mode 100644 index 0000000000..72e333a547 --- /dev/null +++ b/doc/CHANGES-staging/func_db.txt @@ -0,0 +1,6 @@ +Subject: func_db + +The function DB_KEYCOUNT has been added, which +returns the cardinality of the keys at a specified +prefix in AstDB, i.e. the number of keys at a +given prefix. diff --git a/funcs/func_db.c b/funcs/func_db.c index 3f98ed0604..33d0821780 100644 --- a/funcs/func_db.c +++ b/funcs/func_db.c @@ -95,6 +95,25 @@ at the prefix specified within the Asterisk database. If no argument is provided, then a list of key families will be returned. + + DB_KEYCOUNT + + + + + Obtain the number of keys at a prefix within the Asterisk database. + + + + + + This function will return the number of keys that exist + at the prefix specified within the Asterisk database. If no argument is + provided, then the number of all key families will be returned. + + + DB_KEYS + @@ -286,6 +305,57 @@ static struct ast_custom_function db_keys_function = { .read2 = function_db_keys, }; +static int function_db_keycount(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len) +{ + size_t parselen = strlen(parse); + struct ast_db_entry *dbe, *orig_dbe; + const char *last = ""; + int keycount = 0; + + /* Remove leading and trailing slashes */ + while (parse[0] == '/') { + parse++; + parselen--; + } + while (parse[parselen - 1] == '/') { + parse[--parselen] = '\0'; + } + + /* Nothing within the database at that prefix? */ + if (!(orig_dbe = dbe = ast_db_gettree(parse, NULL))) { + snprintf(buf, len, "%d", keycount); + return 0; + } + + for (; dbe; dbe = dbe->next) { + /* Find the current component */ + char *curkey = &dbe->key[parselen + 1], *slash; + if (*curkey == '/') { + curkey++; + } + /* Remove everything after the current component */ + if ((slash = strchr(curkey, '/'))) { + *slash = '\0'; + } + + /* Skip duplicates */ + if (!strcasecmp(last, curkey)) { + continue; + } + last = curkey; + + keycount++; + } + ast_db_freetree(orig_dbe); + snprintf(buf, len, "%d", keycount); + return 0; +} + +static struct ast_custom_function db_keycount_function = { + .name = "DB_KEYCOUNT", + .read = function_db_keycount, +}; + static int function_db_delete(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len) { @@ -347,6 +417,7 @@ static int unload_module(void) res |= ast_custom_function_unregister(&db_exists_function); res |= ast_custom_function_unregister(&db_delete_function); res |= ast_custom_function_unregister(&db_keys_function); + res |= ast_custom_function_unregister(&db_keycount_function); return res; } @@ -359,6 +430,7 @@ static int load_module(void) res |= ast_custom_function_register(&db_exists_function); res |= ast_custom_function_register_escalating(&db_delete_function, AST_CFE_READ); res |= ast_custom_function_register(&db_keys_function); + res |= ast_custom_function_register(&db_keycount_function); return res; }