diff --git a/debian/patches/series b/debian/patches/series index a2fac4db2..a895b1dca 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -46,3 +46,4 @@ sipwise/db_redis_skip_not_eq_type_keys.patch sipwise/db_redis_update_type_keys.patch sipwise/db_redis_range_compare_timestamps.patch sipwise/db_redis_bigint_min_len.patch +sipwise/db_redis_use_keys_instead_of_scan.patch diff --git a/debian/patches/sipwise/db_redis_use_keys_instead_of_scan.patch b/debian/patches/sipwise/db_redis_use_keys_instead_of_scan.patch new file mode 100644 index 000000000..bc7a711c2 --- /dev/null +++ b/debian/patches/sipwise/db_redis_use_keys_instead_of_scan.patch @@ -0,0 +1,91 @@ +--- a/src/modules/db_redis/redis_dbase.c ++++ b/src/modules/db_redis/redis_dbase.c +@@ -695,15 +695,21 @@ + + size_t i = 0; + redis_key_t *query_v = NULL; +- char cursor_str[32] = ""; + redisReply *reply = NULL; +- unsigned long cursor = 0; ++ redisReply *keys_list = NULL; + size_t j; + int l; ++ ++ ++#undef USE_SCAN ++ ++#ifdef USE_SCAN ++ ++ char cursor_str[32] = ""; ++ unsigned long cursor = 0; + unsigned int match_count = match_count_start_val; + char match_count_str[16]; + +- + do { + snprintf(cursor_str, sizeof(cursor_str), "%lu", cursor); + +@@ -763,16 +769,37 @@ + } + LM_DBG("cursor is %lu\n", cursor); + +- if (reply->element[1]->type != REDIS_REPLY_ARRAY) { ++ keys_list = reply->element[1]; ++ ++#else // use KEYS ++ ++ if (db_redis_key_add_string(&query_v, "KEYS", 4) != 0) { ++ LM_ERR("Failed to add scan command to scan query\n"); ++ goto err; ++ } ++ if (db_redis_key_add_string(&query_v, match_pattern->s, match_pattern->len) != 0) { ++ LM_ERR("Failed to add match pattern to scan query\n"); ++ goto err; ++ } ++ ++ reply = db_redis_command_argv(con, query_v); ++ db_redis_key_free(&query_v); ++ db_redis_check_reply(con, reply, err); ++ ++ keys_list = reply; ++ ++#endif ++ ++ if (keys_list->type != REDIS_REPLY_ARRAY) { + LM_ERR("Invalid content type for scan on table '%.*s', expected array\n", + match_pattern->len, match_pattern->s); + goto err; + } + +- *query_keys_count += reply->element[1]->elements; ++ *query_keys_count += keys_list->elements; + +- for (j = 0; j < reply->element[1]->elements; ++i, ++j) { +- redisReply *key = reply->element[1]->element[j]; ++ for (j = 0; j < keys_list->elements; ++i, ++j) { ++ redisReply *key = keys_list->element[j]; + if (!key) { + LM_ERR("Invalid null key at cursor result index %lu while scanning table '%.*s'\n", + j, match_pattern->len, match_pattern->s); +@@ -789,14 +816,19 @@ + } + } + ++#ifdef USE_SCAN + // exponential increase and falloff, hovering around 1000 results +- if (reply->element[1]->elements > 1300 && match_count > 500) ++ if (keys_list->elements > 1300 && match_count > 500) + match_count /= 2; +- else if (reply->element[1]->elements < 700 && match_count < 500000) ++ else if (keys_list->elements < 700 && match_count < 500000) + match_count *= 2; ++#endif + + db_redis_free_reply(&reply); ++ ++#ifdef USE_SCAN + } while (cursor > 0); ++#endif + + // for full table scans, we have to manually match all given keys + // but only do this once for repeated invocations