Browse Source

MT#55283 properly support empty keyspace list

If keyspace notifications are used at all, the respective objects and
threads must be created during startup. This requires at least some
keyspace to be configured. To support usage without any keyspaces
initially (and add them during runtime), add a special case (set
keyspace to -1).

Convert all keyspace variables to signed ints. Ignore negative keyspace
numbers where appropriate. Support Redis endpoint addresses without
database number.

Fixes #1902

Change-Id: I45a3c87bc515f9b14e64ec1ec0906dde271b5f8d
(cherry picked from commit fb1ad3f0cf)
(cherry picked from commit bf60ce2744)
mr13.1.1
Richard Fuchs 11 months ago
parent
commit
fa0ce46a76
4 changed files with 62 additions and 45 deletions
  1. +29
    -25
      daemon/cli.c
  2. +23
    -19
      daemon/main.c
  3. +4
    -1
      daemon/redis.c
  4. +6
    -0
      docs/rtpengine.md

+ 29
- 25
daemon/cli.c View File

@ -312,7 +312,7 @@ RTPE_CONFIG_UINT64_PARAMS
}
count=0;
for (__auto_type s = initial_rtpe_config.redis_subscribed_keyspaces.head; s ; s = s->next) {
cw->cw_printf(cw, "keyspace[%d] = %d\n", count, GPOINTER_TO_UINT(s->data));
cw->cw_printf(cw, "keyspace[%d] = %d\n", count, GPOINTER_TO_INT(s->data));
++count;
}
@ -364,7 +364,7 @@ RTPE_CONFIG_UINT64_PARAMS
}
count=0;
for (__auto_type c = rtpe_config.redis_subscribed_keyspaces.head; c ; c = c->next) {
cw->cw_printf(cw, "keyspace[%d] = %d\n", count, GPOINTER_TO_UINT(c->data));
cw->cw_printf(cw, "keyspace[%d] = %d\n", count, GPOINTER_TO_INT(c->data));
++count;
}
@ -1043,7 +1043,7 @@ static void cli_incoming_terminate(str *instr, struct cli_writer *cw) {
}
static void cli_incoming_ksadd(str *instr, struct cli_writer *cw) {
unsigned long uint_keyspace_db;
long int_keyspace_db;
char *endptr;
if (!rtpe_redis_notify) {
@ -1057,28 +1057,30 @@ static void cli_incoming_ksadd(str *instr, struct cli_writer *cw) {
}
errno = 0;
uint_keyspace_db = strtoul(instr->s, &endptr, 10);
int_keyspace_db = strtol(instr->s, &endptr, 10);
if ((errno == ERANGE && (uint_keyspace_db == ULONG_MAX)) || (errno != 0 && uint_keyspace_db == 0)) {
cw->cw_printf(cw, "Fail adding keyspace %s to redis notifications; errno=%d\n", instr->s, errno);
if ((errno == ERANGE && (int_keyspace_db == ULONG_MAX)) || int_keyspace_db >= INT_MAX
|| int_keyspace_db < 0
|| (errno != 0 && int_keyspace_db == 0)) {
cw->cw_printf(cw, "Fail adding keyspace " STR_FORMAT " to redis notifications; errno=%d\n", STR_FMT(instr), errno);
} else if (endptr == instr->s) {
cw->cw_printf(cw, "Fail adding keyspace %s to redis notifications; no digits found\n", instr->s);
cw->cw_printf(cw, "Fail adding keyspace " STR_FORMAT " to redis notifications; no digits found\n", STR_FMT(instr));
} else {
rwlock_lock_w(&rtpe_config.keyspaces_lock);
if (!g_queue_find(&rtpe_config.redis_subscribed_keyspaces, GUINT_TO_POINTER(uint_keyspace_db))) {
g_queue_push_tail(&rtpe_config.redis_subscribed_keyspaces, GUINT_TO_POINTER(uint_keyspace_db));
redis_notify_subscribe_action(rtpe_redis_notify, SUBSCRIBE_KEYSPACE, uint_keyspace_db);
cw->cw_printf(cw, "Success adding keyspace %lu to redis notifications.\n", uint_keyspace_db);
if (!g_queue_find(&rtpe_config.redis_subscribed_keyspaces, GINT_TO_POINTER(int_keyspace_db))) {
g_queue_push_tail(&rtpe_config.redis_subscribed_keyspaces, GINT_TO_POINTER(int_keyspace_db));
redis_notify_subscribe_action(rtpe_redis_notify, SUBSCRIBE_KEYSPACE, int_keyspace_db);
cw->cw_printf(cw, "Success adding keyspace %ld to redis notifications.\n", int_keyspace_db);
} else {
cw->cw_printf(cw, "Keyspace %lu is already among redis notifications.\n", uint_keyspace_db);
cw->cw_printf(cw, "Keyspace %ld is already among redis notifications.\n", int_keyspace_db);
}
rwlock_unlock_w(&rtpe_config.keyspaces_lock);
}
}
static void cli_incoming_ksrm(str *instr, struct cli_writer *cw) {
GList *l;
unsigned long uint_keyspace_db;
GList *l;
long int_keyspace_db;
char *endptr;
if (!rtpe_redis_notify) {
@ -1092,26 +1094,28 @@ static void cli_incoming_ksrm(str *instr, struct cli_writer *cw) {
}
errno = 0;
uint_keyspace_db = strtoul(instr->s, &endptr, 10);
int_keyspace_db = strtol(instr->s, &endptr, 10);
rwlock_lock_w(&rtpe_config.keyspaces_lock);
if ((errno == ERANGE && (uint_keyspace_db == ULONG_MAX)) || (errno != 0 && uint_keyspace_db == 0)) {
cw->cw_printf(cw, "Fail removing keyspace %s to redis notifications; errno=%d\n", instr->s, errno);
if ((errno == ERANGE && (int_keyspace_db == ULONG_MAX)) || int_keyspace_db >= INT_MAX
|| int_keyspace_db < 0
|| (errno != 0 && int_keyspace_db == 0)) {
cw->cw_printf(cw, "Fail removing keyspace " STR_FORMAT " to redis notifications; errno=%d\n", STR_FMT(instr), errno);
} else if (endptr == instr->s) {
cw->cw_printf(cw, "Fail removing keyspace %s to redis notifications; no digits found\n", instr->s);
} else if ((l = g_queue_find(&rtpe_config.redis_subscribed_keyspaces, GUINT_TO_POINTER(uint_keyspace_db)))) {
cw->cw_printf(cw, "Fail removing keyspace " STR_FORMAT " to redis notifications; no digits found\n", STR_FMT(instr));
} else if ((l = g_queue_find(&rtpe_config.redis_subscribed_keyspaces, GINT_TO_POINTER(int_keyspace_db)))) {
// remove this keyspace
redis_notify_subscribe_action(rtpe_redis_notify, UNSUBSCRIBE_KEYSPACE, uint_keyspace_db);
redis_notify_subscribe_action(rtpe_redis_notify, UNSUBSCRIBE_KEYSPACE, int_keyspace_db);
g_queue_remove(&rtpe_config.redis_subscribed_keyspaces, l->data);
cw->cw_printf(cw, "Successfully unsubscribed from keyspace %lu.\n", uint_keyspace_db);
cw->cw_printf(cw, "Successfully unsubscribed from keyspace %lu.\n", int_keyspace_db);
// destroy foreign calls for this keyspace
destroy_keyspace_foreign_calls(uint_keyspace_db);
destroy_keyspace_foreign_calls(int_keyspace_db);
// update cli
cw->cw_printf(cw, "Successfully removed all foreign calls for keyspace %lu.\n", uint_keyspace_db);
cw->cw_printf(cw, "Successfully removed all foreign calls for keyspace %ld.\n", int_keyspace_db);
} else {
cw->cw_printf(cw, "Keyspace %lu is not among redis notifications.\n", uint_keyspace_db);
cw->cw_printf(cw, "Keyspace %ld is not among redis notifications.\n", int_keyspace_db);
}
rwlock_unlock_w(&rtpe_config.keyspaces_lock);
@ -1129,7 +1133,7 @@ static void cli_incoming_kslist(str *instr, struct cli_writer *cw) {
rwlock_lock_r(&rtpe_config.keyspaces_lock);
for (l = rtpe_config.redis_subscribed_keyspaces.head; l; l = l->next) {
cw->cw_printf(cw, "%u ", GPOINTER_TO_UINT(l->data));
cw->cw_printf(cw, "%d ", GPOINTER_TO_INT(l->data));
}
rwlock_unlock_r(&rtpe_config.keyspaces_lock);


+ 23
- 19
daemon/main.c View File

@ -377,19 +377,21 @@ static int redis_ep_parse(endpoint_t *ep, int *db, char **hostname, char **auth,
else if ((sl = getenv(auth_env)))
*auth = g_strdup(sl);
sl = strchr(s, '/');
if (!sl)
return -1;
*sl = 0;
sl++;
if (!*sl)
return -1;
l = strtol(sl, &sl, 10);
if (*sl != 0)
return -1;
if (l < 0)
return -1;
*db = l;
if (db) {
sl = strchr(s, '/');
if (!sl)
return -1;
*sl = 0;
sl++;
if (!*sl)
return -1;
l = strtol(sl, &sl, 10);
if (*sl != 0)
return -1;
if (l < 0)
return -1;
*db = l;
}
/* copy for the case with re-resolve during re-connections */
sp = strrchr(s, ':'); /* make sure to not take port into the value of hostname */
@ -488,7 +490,7 @@ static void release_listeners(GQueue *q) {
static void options(int *argc, char ***argv, GHashTable *templates) {
g_autoptr(char_p) if_a = NULL;
g_autoptr(char_p) ks_a = NULL;
unsigned long uint_keyspace_db;
long int_keyspace_db;
str str_keyspace_db;
char **iter;
g_autoptr(char_p) listenps = NULL;
@ -795,15 +797,15 @@ static void options(int *argc, char ***argv, GHashTable *templates) {
if (ks_a) {
for (iter = ks_a; *iter; iter++) {
str_keyspace_db = STR(*iter);
uint_keyspace_db = strtoul(str_keyspace_db.s, &endptr, 10);
int_keyspace_db = strtol(str_keyspace_db.s, &endptr, 10);
if ((errno == ERANGE && (uint_keyspace_db == ULONG_MAX)) ||
(errno != 0 && uint_keyspace_db == 0)) {
if ((errno == ERANGE && (int_keyspace_db == ULONG_MAX)) || int_keyspace_db >= INT_MAX ||
(errno != 0 && int_keyspace_db == 0)) {
ilog(LOG_ERR, "Fail adding keyspace '" STR_FORMAT "' to redis notifications; errno=%d\n", STR_FMT(&str_keyspace_db), errno);
} else if (endptr == str_keyspace_db.s) {
ilog(LOG_ERR, "Fail adding keyspace '" STR_FORMAT "' to redis notifications; no digits found\n", STR_FMT(&str_keyspace_db));
} else {
g_queue_push_tail(&rtpe_config.redis_subscribed_keyspaces, GUINT_TO_POINTER(uint_keyspace_db));
g_queue_push_tail(&rtpe_config.redis_subscribed_keyspaces, GINT_TO_POINTER(int_keyspace_db));
}
}
}
@ -1143,7 +1145,7 @@ static void fill_initial_rtpe_cfg(struct rtpengine_config* ini_rtpe_cfg) {
for (__auto_type l = rtpe_config.redis_subscribed_keyspaces.head; l ; l = l->next) {
// l->data has been assigned to a variable before being given into the queue structure not to get a shallow copy
unsigned int num = GPOINTER_TO_UINT(l->data);
int num = GPOINTER_TO_INT(l->data);
g_queue_push_tail(&ini_rtpe_cfg->redis_subscribed_keyspaces, GINT_TO_POINTER(num));
}
@ -1464,6 +1466,8 @@ static void do_redis_restore(void) {
for (GList *l = rtpe_config.redis_subscribed_keyspaces.head; l; l = l->next) {
int db = GPOINTER_TO_INT(l->data);
if (db < 0)
continue;
if (redis_restore(r, true, db))
ilog(LOG_WARN, "Unable to restore calls from the active-active peer");
}


+ 4
- 1
daemon/redis.c View File

@ -776,7 +776,10 @@ static int redis_notify(struct redis *r) {
// subscribe to the values in the configured keyspaces
rwlock_lock_r(&rtpe_config.keyspaces_lock);
for (l = rtpe_config.redis_subscribed_keyspaces.head; l; l = l->next) {
redis_notify_subscribe_action(r, SUBSCRIBE_KEYSPACE, GPOINTER_TO_INT(l->data));
int id = GPOINTER_TO_INT(l->data);
if (id < 0)
continue;
redis_notify_subscribe_action(r, SUBSCRIBE_KEYSPACE, id);
}
rwlock_unlock_r(&rtpe_config.keyspaces_lock);


+ 6
- 0
docs/rtpengine.md View File

@ -542,6 +542,12 @@ call to inject-DTMF won't be sent to __\-\-dtmf-log-dest=__ or __\-\-listen-tcp-
Further subscriptions could be added/removed via __rtpengine-ctl ksadd/ksrm__.
This may lead to enabling/disabling of the redis keyspace notification feature.
The list of keyspace subscriptions can initially be left empty, but if any
keyspaces are to be added later during runtime, the feature must still be
configured at *rtpengine* startup. This can be achieved by either setting
__\-\-redis-subscribe=__ to a valid address, or by listing the single value
__-1__ under __\-\-subscribe-keyspace=__.
- __\-\-redis-num-threads=__*INT*
How many redis restore threads to create.


Loading…
Cancel
Save