From 3be33de622941b5602ed5e144b9c6c5f0014ccaf Mon Sep 17 00:00:00 2001 From: Andreas Granig Date: Thu, 15 Feb 2018 16:44:30 +0100 Subject: [PATCH] TT#32450 Queue appended redis commands for reconnect Hiredis sends queued commands to redis only after first call of getReply, and if that fails, we need to have the appended commands queued up, so we can re-queue them and re-execute again after reconnect. Also refresh code using upstream fixes, like declaring vars at the beginning of functions instead of inline in for() loops. Change-Id: I2de5da00818aaa27d3c10ba81074cfa83083e5b5 --- debian/patches/sipwise/db_redis.patch | 768 ++++++++++++-------------- 1 file changed, 362 insertions(+), 406 deletions(-) diff --git a/debian/patches/sipwise/db_redis.patch b/debian/patches/sipwise/db_redis.patch index fc8d0fcaf..03804d57f 100644 --- a/debian/patches/sipwise/db_redis.patch +++ b/debian/patches/sipwise/db_redis.patch @@ -1,7 +1,5 @@ -Index: kamailio/Makefile.groups -=================================================================== ---- kamailio.orig/Makefile.groups 2018-02-14 15:23:35.861985218 +0100 -+++ kamailio/Makefile.groups 2018-02-14 15:23:35.853985199 +0100 +--- a/Makefile.groups ++++ b/Makefile.groups @@ -150,7 +150,7 @@ mod_list_jansson=jansson janssonrpc-c @@ -11,10 +9,8 @@ Index: kamailio/Makefile.groups # - modules depending on mono library mod_list_mono=app_mono -Index: kamailio/modules/db_redis/Makefile -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/Makefile 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/Makefile @@ -0,0 +1,36 @@ +# +# WARNING: do not run this directly, it should be run by the master Makefile @@ -52,10 +48,8 @@ Index: kamailio/modules/db_redis/Makefile + REDISON=yes $(MAKE) -C ../../utils/kamctl/ install-modules + +install-scripts: install-redis-scripts -Index: kamailio/modules/db_redis/README -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/README 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/README @@ -0,0 +1,189 @@ +DB_REDIS Module + @@ -246,10 +240,8 @@ Index: kamailio/modules/db_redis/README +modparam("acc_db", "db_url", DBURL_ACC) +modparam("auth_db", "db_url", DBURL_AUTH) +... -Index: kamailio/modules/db_redis/db_redis_mod.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/db_redis_mod.c 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/db_redis_mod.c @@ -0,0 +1,115 @@ +/** + * Copyright (C) 2018 Andreas Granig (sipwise.com) @@ -366,10 +358,8 @@ Index: kamailio/modules/db_redis/db_redis_mod.c +static void mod_destroy(void) { + LM_DBG("module destroying\n"); +} -Index: kamailio/modules/db_redis/db_redis_mod.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/db_redis_mod.h 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/db_redis_mod.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 Andreas Granig (sipwise.com) @@ -424,19 +414,15 @@ Index: kamailio/modules/db_redis/db_redis_mod.h +extern str redis_schema_path; + +#endif /* _DB_REDIS_MOD_H */ -Index: kamailio/modules/db_redis/doc/Makefile -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/doc/Makefile 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/doc/Makefile @@ -0,0 +1,4 @@ +docs = db_redis.xml + +docbook_dir = ../../../docbook +include $(docbook_dir)/Makefile.module -Index: kamailio/modules/db_redis/doc/db_redis.xml -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/doc/db_redis.xml 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/doc/db_redis.xml @@ -0,0 +1,33 @@ + + + + -Index: kamailio/modules/db_redis/doc/db_redis_admin.xml -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/doc/db_redis_admin.xml 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/doc/db_redis_admin.xml @@ -0,0 +1,192 @@ + + + + -Index: kamailio/modules/db_redis/redis_connection.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/redis_connection.c 2018-02-14 15:23:35.853985199 +0100 -@@ -0,0 +1,301 @@ +--- /dev/null ++++ b/modules/db_redis/redis_connection.c +@@ -0,0 +1,397 @@ +/* + * Copyright (C) 2018 Andreas Granig (sipwise.com) + * @@ -699,6 +681,78 @@ Index: kamailio/modules/db_redis/redis_connection.c +#include "redis_connection.h" +#include "redis_table.h" + ++static void print_query(redis_key_t *query) { ++ LM_DBG("Query dump:\n"); ++ for (redis_key_t *k = query; k; k = k->next) { ++ LM_DBG(" %s\n", k->key.s); ++ } ++} ++ ++static int db_redis_push_query(km_redis_con_t *con, redis_key_t *query) { ++ ++ redis_command_t *cmd = NULL; ++ redis_command_t *tmp = NULL; ++ redis_key_t *new_query = NULL; ++ ++ if (!query) ++ return 0; ++ ++ cmd = (redis_command_t*)pkg_malloc(sizeof(redis_command_t)); ++ if (!cmd) { ++ LM_ERR("Failed to allocate memory for redis command\n"); ++ goto err; ++ } ++ ++ // duplicate query, as original one might be free'd after being ++ // appended ++ while(query) { ++ if (db_redis_key_add_str(&new_query, &query->key) != 0) { ++ LM_ERR("Failed to duplicate query\n"); ++ goto err; ++ } ++ query = query->next; ++ } ++ ++ cmd->query = new_query; ++ cmd->next = NULL; ++ ++ if (!con->command_queue) { ++ con->command_queue = cmd; ++ } else { ++ tmp = con->command_queue; ++ while (tmp->next) ++ tmp = tmp->next; ++ tmp->next = cmd; ++ } ++ ++ return 0; ++ ++err: ++ if (new_query) { ++ db_redis_key_free(&new_query); ++ } ++ if (cmd) { ++ pkg_free(cmd); ++ } ++ return -1; ++} ++ ++static redis_key_t* db_redis_shift_query(km_redis_con_t *con) { ++ redis_command_t *cmd; ++ redis_key_t *query; ++ ++ query = NULL; ++ cmd = con->command_queue; ++ ++ if (cmd) { ++ query = cmd->query; ++ con->command_queue = cmd->next; ++ pkg_free(cmd); ++ } ++ ++ return query; ++} ++ +int db_redis_connect(km_redis_con_t *con) { + struct timeval tv; + redisReply *reply; @@ -864,14 +918,6 @@ Index: kamailio/modules/db_redis/redis_connection.c + pkg_free(_c); +} + -+ -+static void print_query(redis_key_t *query) { -+ LM_DBG("Query dump:\n"); -+ for (redis_key_t *k = query; k; k = k->next) { -+ LM_DBG(" %s\n", k->key.s); -+ } -+} -+ +void *db_redis_command_argv(km_redis_con_t *con, redis_key_t *query) { + char **argv = NULL; + int argc; @@ -902,12 +948,17 @@ Index: kamailio/modules/db_redis/redis_connection.c + return reply; +} + -+int db_redis_append_command_argv(km_redis_con_t *con, redis_key_t *query) { ++int db_redis_append_command_argv(km_redis_con_t *con, redis_key_t *query, int queue) { + char **argv = NULL; + int ret, argc; + + print_query(query); + ++ if (queue > 0 && db_redis_push_query(con, query) != 0) { ++ LM_ERR("Failed to queue redis command\n"); ++ return -1; ++ } ++ + argc = db_redis_key_list2arr(query, &argv); + if (argc < 0) { + LM_ERR("Failed to allocate memory for query array\n"); @@ -916,6 +967,10 @@ Index: kamailio/modules/db_redis/redis_connection.c + LM_DBG("query has %d args\n", argc); + + ret = redisAppendCommandArgv(con->con, argc, (const char**)argv, NULL); ++ ++ // this should actually never happen, because if all replies ++ // are properly consumed for the previous command, it won't send ++ // out a new query until redisGetReply is called + if (con->con->err == REDIS_ERR_EOF) { + if (db_redis_connect(con) != 0) { + LM_ERR("Failed to reconnect to redis db\n"); @@ -937,22 +992,40 @@ Index: kamailio/modules/db_redis/redis_connection.c + +int db_redis_get_reply(km_redis_con_t *con, void **reply) { + int ret; ++ redis_key_t *query; + + *reply = NULL; + ret = redisGetReply(con->con, reply); + if (con->con->err == REDIS_ERR_EOF) { ++ LM_DBG("redis connection is gone, try reconnect\n"); ++ con->append_counter = 0; + if (db_redis_connect(con) != 0) { + LM_ERR("Failed to reconnect to redis db\n"); + if (con->con) { + redisFree(con->con); + con->con = NULL; + } -+ return ret; ++ } ++ // take commands from oldest to newest and re-do again, ++ // but don't queue them once again in retry-mode ++ while ((query = db_redis_shift_query(con))) { ++ LM_DBG("re-queueing appended command\n"); ++ if (db_redis_append_command_argv(con, query, 0) != 0) { ++ LM_ERR("Failed to re-queue redis command"); ++ return -1; ++ } ++ db_redis_key_free(&query); + } + ret = redisGetReply(con->con, reply); -+ } -+ if (!con->con->err) ++ if (con->con->err != REDIS_ERR_EOF) { ++ con->append_counter--; ++ } ++ } else { ++ LM_DBG("get_reply successful, removing query\n"); ++ query = db_redis_shift_query(con); ++ db_redis_key_free(&query); + con->append_counter--; ++ } + return ret; +} + @@ -965,6 +1038,7 @@ Index: kamailio/modules/db_redis/redis_connection.c + +void db_redis_consume_replies(km_redis_con_t *con) { + redisReply *reply = NULL; ++ redis_key_t *query; + while (con->append_counter > 0 && !con->con->err) { + LM_DBG("consuming outstanding reply %u", con->append_counter); + db_redis_get_reply(con, (void**)&reply); @@ -973,12 +1047,14 @@ Index: kamailio/modules/db_redis/redis_connection.c + reply = NULL; + } + } ++ while ((query = db_redis_shift_query(con))) { ++ LM_DBG("consuming queued command\n"); ++ db_redis_key_free(&query); ++ } +} -Index: kamailio/modules/db_redis/redis_connection.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/redis_connection.h 2018-02-14 15:23:35.853985199 +0100 -@@ -0,0 +1,73 @@ +--- /dev/null ++++ b/modules/db_redis/redis_connection.h +@@ -0,0 +1,81 @@ +/** + * Copyright (C) 2018 Andreas Granig (sipwise.com) + * @@ -1004,7 +1080,7 @@ Index: kamailio/modules/db_redis/redis_connection.h +#ifndef _REDIS_CONNECTION_H_ +#define _REDIS_CONNECTION_H_ + -+#include ++#include + +#include "db_redis_mod.h" + @@ -1025,12 +1101,20 @@ Index: kamailio/modules/db_redis/redis_connection.h + } \ +} while(0); + ++typedef struct redis_key redis_key_t; ++ ++typedef struct redis_command { ++ redis_key_t *query; ++ struct redis_command *next; ++} redis_command_t; ++ +typedef struct km_redis_con { + struct db_id* id; + unsigned int ref; + struct pool_con* next; + + redisContext *con; ++ redis_command_t *command_queue; + unsigned int append_counter; + struct str_hash_table tables; +} km_redis_con_t; @@ -1046,17 +1130,15 @@ Index: kamailio/modules/db_redis/redis_connection.h + +int db_redis_connect(km_redis_con_t *con); +void *db_redis_command_argv(km_redis_con_t *con, redis_key_t *query); -+int db_redis_append_command_argv(km_redis_con_t *con, redis_key_t *query); ++int db_redis_append_command_argv(km_redis_con_t *con, redis_key_t *query, int queue); +int db_redis_get_reply(km_redis_con_t *con, void **reply); +void db_redis_consume_replies(km_redis_con_t *con); +void db_redis_free_reply(redisReply **reply); + +#endif /* _REDIS_CONNECTION_H_ */ -Index: kamailio/modules/db_redis/redis_dbase.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/redis_dbase.c 2018-02-14 15:23:35.853985199 +0100 -@@ -0,0 +1,2128 @@ +--- /dev/null ++++ b/modules/db_redis/redis_dbase.c +@@ -0,0 +1,2151 @@ +/* + * Copyright (C) 2018 Andreas Granig (sipwise.com) + * @@ -1087,6 +1169,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c +#include "redis_table.h" + +static void db_redis_dump_reply(redisReply *reply) { ++ int i; + if (reply->type == REDIS_REPLY_STRING) { + LM_DBG("%s\n", reply->str); + } else if (reply->type == REDIS_REPLY_INTEGER) { @@ -1095,7 +1178,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + LM_DBG("\n"); + } else if (reply->type == REDIS_REPLY_ARRAY) { + LM_DBG("printing %lu elements in array reply\n", reply->elements); -+ for(int i = 0; i < reply->elements; ++i) { ++ for(i = 0; i < reply->elements; ++i) { + db_redis_dump_reply(reply->element[i]); + } + } else { @@ -1275,7 +1358,8 @@ Index: kamailio/modules/db_redis/redis_dbase.c + return -1; +} + -+static int db_redis_build_entry_manual_keys(redis_table_t *table, const db_key_t *_k, const db_val_t *_v, const int _n, int **manual_keys, int *manual_key_count) { ++static int db_redis_build_entry_manual_keys(redis_table_t *table, const db_key_t *_k, ++ const db_val_t *_v, const int _n, int **manual_keys, int *manual_key_count) { + + // TODO: we also put keys here which are already part of type mapping! + // there must be removed for performance reasons @@ -1292,9 +1376,10 @@ Index: kamailio/modules/db_redis/redis_dbase.c + + for (key = table->entry_keys; key; key = key->next) { + int subkey_found = 0; ++ int i; + LM_DBG("checking for existence of entry key '%.*s' in query to get manual key\n", + key->key.len, key->key.s); -+ for (int i = 0; i < _n; ++i) { ++ for (i = 0; i < _n; ++i) { + const db_key_t k = _k[i]; + if (!str_strcmp(&key->key, (str*)k)) { + LM_DBG("found key in entry key\n"); @@ -1319,7 +1404,9 @@ Index: kamailio/modules/db_redis/redis_dbase.c + return -1; +} + -+static int db_redis_find_query_key(redis_key_t *key, const str *table_name, str *type_name, const db_key_t *_k, const db_val_t *_v, const int _n, str *key_name, int *key_found) { ++static int db_redis_find_query_key(redis_key_t *key, const str *table_name, ++ str *type_name, const db_key_t *_k, const db_val_t *_v, const int _n, ++ str *key_name, int *key_found) { + + unsigned int len; + str val = {NULL, 0}; @@ -1330,9 +1417,10 @@ Index: kamailio/modules/db_redis/redis_dbase.c + + for (; key; key = key->next) { + int subkey_found = 0; ++ int i; + LM_DBG("checking for existence of entry key '%.*s' in query\n", + key->key.len, key->key.s); -+ for (int i = 0; i < _n; ++i) { ++ for (i = 0; i < _n; ++i) { + const db_key_t k = _k[i]; + const db_val_t v = _v[i]; + @@ -1617,9 +1705,10 @@ Index: kamailio/modules/db_redis/redis_dbase.c + db_redis_free_reply(&reply); + break; + } else { ++ int i; + LM_DBG("populating query keys list with result of type query\n"); + *query_keys_count = reply->elements; -+ for (int i = 0; i < reply->elements; ++i) { ++ for (i = 0; i < reply->elements; ++i) { + redisReply *subreply = reply->element[i]; + if (subreply->type == REDIS_REPLY_STRING) { + LM_DBG("adding resulting entry key '%s' from type query\n", subreply->str); @@ -1681,6 +1770,8 @@ Index: kamailio/modules/db_redis/redis_dbase.c + redisReply *reply = NULL; + unsigned long cursor = 0; + char *match = NULL; ++ size_t j; ++ int l; + + str match_pattern = {":entry::*", strlen(":entry::*")}; + @@ -1755,7 +1846,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + + *query_keys_count += reply->element[1]->elements; + -+ for (size_t j = 0; j < reply->element[1]->elements; ++i, ++j) { ++ for (j = 0; j < reply->element[1]->elements; ++i, ++j) { + redisReply *key = reply->element[1]->element[j]; + if (!key) { + LM_ERR("Invalid null key at cursor result index %lu while scanning table '%.*s'\n", @@ -1783,8 +1874,8 @@ Index: kamailio/modules/db_redis/redis_dbase.c + goto err; + } + memset(*manual_keys, 0, *manual_keys_count * sizeof(int)); -+ for (int i = 0; i < _n; ++i) { -+ (*manual_keys)[i] = i; ++ for (l = 0; l < _n; ++l) { ++ (*manual_keys)[l] = l; + } + + if (reply) { @@ -2005,6 +2096,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + int *manual_keys, int manual_keys_count) { + db_val_t* dval; + db_row_t* drow; ++ size_t col; + + if (reply->type != REDIS_REPLY_ARRAY) { + LM_ERR("Unexpected redis reply type, expecting array\n"); @@ -2017,7 +2109,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + } + + // manually filter non-matching replies -+ for (size_t col = 0; col < reply->elements; ++col) { ++ for (col = 0; col < reply->elements; ++col) { + if (col < manual_keys_count) { + int idx = manual_keys[col]; + db_key_t k = _k[idx]; @@ -2045,7 +2137,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + RES_NUM_ROWS(_r), RES_ROW_N(_r), RES_COL_N(_r), reply->elements - manual_keys_count); + return -1; + } -+ for (size_t col = manual_keys_count; col < reply->elements; ++col) { ++ for (col = manual_keys_count; col < reply->elements; ++col) { + size_t colidx = col - manual_keys_count; + size_t redisidx = col; + int coltype; @@ -2095,6 +2187,8 @@ Index: kamailio/modules/db_redis/redis_dbase.c + redisReply *reply = NULL; + redis_key_t *query_v = NULL; + int num_rows = 0; ++ redis_key_t *key; ++ int j; + + *_r = db_redis_new_result(); + if (!*_r) { @@ -2119,7 +2213,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + } + } + -+ for (redis_key_t *key = *keys; key; key = key->next) { ++ for (key = *keys; key; key = key->next) { + redis_key_t *tmp = NULL; + str *keyname = &(key->key); + @@ -2135,7 +2229,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + LM_ERR("Failed to add key name to list\n"); + goto error; + } -+ if (db_redis_append_command_argv(con, query_v) != REDIS_OK) { ++ if (db_redis_append_command_argv(con, query_v, 1) != REDIS_OK) { + LM_ERR("Failed to append redis command\n"); + goto error; + } @@ -2158,7 +2252,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + + // we put the manual comparison columns first, so we can skip them + // easily in result, for the cost of potential duplicate column returns -+ for (int j = 0; j < *manual_keys_count; ++j) { ++ for (j = 0; j < *manual_keys_count; ++j) { + int idx = (*manual_keys)[j]; + str *k_name = _k[idx]; + if (db_redis_key_add_str(&query_v, k_name) != 0) { @@ -2166,7 +2260,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + goto error; + } + } -+ for (int j = 0; j < _nc; ++j) { ++ for (j = 0; j < _nc; ++j) { + str *k_name = _c[j]; + if (db_redis_key_add_str(&query_v, k_name) != 0) { + LM_ERR("Failed to add manual key to query list\n"); @@ -2174,7 +2268,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + } + } + -+ if (db_redis_append_command_argv(con, query_v) != REDIS_OK) { ++ if (db_redis_append_command_argv(con, query_v, 1) != REDIS_OK) { + LM_ERR("Failed to append redis command\n"); + goto error; + } @@ -2193,7 +2287,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + // reset and increment in convert_row + RES_NUM_ROWS(*_r) = RES_ROW_N(*_r) = 0; + -+ for (redis_key_t *key = *keys; key; key = key->next) { ++ for (key = *keys; key; key = key->next) { + // get reply for EXISTS query + if (db_redis_get_reply(con, (void**)&reply) != REDIS_OK) { + LM_ERR("Failed to get reply for query: %s\n", @@ -2255,6 +2349,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + redis_key_t *k = NULL; + int type_keys_count = 0; + int all_type_keys_count = 0; ++ size_t col; + + redisReply *reply = NULL; + redis_key_t *query_v = NULL; @@ -2262,6 +2357,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + redis_key_t *all_type_keys = NULL; + db_val_t *db_vals = NULL; + db_key_t *db_keys = NULL; ++ redis_key_t *type_key; + + if (!keys_count && do_table_scan) { + LM_DBG("performing full table scan\n"); @@ -2344,7 +2440,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + + // manually filter non-matching replies + row_match = 1; -+ for (size_t col = 0; col < reply->elements; ++col) { ++ for (col = 0; col < reply->elements; ++col) { + if (col < manual_keys_count) { + int idx = manual_keys[col]; + db_key_t k = _k[idx]; @@ -2416,7 +2512,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + db_redis_check_reply(con, reply, error); + db_redis_free_reply(&reply); + -+ for (redis_key_t *type_key = type_keys; type_key; type_key = type_key->next) { ++ for (type_key = type_keys; type_key; type_key = type_key->next) { + if (db_redis_key_add_string(&query_v, "SREM", 4) != 0) { + LM_ERR("Failed to add srem command to post-delete query\n"); + goto error; @@ -2467,6 +2563,10 @@ Index: kamailio/modules/db_redis/redis_dbase.c + redisReply *reply = NULL; + redis_key_t *query_v = NULL; + int update_queries = 0; ++ redis_key_t *key; ++ int i; ++ int j; ++ size_t col; + + if (!keys_count && do_table_scan) { + LM_DBG("performing full table scan\n"); @@ -2478,7 +2578,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + } + } + -+ for (redis_key_t *key = *keys; key; key = key->next) { ++ for (key = *keys; key; key = key->next) { + str *keyname = &key->key; + + LM_DBG("fetching row for '%.*s' from redis\n", keyname->len, keyname->s); @@ -2492,7 +2592,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + LM_ERR("Failed to add key name to pre-update exists query\n"); + goto error; + } -+ if (db_redis_append_command_argv(con, query_v) != REDIS_OK) { ++ if (db_redis_append_command_argv(con, query_v, 1) != REDIS_OK) { + LM_ERR("Failed to append redis command\n"); + goto error; + } @@ -2518,7 +2618,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + goto error; + } + -+ for (int j = 0; j < *manual_keys_count; ++j) { ++ for (j = 0; j < *manual_keys_count; ++j) { + int idx = (*manual_keys)[j]; + str *k_name = _k[idx]; + if (db_redis_key_add_str(&query_v, k_name) != 0) { @@ -2527,7 +2627,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + } + } + -+ if (db_redis_append_command_argv(con, query_v) != REDIS_OK) { ++ if (db_redis_append_command_argv(con, query_v, 1) != REDIS_OK) { + LM_ERR("Failed to append redis command\n"); + goto error; + } @@ -2551,7 +2651,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + */ + + -+ for (redis_key_t *key = *keys; key; key = key->next) { ++ for (key = *keys; key; key = key->next) { + int row_match; + + LM_DBG("fetching replies for '%.*s' from redis\n", key->key.len, key->key.s); @@ -2592,7 +2692,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + + // manually filter non-matching replies + row_match = 1; -+ for (size_t col = 0; col < reply->elements; ++col) { ++ for (col = 0; col < reply->elements; ++col) { + if (col < *manual_keys_count) { + int idx = (*manual_keys)[col]; + db_key_t k = _k[idx]; @@ -2623,7 +2723,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + goto error; + } + -+ for (int i = 0; i < _nu; ++i) { ++ for (i = 0; i < _nu; ++i) { + str *k = _uk[i]; + str v = {NULL, 0}; + @@ -2642,7 +2742,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + pkg_free(v.s); + } + update_queries++; -+ if (db_redis_append_command_argv(con, query_v) != REDIS_OK) { ++ if (db_redis_append_command_argv(con, query_v, 1) != REDIS_OK) { + LM_ERR("Failed to append redis command\n"); + goto error; + } @@ -2652,7 +2752,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + + LM_DBG("getting replies for %d queries\n", update_queries); + -+ for (int i = 0; i < update_queries; ++i) { ++ for (i = 0; i < update_queries; ++i) { + if (db_redis_get_reply(con, (void**)&reply) != REDIS_OK) { + LM_ERR("Failed to get reply for query: %s\n", + con->con->errstr); @@ -2699,6 +2799,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + int *manual_keys = NULL; + int manual_keys_count = 0; + db_op_t *query_ops = NULL; ++ int i; + + // TODO: implement order-by + // TODO: optimize mapping-based manual post-check (remove check for keys already @@ -2748,7 +2849,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + LM_ERR("Failed to allocate memory for query op list\n"); + goto error; + } -+ for (int i = 0; i < _n; ++i) { ++ for (i = 0; i < _n; ++i) { + query_ops[i] = op; + } + } else { @@ -2832,6 +2933,8 @@ Index: kamailio/modules/db_redis/redis_dbase.c + int type_keys_count = 0; + redis_key_t *query_v = NULL; + redisReply *reply = NULL; ++ int i; ++ redis_key_t *k; + + con = REDIS_CON(_h); + if (con && con->con == NULL) { @@ -2872,7 +2975,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + goto error; + } + -+ for (int i = 0; i < _n; ++i) { ++ for (i = 0; i < _n; ++i) { + str *k = _k[i]; + str v; + @@ -2896,7 +2999,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + db_redis_check_reply(con, reply, error); + db_redis_free_reply(&reply); + -+ for (redis_key_t *k = type_keys; k; k = k->next) { ++ for (k = type_keys; k; k = k->next) { + str *type_key = &k->key; + + LM_DBG("inserting entry key '%.*s' to type map '%.*s'\n", @@ -2960,6 +3063,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + int free_op = 0; + int do_table_scan = 0; + db_op_t *query_ops = NULL; ++ int i; + + // TODO: optimize mapping-based manual post-check (remove check for keys already + // in type query key) @@ -2993,7 +3097,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + LM_ERR("Failed to allocate memory for query op list\n"); + goto error; + } -+ for (int i = 0; i < _n; ++i) { ++ for (i = 0; i < _n; ++i) { + query_ops[i] = op; + } + } else { @@ -3071,6 +3175,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + int *manual_keys = NULL; + int manual_keys_count = 0; + db_op_t *query_ops = NULL; ++ int i; + + // TODO: optimize mapping-based manual post-check (remove check for keys already + // in type query key) @@ -3104,7 +3209,7 @@ Index: kamailio/modules/db_redis/redis_dbase.c + LM_ERR("Failed to allocate memory for query op list\n"); + goto error; + } -+ for (int i = 0; i < _n; ++i) { ++ for (i = 0; i < _n; ++i) { + query_ops[i] = op; + } + } else { @@ -3185,10 +3290,8 @@ Index: kamailio/modules/db_redis/redis_dbase.c + db_free_result(_r); + return 0; +} -Index: kamailio/modules/db_redis/redis_dbase.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/redis_dbase.h 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/redis_dbase.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 Andreas Granig (sipwise.com) @@ -3269,7 +3372,7 @@ Index: kamailio/modules/db_redis/redis_dbase.h + * Just like insert, but replace the row if it exists + */ +int db_redis_replace(const db1_con_t* handle, const db_key_t* keys, const db_val_t* vals, -+ const int n, const int _un, const int _m); ++ const int n, const int _un, const int _m); + +/* + * Store name of table that will be used by @@ -3278,11 +3381,9 @@ Index: kamailio/modules/db_redis/redis_dbase.h +int db_redis_use_table(db1_con_t* _h, const str* _t); + +#endif /* _REDIS_BASE_H_ */ -Index: kamailio/modules/db_redis/redis_table.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/redis_table.c 2018-02-14 15:23:35.853985199 +0100 -@@ -0,0 +1,838 @@ +--- /dev/null ++++ b/modules/db_redis/redis_table.c +@@ -0,0 +1,841 @@ +/* + * Copyright (C) 2018 Andreas Granig (sipwise.com) + * @@ -3474,11 +3575,12 @@ Index: kamailio/modules/db_redis/redis_table.c + redis_table_t *table; + redis_key_t *key; + redis_type_t *type; ++ int i, j; + + LM_DBG("dumping all redis tables:\n"); + ht = &con->tables; + -+ for (int i = 0; i < ht->size; ++i) { ++ for (i = 0; i < ht->size; ++i) { + last = (&ht->table[i])->prev; + clist_foreach(&ht->table[i], he, next) { + LM_DBG(" table %.*s\n", he->key.len, he->key.s); @@ -3486,7 +3588,7 @@ Index: kamailio/modules/db_redis/redis_table.c + + LM_DBG(" schema:\n"); + col_ht = &table->columns; -+ for (int j = 0; j < col_ht->size; ++j) { ++ for (j = 0; j < col_ht->size; ++j) { + col_last = (&col_ht->table[j])->prev; + clist_foreach(&col_ht->table[j], col_he, next) { + LM_DBG(" %.*s: %d\n", @@ -3524,6 +3626,7 @@ Index: kamailio/modules/db_redis/redis_table.c + redis_table_t *table; + redis_key_t *key; + redis_type_t *type; ++ int j; + + struct str_hash_table *col_ht; + struct str_hash_entry *col_he; @@ -3544,7 +3647,7 @@ Index: kamailio/modules/db_redis/redis_table.c + + LM_DBG(" schema:\n"); + col_ht = &table->columns; -+ for (int j = 0; j < col_ht->size; ++j) { ++ for (j = 0; j < col_ht->size; ++j) { + col_last = (&col_ht->table[j])->prev; + clist_foreach(&col_ht->table[j], col_he, next) { + LM_DBG(" %.*s: %d\n", @@ -3583,15 +3686,16 @@ Index: kamailio/modules/db_redis/redis_table.c + redis_table_t *table; + redis_key_t *key, *tmpkey; + redis_type_t *type, *tmptype; ++ int i, j; + + ht = &con->tables; -+ for (int i = 0; i < ht->size; ++i) { ++ for (i = 0; i < ht->size; ++i) { + last = (&ht->table[i])->prev; + clist_foreach(&ht->table[i], he, next) { + table = (redis_table_t*) he->u.p; + + col_ht = &table->columns; -+ for (int j = 0; j < col_ht->size; ++j) { ++ for (j = 0; j < col_ht->size; ++j) { + col_last = (&col_ht->table[j])->prev; + clist_foreach(&col_ht->table[j], col_he, next) { + pkg_free(col_he->key.s); @@ -4121,10 +4225,8 @@ Index: kamailio/modules/db_redis/redis_table.c + } + return -1; +} -Index: kamailio/modules/db_redis/redis_table.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/modules/db_redis/redis_table.h 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/modules/db_redis/redis_table.h @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2018 Andreas Granig (sipwise.com) @@ -4169,7 +4271,7 @@ Index: kamailio/modules/db_redis/redis_table.h + +typedef struct redis_table redis_table_t; +struct redis_table { -+ int version; ++ int version; + redis_key_t *entry_keys; + redis_type_t *types; + struct str_hash_table columns; @@ -4192,10 +4294,8 @@ Index: kamailio/modules/db_redis/redis_table.h +int db_redis_keys_spec(char *spec); + +#endif /* _REDIS_TABLE_H_ */ -Index: kamailio/doc/stylesheets/dbschema_k/xsl/db_redis.xsl -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ kamailio/doc/stylesheets/dbschema_k/xsl/db_redis.xsl 2018-02-14 15:23:35.853985199 +0100 +--- /dev/null ++++ b/doc/stylesheets/dbschema_k/xsl/db_redis.xsl @@ -0,0 +1,126 @@ + +