"Fossies" - the Fresh Open Source Software Archive

Member "opensips-3.0.1/modules/sql_cacher/sql_cacher.c" (1 Oct 2019, 52909 Bytes) of package /linux/misc/opensips-3.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sql_cacher.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.0.0_vs_3.0.1.

    1 /**
    2  *
    3  * Copyright (C) 2015 OpenSIPS Foundation
    4  *
    5  * This file is part of opensips, a free SIP server.
    6  *
    7  * opensips is free software; you can redistribute it and/or modify
    8  * it under the terms of the GNU General Public License as published by
    9  * the Free Software Foundation; either version 2 of the License, or
   10  * (at your option) any later version
   11  *
   12  * opensips is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  * GNU General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU General Public License
   18  * along with this program; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
   20  *
   21  * History
   22  * -------
   23  *  2015-09-xx  initial version (Vlad Patrascu)
   24 */
   25 
   26 #include "../../sr_module.h"
   27 #include "../../dprint.h"
   28 #include "../../mem/mem.h"
   29 #include "../../ut.h"
   30 #include "../../trim.h"
   31 #include "../../pvar.h"
   32 #include "../../locking.h"
   33 #include "../../rw_locking.h"
   34 #include "../../timer.h"
   35 #include "../../ipc.h"
   36 #include "sql_cacher.h"
   37 
   38 static int mod_init(void);
   39 static void destroy(void);
   40 static int child_init(int rank);
   41 
   42 int pv_parse_name(pv_spec_p sp, str *in);
   43 int pv_init_param(pv_spec_p sp, int param);
   44 int pv_get_sql_cached_value(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res);
   45 static int parse_cache_entry(unsigned int type, void *val);
   46 static void free_c_entry(cache_entry_t *c);
   47 
   48 static mi_response_t *mi_reload_1(const mi_params_t *params,
   49                                 struct mi_handler *async_hdl);
   50 static mi_response_t *mi_reload_2(const mi_params_t *params,
   51                                 struct mi_handler *async_hdl);
   52 
   53 static str spec_delimiter = str_init(DEFAULT_SPEC_DELIM);
   54 static str pvar_delimiter = str_init(DEFAULT_PVAR_DELIM);
   55 static str columns_delimiter = str_init(DEFAULT_COLUMNS_DELIM);
   56 static int fetch_nr_rows = DEFAULT_FETCH_NR_ROWS;
   57 static int full_caching_expire = DEFAULT_FULL_CACHING_EXPIRE;
   58 static int reload_interval = DEFAULT_RELOAD_INTERVAL;
   59 
   60 static cache_entry_t **entry_list;
   61 static struct queried_key **queries_in_progress;
   62 
   63 /* per process db handlers corresponding to cache entries in entry_list */
   64 static db_handlers_t *db_hdls_list;
   65 
   66 gen_lock_t *queries_lock;
   67 
   68 /* module parameters */
   69 static param_export_t mod_params[] = {
   70     {"spec_delimiter", STR_PARAM, &spec_delimiter.s},
   71     {"pvar_delimiter", STR_PARAM, &pvar_delimiter.s},
   72     {"columns_delimiter", STR_PARAM, &columns_delimiter.s},
   73     {"sql_fetch_nr_rows", INT_PARAM, &fetch_nr_rows},
   74     {"full_caching_expire", INT_PARAM, &full_caching_expire},
   75     {"reload_interval", INT_PARAM, &reload_interval},
   76     {"cache_table", STR_PARAM|USE_FUNC_PARAM, (void *)&parse_cache_entry},
   77     {0,0,0}
   78 };
   79 
   80 static pv_export_t mod_items[] = {
   81     {{"sql_cached_value", sizeof("sql_cached_value") - 1}, 1000,
   82         pv_get_sql_cached_value, 0, pv_parse_name, 0, 0, 0},
   83     { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
   84 };
   85 
   86 static mi_export_t mi_cmds[] = {
   87     { "sql_cacher_reload", "reload the SQL database into the cache", 0, 0, {
   88         {mi_reload_1, {"id", 0}},
   89         {mi_reload_2, {"id", "key", 0}},
   90         {EMPTY_MI_RECIPE}}
   91     },
   92     {EMPTY_MI_EXPORT}
   93 };
   94 
   95 static dep_export_t deps = {
   96     { /* OpenSIPS module dependencies */
   97         { MOD_TYPE_SQLDB, NULL, DEP_ABORT },
   98         { MOD_TYPE_CACHEDB, NULL, DEP_ABORT },
   99         { MOD_TYPE_NULL, NULL, 0 },
  100     },
  101     { /* modparam dependencies */
  102         { NULL, NULL },
  103     },
  104 };
  105 
  106 /**
  107  * module exports
  108  */
  109 struct module_exports exports = {
  110     "sql_cacher",               /* module name */
  111     MOD_TYPE_DEFAULT,           /* class of this module */
  112     MODULE_VERSION,
  113     DEFAULT_DLFLAGS,            /* dlopen flags */
  114     0,                          /* load function */
  115     &deps,                      /* OpenSIPS module dependencies */
  116     0,                          /* exported functions */
  117     0,                          /* exported async functions */
  118     mod_params,                 /* exported parameters */
  119     0,                          /* exported statistics */
  120     mi_cmds,                    /* exported MI functions */
  121     mod_items,                  /* exported pseudo-variables */
  122     0,                          /* exported transformations */
  123     0,                          /* extra processes */
  124     0,                          /* module pre-initialization function */
  125     mod_init,                   /* module initialization function */
  126     0,                          /* response handling function */
  127     destroy,                    /* destroy function */
  128     child_init,                 /* per-child init function */
  129     0                           /* reload confirm function */
  130 };
  131 
  132 static int parse_cache_entry(unsigned int type, void *val)
  133 {
  134     cache_entry_t *new_entry;
  135     char *p1, *p2, *tmp, *c_tmp1, *c_tmp2;
  136     int col_idx;
  137     int rc = -1;
  138     int i;
  139     str parse_str_copy, parse_str;
  140 
  141     if(!entry_list){
  142         entry_list =  shm_malloc(sizeof(cache_entry_t*));
  143         if (!entry_list) {
  144             LM_ERR("No more memory for cache entries list\n");
  145             return -1;
  146         }
  147         *entry_list = NULL;
  148     }
  149 
  150     parse_str.len = strlen((char *)val);
  151     parse_str.s = pkg_malloc(parse_str.len);
  152     if(!parse_str.s){
  153         LM_ERR("No more pkg memory\n");
  154         return -1;
  155     }
  156     memcpy(parse_str.s, (char *)val, parse_str.len);
  157         new_entry = shm_malloc(sizeof(cache_entry_t));
  158         if (!new_entry) {
  159             LM_ERR("No more memory for cache entry struct\n");
  160             return -1;
  161         }
  162         new_entry->id.s = NULL;
  163         new_entry->columns = NULL;
  164         new_entry->nr_columns = 0;
  165         new_entry->on_demand = 0;
  166         new_entry->expire = DEFAULT_ON_DEMAND_EXPIRE;
  167         new_entry->nr_ints = 0;
  168         new_entry->nr_strs = 0;
  169         new_entry->column_types = 0;
  170         new_entry->ref_lock = NULL;
  171 
  172 #define PARSE_TOKEN(_ptr1, _ptr2, field, field_name_str, field_name_len) \
  173     do { \
  174         (_ptr2) = memchr((_ptr1), '=', parse_str.len - \
  175                                             ((_ptr1) - parse_str.s)); \
  176         if (!(_ptr2)) { \
  177             LM_ERR("expected: '=' after %.*s\n", (field_name_len), (field_name_str)); \
  178             goto parse_err; \
  179         } \
  180         if (!memcmp((_ptr1), (field_name_str), (field_name_len))) { \
  181             if (*((_ptr1)+(field_name_len)) != '=') { \
  182                 LM_ERR("expected: '=' after %.*s\n", (field_name_len), (field_name_str)); \
  183                 goto parse_err; \
  184             } \
  185             tmp = memchr((_ptr2) + 1, spec_delimiter.s[0], parse_str.len - \
  186                                                     ((_ptr2) - parse_str.s)); \
  187             if (!tmp) { \
  188                 LM_ERR("expected: %c after value of %.*s\n", spec_delimiter.s[0], \
  189                     (field_name_len), (field_name_str)); \
  190                 goto parse_err; \
  191             } \
  192             new_entry->field.len = tmp - (_ptr2) - 1; \
  193             if (new_entry->field.len <= 0) { \
  194                 LM_ERR("expected value of: %.*s\n", (field_name_len), (field_name_str)); \
  195                 goto parse_err; \
  196             } \
  197             new_entry->field.s = shm_malloc(new_entry->field.len); \
  198             memcpy(new_entry->field.s, p2 + 1, new_entry->field.len); \
  199         } else { \
  200             LM_ERR("expected: %.*s instead of: %.*s\n", (field_name_len), (field_name_str), \
  201                 (field_name_len), (_ptr1)); \
  202             goto parse_err; \
  203         } \
  204     } while (0)
  205 
  206         parse_str_copy = parse_str;
  207         trim(&parse_str);
  208         /* parse the id */
  209         p1 = parse_str.s;
  210         PARSE_TOKEN(p1, p2, id, ID_STR, ID_STR_LEN);
  211         /* parse the db_url */
  212         p1 = tmp + 1;
  213         PARSE_TOKEN(p1, p2, db_url, DB_URL_STR, DB_URL_LEN);
  214         /* parse the cachedb_url */
  215         p1 = tmp + 1;
  216         PARSE_TOKEN(p1, p2, cachedb_url, CACHEDB_URL_STR, CACHEDB_URL_LEN);
  217         /* parse the table name */
  218         p1 = tmp + 1;
  219         PARSE_TOKEN(p1, p2, table, TABLE_STR, TABLE_STR_LEN);
  220 #undef PARSE_TOKEN
  221 
  222         /* parse the key column name */
  223         p1 = tmp + 1;
  224         p2 = memchr(p1, '=', parse_str.len - (p1 - parse_str.s));
  225         if (!p2) {
  226             LM_ERR("expected: '=' after %.*s\n", KEY_STR_LEN, KEY_STR);
  227             goto parse_err;
  228         }
  229         if (!memcmp(p1, KEY_STR, KEY_STR_LEN)) {
  230             if (*(p1+KEY_STR_LEN) != '=') { \
  231                 LM_ERR("expected: '=' after %.*s\n", KEY_STR_LEN, KEY_STR);
  232                 goto parse_err;
  233             }
  234 
  235             tmp = memchr(p2 + 1, spec_delimiter.s[0],
  236                         parse_str.len - (p2 - parse_str.s));
  237             if (!tmp) /* delimiter not found, reached the end of the string to parse */
  238                 new_entry->key.len = parse_str.len - (p2 - parse_str.s + 1);
  239             else
  240                 new_entry->key.len = tmp - p2 - 1;
  241 
  242             if (new_entry->key.len <= 0) {
  243                 LM_ERR("expected value of: %.*s\n", KEY_STR_LEN, KEY_STR);
  244                 goto parse_err;
  245             }
  246 
  247             new_entry->key.s = shm_malloc(new_entry->key.len);
  248             memcpy(new_entry->key.s, p2 + 1, new_entry->key.len);
  249 
  250             if (!tmp)
  251                 goto end_parsing;
  252         } else {
  253             LM_ERR("expected: %.*s instead of: %.*s\n", (KEY_STR_LEN), (KEY_STR), \
  254                 KEY_STR_LEN, p1);
  255             goto parse_err;
  256         }
  257 
  258         /* parse the required column names if present */
  259         p1 = tmp + 1;
  260         p2 = memchr(p1, '=', parse_str.len - (p1 - parse_str.s));
  261         if (!p2) {
  262             LM_ERR("expected: '='\n");
  263             goto parse_err;
  264         }
  265         if (!memcmp(p1, COLUMNS_STR, COLUMNS_STR_LEN)) {
  266             if (*(p1+COLUMNS_STR_LEN) != '=') { \
  267                 LM_ERR("expected: '=' after: %.*s\n", COLUMNS_STR_LEN, COLUMNS_STR);
  268                 goto parse_err;
  269             }
  270             col_idx = 0;
  271             tmp = memchr(p2 + 1, spec_delimiter.s[0],
  272                         parse_str.len - (p2 - parse_str.s));
  273             /* just count how many columns there are */
  274             new_entry->nr_columns = 1;
  275             c_tmp1 = memchr(p2 + 1, columns_delimiter.s[0],
  276                             parse_str.len - (p2 - parse_str.s + 1));
  277             while (c_tmp1) {
  278                 new_entry->nr_columns++;
  279                 c_tmp1 = memchr(c_tmp1 + 1, columns_delimiter.s[0],
  280                                 parse_str.len - (c_tmp1 - parse_str.s + 1));
  281             }
  282 
  283             if (new_entry->nr_columns > sizeof(long long) * 8) {
  284                 LM_WARN("Too many columns, maximum number is %zu\n", sizeof(long long) * 8);
  285                 goto parse_err;
  286             }
  287             /* allocate array of columns and actually parse */
  288             new_entry->columns = shm_malloc(new_entry->nr_columns * sizeof(str*));
  289 
  290             c_tmp1 = p2 + 1;
  291             c_tmp2 = memchr(p2 + 1, columns_delimiter.s[0],
  292                         parse_str.len - (p2 - parse_str.s + 1));
  293             while (c_tmp2) {
  294                 new_entry->columns[col_idx] = shm_malloc(sizeof(str));
  295                 (*new_entry->columns[col_idx]).len = c_tmp2 - c_tmp1;
  296                 if ((*new_entry->columns[col_idx]).len <= 0) {
  297                     LM_ERR("expected name of column\n");
  298                     goto parse_err;
  299                 }
  300                 (*new_entry->columns[col_idx]).s = shm_malloc((*new_entry->columns[col_idx]).len);
  301                 memcpy((*new_entry->columns[col_idx]).s, c_tmp1, (*new_entry->columns[col_idx]).len);
  302 
  303                 c_tmp1 = c_tmp2 + 1;
  304                 c_tmp2 = memchr(c_tmp1, columns_delimiter.s[0],
  305                             parse_str.len - (c_tmp1 - parse_str.s + 1));
  306                 col_idx++;
  307             }
  308 
  309             new_entry->columns[col_idx] = shm_malloc(sizeof(str));
  310             if (!tmp)
  311                 (*new_entry->columns[col_idx]).len = parse_str.len - (p2 - c_tmp1 + 1);
  312             else
  313                 (*new_entry->columns[col_idx]).len = tmp - c_tmp1;
  314 
  315             if ((*new_entry->columns[col_idx]).len <= 0) {
  316                 LM_ERR("expected name of column\n");
  317                 goto parse_err;
  318             }
  319             (*new_entry->columns[col_idx]).s = shm_malloc((*new_entry->columns[col_idx]).len);
  320             memcpy((*new_entry->columns[col_idx]).s, c_tmp1, (*new_entry->columns[col_idx]).len);
  321 
  322             if (!tmp) /* delimiter not found, reached the end of the string to parse */
  323                 goto end_parsing;
  324             else {
  325                 p1 = tmp + 1;
  326                 p2 = memchr(p1, '=', parse_str.len - (p1 - parse_str.s));
  327                 if (!p2) {
  328                     LM_ERR("expected: '='\n");
  329                     goto parse_err;
  330                 }
  331             }
  332         }
  333 
  334         /* parse on demand parameter */
  335         if (!memcmp(p1, ONDEMAND_STR, ONDEMAND_STR_LEN)) {
  336             if (*(p1+ONDEMAND_STR_LEN) != '=') { \
  337                 LM_ERR("expected: '=' after: %.*s\n", ONDEMAND_STR_LEN, ONDEMAND_STR);
  338                 goto parse_err;
  339             }
  340             tmp = memchr(p2 + 1, spec_delimiter.s[0],
  341                     parse_str.len - (p2 - parse_str.s));
  342             str str_val;
  343             if (!tmp) /* delimiter not found, reached the end of the string to parse */
  344                 str_val.len = parse_str.len - (p2 - parse_str.s + 1);
  345             else
  346                 str_val.len = tmp - p2 - 1;
  347 
  348             if (str_val.len <= 0) {
  349                 LM_ERR("expected value of: %.*s\n", ONDEMAND_STR_LEN, ONDEMAND_STR);
  350                 goto parse_err;
  351             }
  352             str_val.s = p2 + 1; 
  353             if(str2int(&str_val, &new_entry->on_demand)) {
  354                 LM_ERR("expected integer value for: %.*s instead of: %.*s\n",
  355                         ONDEMAND_STR_LEN, ONDEMAND_STR, str_val.len, str_val.s);
  356                 goto parse_err;
  357             }
  358 
  359             if (!tmp) /* delimiter not found, reached the end of the string to parse */
  360                 goto end_parsing;
  361             else {
  362                 p1 = tmp + 1;
  363                 p2 = memchr(p1, '=', parse_str.len - (p1 - parse_str.s));
  364                 if (!p2) {
  365                     LM_ERR("expected: '='\n");
  366                     goto parse_err;
  367                 }
  368             }
  369         }
  370 
  371         /* parse expire parameter */
  372         if (!memcmp(p1, EXPIRE_STR, EXPIRE_STR_LEN)) {
  373             str str_val;
  374             str_val.len = parse_str.len - (p2 - parse_str.s + 1);
  375             if (str_val.len <= 0) {
  376                 LM_ERR("expected value of: %.*s\n", EXPIRE_STR_LEN, EXPIRE_STR);
  377                 goto parse_err;
  378             }
  379             str_val.s = p2 + 1; 
  380             if(str2int(&str_val, &new_entry->expire)) {
  381                 LM_ERR("expected integer value for: %.*s instead of: %.*s\n",
  382                         EXPIRE_STR_LEN, EXPIRE_STR, str_val.len, str_val.s);
  383                 goto parse_err;
  384             }
  385         } else {
  386             LM_ERR("unknown parameter: %.*s\n",
  387                 (int)(parse_str.len - (p1 - parse_str.s)), p1);
  388             goto parse_err;
  389         }
  390 
  391 end_parsing:
  392         new_entry->next = NULL;
  393         if (*entry_list)
  394             new_entry->next = *entry_list;
  395         *entry_list = new_entry;
  396 
  397         pkg_free(parse_str_copy.s);
  398         return 0;
  399 parse_err:
  400         if (!new_entry->id.s)
  401             LM_WARN("invalid cache entry specification: %.*s\n",
  402                 parse_str.len, parse_str.s);
  403         else
  404             LM_WARN("invalid cache entry specification for id: %.*s\n",
  405                 new_entry->id.len, new_entry->id.s);
  406 
  407         if (new_entry->columns) {
  408             for (i=0; i < new_entry->nr_columns; i++)
  409                 if (new_entry->columns[i]) {
  410                     if ((*new_entry->columns[i]).s)
  411                         shm_free((*new_entry->columns[i]).s);
  412                     shm_free(new_entry->columns[i]);
  413                 }
  414             shm_free(new_entry->columns);
  415         }
  416         shm_free(new_entry);
  417         pkg_free(parse_str_copy.s);
  418 
  419     return rc;
  420 }
  421 
  422 /* get the column types from the sql query result */
  423 static int get_column_types(cache_entry_t *c_entry, db_val_t *values, int nr_columns)
  424 {
  425     unsigned int i;
  426     db_type_t val_type;
  427 
  428     c_entry->nr_ints = 0;
  429     c_entry->nr_strs = 0;
  430     c_entry->column_types = 0;
  431 
  432     for (i = 0; i < nr_columns; i++) {
  433         val_type = VAL_TYPE(values + i);
  434         switch (val_type) {
  435             case DB_INT:
  436             case DB_BIGINT:
  437             case DB_DOUBLE:
  438                 c_entry->nr_ints++;
  439                 c_entry->column_types &= ~(1LL << i);
  440                 break;
  441             case DB_STRING:
  442             case DB_STR:
  443             case DB_BLOB:
  444                 c_entry->nr_strs++;
  445                 c_entry->column_types |= (1LL << i);
  446                 break;
  447             default:
  448                 LM_ERR("Unsupported type: %d for column: %.*s\n", val_type,
  449                     c_entry->columns[i]->len, c_entry->columns[i]->s);
  450                 return -1;
  451         }
  452     }
  453 
  454     return 0;
  455 }
  456 
  457 /* returns the total size of the actual value which will be stored in the cachedb*/
  458 static unsigned int get_cdb_val_size(cache_entry_t *c_entry, db_val_t *values, int nr_columns)
  459 {
  460     unsigned int i, len = 0;
  461     db_type_t val_type;
  462 
  463     /* reload version + integer values + offsets of the string values */
  464     len = INT_B64_ENC_LEN + c_entry->nr_ints*INT_B64_ENC_LEN + c_entry->nr_strs*INT_B64_ENC_LEN;
  465     /* length of the actual string values*/
  466     for (i = 0; i < nr_columns; i++) {
  467         val_type = VAL_TYPE(values + i);
  468         switch (val_type) {
  469             case DB_STRING:
  470                 len += strlen(VAL_STRING(values + i));
  471                 break;
  472             case DB_STR:
  473                 len += VAL_STR(values + i).len;
  474                 break;
  475             case DB_BLOB:
  476                 len += VAL_BLOB(values + i).len;
  477                 break;
  478             default: continue;
  479         }
  480     }
  481 
  482     return len;
  483 }
  484 
  485 static int insert_in_cachedb(cache_entry_t *c_entry, db_handlers_t *db_hdls,
  486             db_val_t *key, db_val_t *values, int reload_version, int nr_columns)
  487 {
  488     unsigned int i, offset = 0, strs_offset = 0;
  489     int int_val;
  490     int int_key_len = 0, rc = 0;
  491     char int_buf[4], int_enc_buf[INT_B64_ENC_LEN];
  492     char *int_key_buf = NULL;
  493     str str_val;
  494     db_type_t val_type;
  495     str str_key = STR_NULL;
  496     str cdb_val;
  497     str cdb_key = STR_NULL;
  498 
  499     cdb_val.len = get_cdb_val_size(c_entry, values, nr_columns);
  500     cdb_val.s = pkg_malloc(cdb_val.len);
  501     if (!cdb_val.s) {
  502         LM_ERR("No more pkg memory\n");
  503         return -1;
  504     }
  505 
  506     /* store the reload version (base64 encoded) */
  507     memcpy(int_buf, &reload_version, 4);
  508     base64encode((unsigned char *)int_enc_buf, (unsigned char *)int_buf, 4);
  509     memcpy(cdb_val.s, int_enc_buf, INT_B64_ENC_LEN);
  510 
  511     offset += INT_B64_ENC_LEN;
  512 
  513     /* store the integer values (base64 encoded) */
  514     for (i = 0; i < nr_columns; i++) {
  515         int_val = 0;
  516         val_type = VAL_TYPE(values + i);
  517 
  518         switch (val_type) {
  519             case DB_INT:
  520                 int_val = VAL_INT(values + i);
  521                 break;
  522             case DB_BIGINT:
  523                 int_val = (int)VAL_BIGINT(values + i);
  524                 break;
  525             case DB_DOUBLE:
  526                 int_val = (int)VAL_DOUBLE(values + i);
  527                 break;
  528             default: continue;
  529         }
  530         if (VAL_NULL(values + i))
  531             memset(int_enc_buf, 0, INT_B64_ENC_LEN);
  532         else {
  533             memcpy(int_buf, &int_val, 4);
  534             base64encode((unsigned char *)int_enc_buf, (unsigned char *)int_buf, 4);
  535         }
  536 
  537         memcpy(cdb_val.s + offset, int_enc_buf, INT_B64_ENC_LEN);
  538 
  539         offset += INT_B64_ENC_LEN;
  540     }
  541 
  542     /* store the string values and their offsets as integers (base64 encoded) */
  543     strs_offset = offset + c_entry->nr_strs * INT_B64_ENC_LEN;
  544 
  545     for (i = 0; i < nr_columns; i++) {
  546         val_type = VAL_TYPE(values + i);
  547         switch (val_type) {
  548             case DB_STRING:
  549                 str_val.s = (char *)VAL_STRING(values + i);
  550                 str_val.len = strlen(str_val.s);
  551                 break;
  552             case DB_STR:
  553                 str_val = VAL_STR(values + i);
  554                 break;
  555             case DB_BLOB:
  556                 str_val = VAL_BLOB(values + i);
  557                 break;
  558             default: continue;
  559         }
  560         if (VAL_NULL(values + i))
  561             int_val = 0;
  562         else
  563             int_val = strs_offset;
  564 
  565         memcpy(int_buf, &int_val, 4);
  566         base64encode((unsigned char *)int_enc_buf, (unsigned char *)int_buf, 4);
  567         memcpy(cdb_val.s + offset, int_enc_buf, INT_B64_ENC_LEN);
  568 
  569         offset += INT_B64_ENC_LEN;
  570 
  571         memcpy(cdb_val.s + strs_offset, str_val.s, str_val.len);
  572         strs_offset += str_val.len;
  573     }
  574 
  575     /* make sure the key is string */
  576     val_type = VAL_TYPE(key);
  577     switch (val_type) {
  578         case DB_STRING:
  579             str_key.s = (char *)VAL_STRING(key);
  580             str_key.len = strlen(str_key.s);
  581             break;
  582         case DB_STR:
  583             str_key = VAL_STR(key);
  584             break;
  585         case DB_BLOB:
  586             str_key = VAL_BLOB(key);
  587             break;
  588         case DB_INT:
  589             int_key_buf = sint2str(VAL_INT(key), &int_key_len);
  590             break;
  591         case DB_BIGINT:
  592             int_val = (int)VAL_BIGINT(key);
  593             int_key_buf = sint2str(int_val, &int_key_len);
  594             break;
  595         case DB_DOUBLE:
  596             int_val = (int)VAL_DOUBLE(key);
  597             int_key_buf = sint2str(int_val, &int_key_len);
  598             break;
  599         default:
  600             LM_ERR("Unsupported type for SQL DB key column\n");
  601             rc = -1;
  602             goto out;
  603     }
  604     if (int_key_len) {
  605         str_key.s = int_key_buf;
  606         str_key.len = int_key_len;
  607     }
  608 
  609     cdb_key.len = c_entry->id.len + str_key.len;
  610     cdb_key.s = pkg_malloc(cdb_key.len);
  611     if (!cdb_key.s) {
  612         LM_ERR("No more pkg memory\n");
  613         rc = -1;
  614         goto out;
  615     }
  616     memcpy(cdb_key.s, c_entry->id.s, c_entry->id.len);
  617     memcpy(cdb_key.s + c_entry->id.len, str_key.s, str_key.len);
  618 
  619     if (db_hdls->cdbf.set(db_hdls->cdbcon, &cdb_key, &cdb_val, c_entry->expire) < 0) {
  620         LM_ERR("Failed to insert the values for key: %.*s in cachedb\n",
  621             str_key.len, str_key.s);
  622         rc = -1;
  623     }
  624 
  625 out:
  626     pkg_free(cdb_key.s);
  627     pkg_free(cdb_val.s);
  628     return rc;
  629 }
  630 
  631 static db_handlers_t *db_init_test_conn(cache_entry_t *c_entry)
  632 {
  633     db_handlers_t *new_db_hdls;
  634     str test_query_key_str = str_init(TEST_QUERY_STR);
  635     str cdb_test_key = str_init(CDB_TEST_KEY_STR);
  636     str cdb_test_val = str_init(CDB_TEST_VAL_STR);
  637     db_key_t query_key_col;
  638     db_val_t query_key_val;
  639     db_res_t *sql_res;
  640     str cachedb_res;
  641     unsigned int i;
  642     int rc;
  643 
  644     new_db_hdls = pkg_malloc(sizeof(db_handlers_t));
  645     if (!new_db_hdls) {
  646         LM_ERR("No more pkg memory for db handlers\n");
  647         return NULL;
  648     }
  649     new_db_hdls->c_entry = c_entry;
  650     new_db_hdls->db_con = 0;
  651     new_db_hdls->query_ps = NULL;
  652     new_db_hdls->cdbcon = 0;
  653 
  654     /* cachedb init and test connection */
  655     if (cachedb_bind_mod(&c_entry->cachedb_url, &new_db_hdls->cdbf) < 0) {
  656         LM_ERR("Unable to bind to a cachedb database driver for URL: %.*s\n",
  657             c_entry->cachedb_url.len, c_entry->cachedb_url.s);
  658         return NULL;
  659     }
  660     /* open a test connection */
  661     new_db_hdls->cdbcon = new_db_hdls->cdbf.init(&c_entry->cachedb_url);
  662     if (!new_db_hdls->cdbcon) {
  663         LM_ERR("Cannot init connection to cachedb: %.*s\n",
  664             c_entry->cachedb_url.len, c_entry->cachedb_url.s);
  665         return NULL;
  666     }
  667     /* setting and getting a test key in cachedb */
  668     if (new_db_hdls->cdbf.set(new_db_hdls->cdbcon, &cdb_test_key, &cdb_test_val,
  669         0) < 0) {
  670         LM_ERR("Failed to set test key in cachedb: %.*s\n",
  671             c_entry->cachedb_url.len, c_entry->cachedb_url.s);
  672         new_db_hdls->cdbf.destroy(new_db_hdls->cdbcon);
  673         new_db_hdls->cdbcon = 0;
  674         return NULL;
  675     }
  676     if (new_db_hdls->cdbf.get(new_db_hdls->cdbcon, &cdb_test_key, &cachedb_res) < 0) {
  677         LM_ERR("Failed to get test key from cachedb: %.*s\n",
  678             c_entry->cachedb_url.len, c_entry->cachedb_url.s);
  679         new_db_hdls->cdbf.destroy(new_db_hdls->cdbcon);
  680         new_db_hdls->cdbcon = 0;
  681         return NULL;
  682     }
  683     rc = str_strcmp(&cachedb_res, &cdb_test_val);
  684     pkg_free(cachedb_res.s);
  685     if (rc != 0) {
  686         LM_ERR("Inconsistent test key for cachedb: %.*s\n",
  687             c_entry->cachedb_url.len, c_entry->cachedb_url.s);
  688         new_db_hdls->cdbf.destroy(new_db_hdls->cdbcon);
  689         new_db_hdls->cdbcon = 0;
  690         return NULL;
  691     }
  692 
  693     /* SQL DB init and test connection */
  694     if (db_bind_mod(&c_entry->db_url, &new_db_hdls->db_funcs) < 0) {
  695         LM_ERR("Unable to bind to a SQL database driver for URL: %.*s\n",
  696             c_entry->db_url.len, c_entry->db_url.s);
  697         return NULL;
  698     }
  699     /* open a test connection */
  700     if ((new_db_hdls->db_con = new_db_hdls->db_funcs.init(&c_entry->db_url)) == 0) {
  701         LM_ERR("Cannot init connection to SQL DB: %.*s\n",
  702             c_entry->db_url.len, c_entry->db_url.s);
  703         return NULL;
  704     }
  705 
  706     /* verify the column names by running a test query with a bogus key */
  707     if (new_db_hdls->db_funcs.use_table(new_db_hdls->db_con, &c_entry->table) < 0) {
  708         LM_ERR("Invalid table name: %.*s\n", c_entry->table.len, c_entry->table.s);
  709         new_db_hdls->db_funcs.close(new_db_hdls->db_con);
  710         new_db_hdls->db_con = 0;
  711         return NULL;
  712     }
  713 
  714     VAL_NULL(&query_key_val) = 0;
  715     VAL_TYPE(&query_key_val) = DB_STR;
  716     VAL_STR(&query_key_val) = test_query_key_str;
  717 
  718     query_key_col = &c_entry->key;
  719 
  720     if (new_db_hdls->db_funcs.query(new_db_hdls->db_con, &query_key_col, 0,
  721         &query_key_val, c_entry->columns, 1, c_entry->nr_columns, 0, &sql_res) != 0) {
  722         LM_ERR("Failure to issuse test query to SQL DB: %.*s\n",
  723             c_entry->db_url.len, c_entry->db_url.s);
  724         new_db_hdls->db_funcs.close(new_db_hdls->db_con);
  725         new_db_hdls->db_con = 0;
  726         return NULL;
  727     }
  728 
  729     /* no columns specified in cache entry -> cache entire table and get column
  730      * names from the sql result */
  731     if (!c_entry->columns) {
  732         c_entry->nr_columns = RES_COL_N(sql_res);
  733         c_entry->columns = shm_malloc(c_entry->nr_columns * sizeof(str*));
  734         for (i = 0; i < c_entry->nr_columns; i++) {
  735             c_entry->columns[i] = shm_malloc(sizeof(str));
  736             (*c_entry->columns[i]).len = RES_NAMES(sql_res)[i]->len;
  737             (*c_entry->columns[i]).s = shm_malloc((*c_entry->columns[i]).len);
  738             memcpy((*c_entry->columns[i]).s, RES_NAMES(sql_res)[i]->s,
  739                 (*c_entry->columns[i]).len);
  740         }
  741     }
  742 
  743     new_db_hdls->db_funcs.free_result(new_db_hdls->db_con, sql_res);
  744     return new_db_hdls;
  745 }
  746 
  747 static int inc_cache_rld_vers(db_handlers_t *db_hdls, int *rld_vers)
  748 {
  749     str rld_vers_key;
  750 
  751     rld_vers_key.len = db_hdls->c_entry->id.len + 23;
  752     rld_vers_key.s = pkg_malloc(rld_vers_key.len);
  753     if (!rld_vers_key.s) {
  754         LM_ERR("No more pkg memory\n");
  755         return -1;
  756     }
  757     memcpy(rld_vers_key.s, db_hdls->c_entry->id.s, db_hdls->c_entry->id.len);
  758     memcpy(rld_vers_key.s + db_hdls->c_entry->id.len, "_sql_cacher_reload_vers", 23);
  759 
  760     if (db_hdls->cdbf.add(db_hdls->cdbcon, &rld_vers_key, 1, 0, rld_vers) < 0) {
  761         LM_DBG("Failed to increment reload version integer from cachedb\n");
  762         pkg_free(rld_vers_key.s);
  763         return -1;
  764     }
  765 
  766     pkg_free(rld_vers_key.s);
  767 
  768     return 0;
  769 }
  770 
  771 static int load_entire_table(cache_entry_t *c_entry, db_handlers_t *db_hdls,
  772                                 int inc_rld_vers)
  773 {
  774     db_key_t *query_cols = NULL;
  775     db_res_t *sql_res = NULL;
  776     db_row_t *row;
  777     db_val_t *values;
  778     int i;
  779     int reload_vers = 0;
  780 
  781     query_cols = pkg_malloc((c_entry->nr_columns + 1) * sizeof(db_key_t));
  782     if (!query_cols) {
  783         LM_ERR("No more pkg memory\n");
  784         return -1;
  785     }
  786     query_cols[0] = &(c_entry->key);
  787     for (i=0; i < c_entry->nr_columns; i++)
  788         query_cols[i+1] = &((*c_entry->columns[i]));
  789 
  790     /* query the entire table */
  791     if (db_hdls->db_funcs.use_table(db_hdls->db_con, &c_entry->table) < 0) {
  792         LM_ERR("Invalid table name: %.*s\n", c_entry->table.len, c_entry->table.s);
  793         db_hdls->db_funcs.close(db_hdls->db_con);
  794         db_hdls->db_con = 0;
  795         pkg_free(query_cols);
  796         return -1;
  797     }
  798     if (DB_CAPABILITY(db_hdls->db_funcs, DB_CAP_FETCH)) {
  799         if (db_hdls->db_funcs.query(db_hdls->db_con, NULL, 0, NULL,
  800                         query_cols, 0, c_entry->nr_columns + 1, 0, 0) != 0) {
  801             LM_ERR("Failure to issue query to SQL DB: %.*s\n",
  802             c_entry->db_url.len, c_entry->db_url.s);
  803             pkg_free(query_cols);
  804             goto error;
  805         }
  806 
  807         if (db_hdls->db_funcs.fetch_result(db_hdls->db_con,&sql_res,fetch_nr_rows)<0) {
  808             LM_ERR("Error fetching rows from SQL DB: %.*s\n",
  809             c_entry->db_url.len, c_entry->db_url.s);
  810             pkg_free(query_cols);
  811             goto error;
  812         }
  813     } else {
  814         if (db_hdls->db_funcs.query(db_hdls->db_con, NULL, 0, NULL,
  815                         query_cols, 0, c_entry->nr_columns + 1, 0, &sql_res) != 0) {
  816             LM_ERR("Failure to issue query to SQL DB: %.*s\n",
  817             c_entry->db_url.len, c_entry->db_url.s);
  818             pkg_free(query_cols);
  819             goto error;
  820         }
  821     }
  822 
  823     pkg_free(query_cols);
  824 
  825     lock_start_write(db_hdls->c_entry->ref_lock);
  826 
  827     if (inc_rld_vers && inc_cache_rld_vers(db_hdls, &reload_vers) < 0) {
  828         lock_stop_write(db_hdls->c_entry->ref_lock);
  829         goto error;
  830     }
  831 
  832     /* anything loaded ? if not, we can do a quick exit here */
  833     if (RES_ROW_N(sql_res) == 0) {
  834         lock_stop_write(db_hdls->c_entry->ref_lock);
  835         db_hdls->db_funcs.free_result(db_hdls->db_con, sql_res);
  836         return 0;
  837     }
  838 
  839     row = RES_ROWS(sql_res);
  840     values = ROW_VALUES(row);
  841     if (get_column_types(c_entry, values + 1, ROW_N(row) - 1) < 0) {
  842         lock_stop_write(db_hdls->c_entry->ref_lock);
  843         goto error;
  844     }
  845 
  846     /* load the rows into the cahchedb */
  847     do {
  848         for (i=0; i < RES_ROW_N(sql_res); i++) {
  849             row = RES_ROWS(sql_res) + i;
  850             values = ROW_VALUES(row);
  851             if (!VAL_NULL(values))
  852                 if (insert_in_cachedb(c_entry, db_hdls, values ,values + 1,
  853                     reload_vers, ROW_N(row) - 1) < 0) {
  854                     lock_stop_write(db_hdls->c_entry->ref_lock);
  855                     return -1;
  856                 }
  857         }
  858 
  859         if (DB_CAPABILITY(db_hdls->db_funcs, DB_CAP_FETCH)) {
  860             if (db_hdls->db_funcs.fetch_result(db_hdls->db_con,&sql_res,fetch_nr_rows)<0) {
  861                 LM_ERR("Error fetching rows (1) from SQL DB: %.*s\n",
  862                     c_entry->db_url.len, c_entry->db_url.s);
  863                 lock_stop_write(db_hdls->c_entry->ref_lock);
  864                 goto error;
  865             }
  866         } else {
  867             break;
  868         }
  869     } while (RES_ROW_N(sql_res) > 0);
  870 
  871     lock_stop_write(db_hdls->c_entry->ref_lock);
  872 
  873     db_hdls->db_funcs.free_result(db_hdls->db_con, sql_res);
  874     return 0;
  875 
  876 error:
  877     if (sql_res)
  878         db_hdls->db_funcs.free_result(db_hdls->db_con, sql_res);
  879     return -1;
  880 }
  881 
  882 /*  return:
  883  *  0 - succes
  884  * -1 - error
  885  * -2 - not found in sql db
  886  */
  887 static int load_key(cache_entry_t *c_entry, db_handlers_t *db_hdls, str key,
  888                 db_val_t **values, db_res_t **sql_res, int rld_vers)
  889 {
  890     db_key_t key_col;
  891     db_row_t *row;
  892     db_val_t key_val;
  893     str src_key, null_val;
  894 
  895     src_key.len = c_entry->id.len + key.len;
  896     src_key.s = pkg_malloc(src_key.len);
  897     if (!src_key.s) {
  898         LM_ERR("No more shm memory\n");
  899         return -1;
  900     }
  901     memcpy(src_key.s, c_entry->id.s, c_entry->id.len);
  902     memcpy(src_key.s + c_entry->id.len, key.s, key.len);
  903 
  904     key_col = &(c_entry->key);
  905     VAL_NULL(&key_val) = 0;
  906     VAL_TYPE(&key_val) = DB_STR;
  907     VAL_STR(&key_val) = key;
  908 
  909     if (db_hdls->db_funcs.use_table(db_hdls->db_con, &c_entry->table) < 0) {
  910         LM_ERR("Invalid table name: %.*s\n", c_entry->table.len, c_entry->table.s);
  911         db_hdls->db_funcs.close(db_hdls->db_con);
  912         db_hdls->db_con = 0;
  913         goto out_error;
  914     }
  915 
  916     CON_PS_REFERENCE(db_hdls->db_con) = &db_hdls->query_ps;
  917     if (db_hdls->db_funcs.query(db_hdls->db_con,
  918         &key_col, 0, &key_val, c_entry->columns, 1,
  919         c_entry->nr_columns, 0, sql_res) != 0) {
  920         LM_ERR("Failure to issue query to SQL DB: %.*s\n",
  921             c_entry->db_url.len, c_entry->db_url.s);
  922         goto sql_error;
  923     }
  924 
  925     if (RES_ROW_N(*sql_res) == 0) {
  926         LM_DBG("key %.*s not found in SQL db\n", key.len, key.s);
  927         null_val.len = 0;
  928         null_val.s = NULL;
  929         if (db_hdls->cdbf.set(db_hdls->cdbcon, &src_key, &null_val, c_entry->expire) < 0) {
  930             LM_ERR("Failed to insert null in cachedb\n");
  931             goto sql_error;
  932         }
  933 
  934         pkg_free(src_key.s);
  935         db_hdls->db_funcs.free_result(db_hdls->db_con, *sql_res);
  936         return -2;
  937 
  938     } else if (RES_ROW_N(*sql_res) > 1) {
  939         LM_ERR("SQL query returned multiple rows\n");
  940         goto sql_error;
  941     }
  942 
  943     row = RES_ROWS(*sql_res);
  944     *values = ROW_VALUES(row);
  945 
  946     if (c_entry->nr_ints + c_entry->nr_strs == 0 &&
  947         get_column_types(c_entry, *values, ROW_N(row)) < 0)
  948         goto sql_error;
  949 
  950     if (insert_in_cachedb(c_entry, db_hdls, &key_val, *values, rld_vers, ROW_N(row)) < 0)
  951         goto sql_error;
  952 
  953     pkg_free(src_key.s);
  954     return 0;
  955 
  956 sql_error:
  957     if (*sql_res)
  958         db_hdls->db_funcs.free_result(db_hdls->db_con, *sql_res);
  959 out_error:
  960     pkg_free(src_key.s);
  961     return -1;
  962 }
  963 
  964 static int get_rld_vers_from_cache(cache_entry_t *c_entry, db_handlers_t *db_hdls)
  965 {
  966     str rld_vers_key;
  967     int rld_vers = -1;
  968 
  969     rld_vers_key.len = c_entry->id.len + 23;
  970     rld_vers_key.s = pkg_malloc(rld_vers_key.len);
  971     if (!rld_vers_key.s) {
  972         LM_ERR("No more pkg memory\n");
  973         return -1;
  974     }
  975     memcpy(rld_vers_key.s, c_entry->id.s, c_entry->id.len);
  976     memcpy(rld_vers_key.s + c_entry->id.len, "_sql_cacher_reload_vers", 23);
  977 
  978     if (db_hdls->cdbf.get_counter(db_hdls->cdbcon, &rld_vers_key, &rld_vers) < 0) {
  979         LM_ERR("Failed to get reload version integer from cachedb\n");
  980         pkg_free(rld_vers_key.s);
  981         return -1;
  982     }
  983 
  984     pkg_free(rld_vers_key.s);
  985 
  986     return rld_vers;
  987 }
  988 
  989 void reload_timer(unsigned int ticks, void *param)
  990 {
  991     db_handlers_t *db_hdls;
  992 
  993     for (db_hdls = db_hdls_list; db_hdls; db_hdls = db_hdls->next) {
  994         if (db_hdls->c_entry->on_demand)
  995             continue;
  996 
  997         if (load_entire_table(db_hdls->c_entry, db_hdls, 1) < 0)
  998             LM_ERR("Failed to reload table %.*s\n", db_hdls->c_entry->table.len,
  999                 db_hdls->c_entry->table.s);
 1000     }
 1001 }
 1002 
 1003 static mi_item_t *mi_reload(const mi_params_t *params, str *key)
 1004 {
 1005     db_handlers_t *db_hdls;
 1006     db_val_t *values;
 1007     db_res_t *sql_res = NULL;
 1008     struct queried_key *it;
 1009     str entry_id, src_key;
 1010     int rld_vers, rc;
 1011 
 1012     if (get_mi_string_param(params, "id", &entry_id.s, &entry_id.len) < 0)
 1013         return init_mi_param_error();
 1014 
 1015     for (db_hdls = db_hdls_list; db_hdls; db_hdls = db_hdls->next)
 1016         if (!str_strcmp(&db_hdls->c_entry->id, &entry_id))
 1017             break;
 1018     if (!db_hdls) {
 1019         LM_ERR("Entry %.*s not found\n", entry_id.len, entry_id.s);
 1020         return init_mi_error(500, MI_SSTR("ERROR Cache entry not found"));
 1021     }
 1022 
 1023     if (db_hdls->c_entry->on_demand) {
 1024         if (key) {
 1025             src_key.len = db_hdls->c_entry->id.len + key->len;
 1026             src_key.s = pkg_malloc(src_key.len);
 1027             if (!src_key.s) {
 1028                 LM_ERR("No more pkg memory\n");
 1029                 return NULL;
 1030             }
 1031             memcpy(src_key.s, db_hdls->c_entry->id.s, db_hdls->c_entry->id.len);
 1032             memcpy(src_key.s + db_hdls->c_entry->id.len, key->s, key->len);
 1033 
 1034             lock_get(queries_lock);
 1035 
 1036             for (it = *queries_in_progress; it; it = it->next)
 1037                 if (!str_strcmp(&it->key, &src_key))
 1038                     break;
 1039             pkg_free(src_key.s);
 1040             if (it) {   /* key is in list */
 1041                 lock_release(queries_lock);
 1042                 lock_get(it->wait_sql_query);
 1043             }
 1044 
 1045             if ((rld_vers = get_rld_vers_from_cache(db_hdls->c_entry, db_hdls)) < 0) {
 1046                 LM_ERR("Unable to fetch reload version counter\n");
 1047                 if (it)
 1048                     lock_release(it->wait_sql_query);
 1049                 else
 1050                     lock_release(queries_lock);
 1051 
 1052                 return init_mi_error(500, MI_SSTR("ERROR Reloading key from SQL"
 1053                                                     " database\n"));
 1054             }
 1055 
 1056             rc = load_key(db_hdls->c_entry, db_hdls, *key, &values, &sql_res, rld_vers);
 1057             if (rc == 0)
 1058                 db_hdls->db_funcs.free_result(db_hdls->db_con, sql_res);
 1059 
 1060             if (it)
 1061                 lock_release(it->wait_sql_query);
 1062             else
 1063                 lock_release(queries_lock);
 1064 
 1065             if (rc == -1)
 1066                 return init_mi_error(500, MI_SSTR("ERROR Reloading key from SQL"
 1067                                                     " database\n"));
 1068             else if (rc == -2)
 1069                 return init_mi_error(500, MI_SSTR("ERROR Reloading key from SQL"
 1070                                                     "database, key not found\n"));
 1071         } else {
 1072             /* 'invalidate' all keys by increasing the reload version counter */
 1073             if (inc_cache_rld_vers(db_hdls, &rld_vers) < 0)
 1074                 return init_mi_error(500, MI_SSTR("ERROR Invalidating cache"));
 1075         }
 1076     } else {
 1077         if (load_entire_table(db_hdls->c_entry, db_hdls, 1) < 0) {
 1078             LM_DBG("Failed to reload table\n");
 1079             return init_mi_error(500, MI_SSTR("ERROR Reloading SQL database"));
 1080         }
 1081     }
 1082 
 1083     return init_mi_result_ok();
 1084 }
 1085 
 1086 static mi_response_t *mi_reload_1(const mi_params_t *params,
 1087                                 struct mi_handler *async_hdl)
 1088 {
 1089     return mi_reload(params, NULL);
 1090 }
 1091 
 1092 static mi_response_t *mi_reload_2(const mi_params_t *params,
 1093                                 struct mi_handler *async_hdl)
 1094 {
 1095     str key;
 1096 
 1097     if (get_mi_string_param(params, "key", &key.s, &key.len) < 0)
 1098         return init_mi_param_error();
 1099 
 1100     return mi_reload(params, &key);
 1101 }
 1102 
 1103 static int init_rld_vers_key(cache_entry_t *c_entry, db_handlers_t *db_hdls)
 1104 {
 1105     str rld_vers_key;
 1106     int reload_version = -1;
 1107 
 1108     /* set up reload version counter for this entry in cachedb */
 1109     rld_vers_key.len = c_entry->id.len + 23;
 1110     rld_vers_key.s = pkg_malloc(rld_vers_key.len);
 1111     if (!rld_vers_key.s) {
 1112         LM_ERR("No more pkg memory\n");
 1113         return -1;
 1114     }
 1115     memcpy(rld_vers_key.s, c_entry->id.s, c_entry->id.len);
 1116     memcpy(rld_vers_key.s + c_entry->id.len, "_sql_cacher_reload_vers", 23);
 1117 
 1118     db_hdls->cdbf.add(db_hdls->cdbcon, &rld_vers_key, 1, 0, &reload_version);
 1119     db_hdls->cdbf.sub(db_hdls->cdbcon, &rld_vers_key, 1, 0, &reload_version);
 1120 
 1121     pkg_free(rld_vers_key.s);
 1122 
 1123     if (reload_version != 0)
 1124         return -1;
 1125 
 1126     return 0;
 1127 }
 1128 
 1129 static void cache_init_load(int sender, void *param)
 1130 {
 1131     db_handlers_t *db_hdls;
 1132 
 1133     for (db_hdls = db_hdls_list; db_hdls; db_hdls = db_hdls->next) {
 1134 
 1135         if (init_rld_vers_key(db_hdls->c_entry, db_hdls) < 0) {
 1136             LM_ERR("Failed to set up reload version counter in cahchedb for "
 1137                 "entry: %.*s\n", db_hdls->c_entry->id.len, db_hdls->c_entry->id.s);
 1138             return;
 1139         }
 1140 
 1141         /* cache the entire table in full caching mode */
 1142         if (!db_hdls->c_entry->on_demand &&
 1143             load_entire_table(db_hdls->c_entry, db_hdls, 0) < 0) {
 1144             LM_ERR("Failed to cache the entire table: %s\n", db_hdls->c_entry->table.s);
 1145             continue;
 1146         } else
 1147             LM_DBG("Cached table: %.*s\n", db_hdls->c_entry->table.len,
 1148                 db_hdls->c_entry->table.s);
 1149 
 1150     }
 1151 }
 1152 
 1153 static int mod_init(void)
 1154 {
 1155     cache_entry_t *c_entry, *c_prev = NULL, *c_tmp;
 1156     db_handlers_t *db_hdls;
 1157     char use_timer = 0;
 1158 
 1159     if (full_caching_expire <= 0) {
 1160         full_caching_expire = DEFAULT_FULL_CACHING_EXPIRE;
 1161         LM_WARN("Invalid full_caching_expire parameter, "
 1162             "setting default value: %d sec\n", DEFAULT_FULL_CACHING_EXPIRE);
 1163     }
 1164     if (reload_interval <= 0 || reload_interval >= full_caching_expire) {
 1165         reload_interval = DEFAULT_RELOAD_INTERVAL;
 1166         LM_WARN("Invalid reload_interval parameter, "
 1167             "setting default value: %d sec\n", DEFAULT_RELOAD_INTERVAL);
 1168     }
 1169     if(!entry_list){
 1170         entry_list =  shm_malloc(sizeof(cache_entry_t*));
 1171         if (!entry_list) {
 1172             LM_ERR("No more memory for cache entries list\n");
 1173             return -1;
 1174         }
 1175         *entry_list = NULL;
 1176     }
 1177     queries_in_progress =  shm_malloc(sizeof(struct queried_key *));
 1178     if (!queries_in_progress) {
 1179         LM_ERR("No more memory for queries_in_progress list\n");
 1180         return -1;
 1181     }
 1182     *queries_in_progress = NULL;
 1183 
 1184     queries_lock = lock_alloc();
 1185     if (!queries_lock) {
 1186         LM_ERR("No more memory for queries_lock\n");
 1187         return -1;
 1188     }
 1189     if (!lock_init(queries_lock)) {
 1190         LM_ERR("Failed to init queries_lock\n");
 1191         return -1;
 1192     }
 1193 
 1194     c_entry = *entry_list;
 1195     while (c_entry) {
 1196         if ((db_hdls = db_init_test_conn(c_entry)) == NULL) {
 1197             LM_ERR("Failed to validate db conns for cache entry\n");
 1198             if (c_prev)
 1199                 c_prev->next = c_entry->next;
 1200             else
 1201                 *entry_list = c_entry->next;
 1202             c_tmp = c_entry;
 1203             c_entry = c_entry->next;
 1204             free_c_entry(c_tmp);
 1205             continue;
 1206         }
 1207 
 1208         if (!c_entry->on_demand) {
 1209             use_timer = 1;
 1210             c_entry->expire = full_caching_expire;
 1211             c_entry->ref_lock = lock_init_rw();
 1212             if (!c_entry->ref_lock) {
 1213                 LM_ERR("Failed to init readers-writers lock\n");
 1214                 continue;
 1215             }
 1216         }
 1217 
 1218         db_hdls->db_funcs.close(db_hdls->db_con);
 1219         db_hdls->db_con = 0;
 1220         db_hdls->cdbf.destroy(db_hdls->cdbcon);
 1221         db_hdls->cdbcon = 0;
 1222         db_hdls->next = db_hdls_list;
 1223         db_hdls_list = db_hdls;
 1224 
 1225         c_prev = c_entry;
 1226         c_entry = c_entry->next;
 1227     }
 1228 
 1229     if (use_timer && register_timer("sql_cacher_reload-timer", reload_timer, NULL,
 1230         full_caching_expire - reload_interval, TIMER_FLAG_DELAY_ON_DELAY) < 0) {
 1231         LM_ERR("failed to register timer\n");
 1232         return -1;
 1233     }
 1234 
 1235     return 0;
 1236 }
 1237 
 1238 static int child_init(int rank)
 1239 {
 1240     db_handlers_t *db_hdls;
 1241 
 1242     for (db_hdls = db_hdls_list; db_hdls; db_hdls = db_hdls->next) {
 1243         db_hdls->cdbcon = db_hdls->cdbf.init(&db_hdls->c_entry->cachedb_url);
 1244         if (!db_hdls->cdbcon) {
 1245             LM_ERR("Cannot connect to cachedb from child\n");
 1246             return -1;
 1247         }
 1248 
 1249         if ((db_hdls->db_con = db_hdls->db_funcs.init(&db_hdls->c_entry->db_url)) == 0) {
 1250             LM_ERR("Cannot connect to SQL DB from child\n");
 1251             return -1;
 1252         }
 1253     }
 1254 
 1255     /* perform full caching load in the same process but after child_init is done */
 1256     if ((rank == 1) && ipc_send_rpc(process_no, cache_init_load, NULL) < 0) {
 1257         LM_ERR("Failed to RPC full caching load\n");
 1258         return -1;
 1259     }
 1260 
 1261     return 0;
 1262 }
 1263 
 1264 /*  return:
 1265  *  1 - if found
 1266  * -2 - if not found
 1267  * -1 - if error
 1268  */
 1269 static int cdb_fetch(pv_name_fix_t *pv_name, str *cdb_res, int *entry_rld_vers)
 1270 {
 1271     str cdb_key;
 1272     int rc = -1;
 1273 
 1274     cdb_key.len = pv_name->id.len + pv_name->key.len;
 1275     cdb_key.s = pkg_malloc(cdb_key.len);
 1276     if (!cdb_key.s) {
 1277         LM_ERR("No more pkg memory\n");
 1278         return -1;
 1279     }
 1280     memcpy(cdb_key.s, pv_name->id.s, pv_name->id.len);
 1281     memcpy(cdb_key.s + pv_name->id.len, pv_name->key.s, pv_name->key.len);
 1282 
 1283     *entry_rld_vers = get_rld_vers_from_cache(pv_name->c_entry, pv_name->db_hdls);
 1284     if (*entry_rld_vers < 0)
 1285         goto out_free;
 1286 
 1287     rc = pv_name->db_hdls->cdbf.get(pv_name->db_hdls->cdbcon, &cdb_key, cdb_res);
 1288 
 1289 out_free:
 1290     pkg_free(cdb_key.s);
 1291     return rc;
 1292 }
 1293 
 1294 /*  return:
 1295  *  0 - succes
 1296  *  1 - succes, null value in db
 1297  *  2 - error
 1298  *  3 - does not match reload version (old value)
 1299  */
 1300 static int cdb_val_decode(pv_name_fix_t *pv_name, str *cdb_val, int reload_version,
 1301                             str *str_res, int *int_res)
 1302 {
 1303     int int_val, next_str_off, i, rc;
 1304     char int_buf[4];
 1305     const char zeroes[INT_B64_ENC_LEN] = {0};
 1306 
 1307     if (pv_name->col_offset == -1) {
 1308         LM_WARN("Unknown column %.*s\n", pv_name->col.len, pv_name->col.s);
 1309         return 2;
 1310     }
 1311 
 1312     /* decode the reload version */
 1313     if (base64decode((unsigned char *)int_buf,
 1314         (unsigned char *)(cdb_val->s), INT_B64_ENC_LEN) != 4)
 1315         goto error;
 1316     memcpy(&int_val, int_buf, 4);
 1317 
 1318     if (reload_version != int_val)
 1319         return 3;
 1320 
 1321     /* null integer value in db */
 1322     if (!memcmp(cdb_val->s + pv_name->col_offset, zeroes, INT_B64_ENC_LEN))
 1323         return 1;
 1324 
 1325     /* decode the integer value or the offset of the string value */
 1326     if (base64decode((unsigned char *)int_buf,
 1327         (unsigned char *)(cdb_val->s + pv_name->col_offset), INT_B64_ENC_LEN) != 4)
 1328         goto error;
 1329     memcpy(&int_val, int_buf, 4);
 1330 
 1331     if (is_str_column(pv_name)) {
 1332         /* null string value in db */
 1333         if (int_val == 0)
 1334             return 1;
 1335 
 1336         str_res->s = cdb_val->s + int_val;
 1337         if (pv_name->last_str)
 1338             str_res->len = cdb_val->len - int_val;
 1339         else {
 1340             /* calculate the length of the current string using the offset of the next not null string */
 1341             i = 1;
 1342             do {
 1343                 rc = base64decode((unsigned char *)int_buf, (unsigned char *)(cdb_val->s +
 1344                     pv_name->col_offset + i * INT_B64_ENC_LEN), INT_B64_ENC_LEN);
 1345                 if (rc != 4)
 1346                     goto error;
 1347                 memcpy(&next_str_off, int_buf, 4);
 1348                 i++;
 1349             } while (next_str_off == 0 && pv_name->col_offset + i*INT_B64_ENC_LEN <
 1350                         (pv_name->c_entry->nr_columns + 1) * INT_B64_ENC_LEN);
 1351 
 1352             if (next_str_off == 0)
 1353                 str_res->len = cdb_val->len - int_val;
 1354             else
 1355                 str_res->len = next_str_off - int_val;
 1356         }
 1357     } else {
 1358         *int_res = int_val;
 1359     }
 1360 
 1361     return 0;
 1362 error:
 1363     LM_ERR("Failed to decode value: %.*s from cachedb\n", cdb_val->len, cdb_val->s);
 1364     return 2;
 1365 }
 1366 
 1367 static void optimize_cdb_decode(pv_name_fix_t *pv_name)
 1368 {
 1369     int i, j, prev_cols;
 1370     char col_type1, col_type2;
 1371 
 1372     for (i = 0; i < pv_name->c_entry->nr_columns; i++) {
 1373         if (!str_strcmp(pv_name->c_entry->columns[i], &pv_name->col)) {
 1374             pv_name->col_nr = i;
 1375 
 1376             prev_cols = 0;
 1377             col_type1 = ((pv_name->c_entry->column_types & (1LL << i)) != 0);
 1378             for (j = 0; j < i; j++) {
 1379                 col_type2 = ((pv_name->c_entry->column_types & (1LL << j)) != 0);
 1380                 if (col_type1 == col_type2)
 1381                     prev_cols++;
 1382             }
 1383             if (col_type1) {
 1384                 pv_name->col_offset = INT_B64_ENC_LEN +
 1385                     pv_name->c_entry->nr_ints*INT_B64_ENC_LEN + prev_cols*INT_B64_ENC_LEN;
 1386                 if (prev_cols == pv_name->c_entry->nr_strs - 1)
 1387                     pv_name->last_str = 1;
 1388                 else
 1389                     pv_name->last_str = 0;
 1390             } else
 1391                 pv_name->col_offset = INT_B64_ENC_LEN + prev_cols*INT_B64_ENC_LEN;
 1392 
 1393             break;
 1394         }
 1395     }
 1396     if (i == pv_name->c_entry->nr_columns)
 1397         pv_name->col_offset = -1;
 1398 }
 1399 
 1400 static void unlink_from_query_list(struct queried_key *pos)
 1401 {
 1402     struct queried_key *prev;
 1403 
 1404     if (pos == *queries_in_progress) {
 1405         *queries_in_progress = (*queries_in_progress)->next;
 1406         return;
 1407     }
 1408 
 1409     for (prev = *queries_in_progress; prev->next != pos; prev = prev->next) ;
 1410 
 1411     prev->next = pos->next;
 1412 }
 1413 
 1414 /*  return:
 1415  *  0 - succes => if str column, @str_res->s must be pkg_free()'d
 1416  *  1 - succes, null value in db
 1417  * -1 - error
 1418  * -2 - not found in sql db
 1419  *  2 - error in cdb_val_decode()
 1420  *  3 - does not match reload version (old value)
 1421  */
 1422 static int on_demand_load(pv_name_fix_t *pv_name, str *str_res, int *int_res,
 1423                             int rld_vers)
 1424 {
 1425     struct queried_key *it, *tmp, *new_key;
 1426     str src_key, st;
 1427     str cdb_res;
 1428     db_res_t *sql_res = NULL;
 1429     db_val_t *values;
 1430     db_type_t val_type;
 1431     int i, rc;
 1432     int rld_vers_retry;
 1433 
 1434     for (i = 0; i < pv_name->c_entry->nr_columns; i++)
 1435         if (!str_strcmp(pv_name->c_entry->columns[i], &pv_name->col)) {
 1436             pv_name->col_nr = i;
 1437             break;
 1438         }
 1439     if (i == pv_name->c_entry->nr_columns) {
 1440         LM_WARN("Unknown column %.*s\n", pv_name->col.len, pv_name->col.s);
 1441         return -1;
 1442     }
 1443 
 1444     src_key.len = pv_name->id.len + pv_name->key.len;
 1445     src_key.s = shm_malloc(src_key.len);
 1446     if (!src_key.s) {
 1447         LM_ERR("No more shm memory\n");
 1448         return -1;
 1449     }
 1450     memcpy(src_key.s, pv_name->id.s, pv_name->id.len);
 1451     memcpy(src_key.s + pv_name->id.len, pv_name->key.s, pv_name->key.len);
 1452 
 1453     lock_get(queries_lock);
 1454 
 1455     for (it = *queries_in_progress; it; it = it->next) {
 1456         if (str_strcmp(&it->key, &src_key))
 1457             continue;
 1458 
 1459         it->nr_waiting_procs++;  /* key is in list! */
 1460         lock_release(queries_lock);
 1461         /* wait for the query to complete */
 1462         lock_get(it->wait_sql_query);
 1463         lock_get(queries_lock);
 1464         shm_free(src_key.s);
 1465         if (it->nr_waiting_procs == 1) {
 1466             lock_release(it->wait_sql_query);
 1467             lock_destroy(it->wait_sql_query);
 1468             lock_dealloc(it->wait_sql_query);
 1469             /* if this is the last process waiting, delete key from list */
 1470             unlink_from_query_list(it);
 1471             tmp = it;
 1472             it = it->next;
 1473             shm_free(tmp->key.s);
 1474             shm_free(tmp);
 1475         } else if (it->nr_waiting_procs > 1) {
 1476             it->nr_waiting_procs--;
 1477             lock_release(it->wait_sql_query);
 1478         }
 1479         lock_release(queries_lock);
 1480 
 1481         /* reload key from cachedb */
 1482         if (cdb_fetch(pv_name, &cdb_res, &rld_vers_retry) < 0) {
 1483             LM_ERR("Error on retrying fetch from cachedb\n");
 1484             return -1;
 1485         }
 1486         if (cdb_res.len == 0 || !cdb_res.s) {
 1487             LM_ERR("Cache fetch result should not be empty\n");
 1488             return -1;
 1489         }
 1490 
 1491         if (pv_name->last_str == -1)
 1492             optimize_cdb_decode(pv_name);
 1493         rc = cdb_val_decode(pv_name, &cdb_res, rld_vers_retry, str_res, int_res);
 1494         if (is_str_column(pv_name) && rc == 0) {
 1495             if (pkg_str_dup(&st, str_res) != 0) {
 1496                 LM_ERR("oom\n");
 1497                 rc = -1;
 1498                 memset(str_res, 0, sizeof *str_res);
 1499             } else {
 1500                 *str_res = st;
 1501             }
 1502         }
 1503 
 1504         pkg_free(cdb_res.s);
 1505 
 1506         return rc;
 1507     }
 1508 
 1509     /* key not found in list -> insert it */
 1510     new_key = shm_malloc(sizeof(struct queried_key));
 1511     if (!new_key) {
 1512         LM_ERR("No more shm memory\n");
 1513         lock_release(queries_lock);
 1514         return -1;
 1515     }
 1516     new_key->key = src_key;
 1517     new_key->nr_waiting_procs = 0;
 1518     new_key->wait_sql_query = lock_alloc();
 1519     if (!new_key->wait_sql_query) {
 1520         LM_ERR("No more memory for wait_sql_query lock\n");
 1521         shm_free(new_key);
 1522         lock_release(queries_lock);
 1523         return -1;
 1524     }
 1525     if (!lock_init(new_key->wait_sql_query)) {
 1526         LM_ERR("Failed to init wait_sql_query lock\n");
 1527         lock_dealloc(new_key->wait_sql_query);
 1528         shm_free(new_key);
 1529         lock_release(queries_lock);
 1530         return -1;
 1531     }
 1532 
 1533     new_key->next = *queries_in_progress;
 1534     *queries_in_progress = new_key;
 1535 
 1536     lock_get(new_key->wait_sql_query);
 1537 
 1538     lock_release(queries_lock);
 1539 
 1540     rc = load_key(pv_name->c_entry, pv_name->db_hdls, pv_name->key, &values,
 1541             &sql_res, rld_vers);
 1542 
 1543     lock_get(queries_lock);
 1544 
 1545     lock_release(new_key->wait_sql_query);
 1546 
 1547     /* delete key from list */
 1548     if (new_key->nr_waiting_procs == 0) {
 1549         lock_destroy(new_key->wait_sql_query);
 1550         lock_dealloc(new_key->wait_sql_query);
 1551         unlink_from_query_list(new_key);
 1552         shm_free(new_key->key.s);
 1553         shm_free(new_key);
 1554     }
 1555 
 1556     lock_release(queries_lock);
 1557 
 1558     if (rc < 0)
 1559         return rc;
 1560 
 1561     if (VAL_NULL(values + pv_name->col_nr)) {
 1562         rc = 1;
 1563         goto out_free_res;
 1564     }
 1565 
 1566     rc = 0;
 1567     val_type = VAL_TYPE(values + pv_name->col_nr);
 1568     switch (val_type) {
 1569         case DB_STRING:
 1570             st.s = (char *)VAL_STRING(values + pv_name->col_nr);
 1571             st.len = strlen(st.s);
 1572             if (pkg_str_dup(str_res, &st) != 0) {
 1573                 LM_ERR("oom\n");
 1574                 rc = -1;
 1575                 goto out_free_res;
 1576             }
 1577             break;
 1578         case DB_STR:
 1579             if (pkg_str_dup(str_res, &(VAL_STR(values + pv_name->col_nr))) != 0) {
 1580                 LM_ERR("oom\n");
 1581                 rc = -1;
 1582                 goto out_free_res;
 1583             }
 1584             break;
 1585         case DB_BLOB:
 1586             if (pkg_str_dup(str_res, &(VAL_BLOB(values + pv_name->col_nr))) != 0) {
 1587                 LM_ERR("oom\n");
 1588                 rc = -1;
 1589                 goto out_free_res;
 1590             }
 1591             break;
 1592         case DB_INT:
 1593             *int_res = VAL_INT(values + pv_name->col_nr);
 1594             break;
 1595         case DB_BIGINT:
 1596             *int_res = (int)VAL_BIGINT(values + pv_name->col_nr);
 1597             break;
 1598         case DB_DOUBLE:
 1599             *int_res = (int)VAL_DOUBLE(values + pv_name->col_nr);
 1600             break;
 1601         default:
 1602             LM_ERR("Unsupported type for SQL column\n");
 1603             rc = -1;
 1604             goto out_free_res;
 1605     }
 1606 
 1607 out_free_res:
 1608     pv_name->db_hdls->db_funcs.free_result(pv_name->db_hdls->db_con, sql_res);
 1609     return rc;
 1610 }
 1611 
 1612 static int parse_pv_name_s(pv_name_fix_t *pv_name, str *name_s)
 1613 {
 1614     char *p1 = NULL, *p2 = NULL;
 1615     char last;
 1616 
 1617 #define PARSE_TOKEN(_ptr1, _ptr2, type, delim) \
 1618     do { \
 1619         (_ptr2) = memchr((_ptr1), (delim), \
 1620                     name_s->len - ((_ptr1) - name_s->s) + 1); \
 1621         if (!(_ptr2)) { \
 1622             LM_ERR("Invalid syntax for pvar name\n"); \
 1623             return -1; \
 1624         } \
 1625         int _prev_len = pv_name->type.len; \
 1626         pv_name->type.len = (_ptr2) - (_ptr1); \
 1627         if (!pv_name->type.s) { \
 1628             pv_name->type.s = pkg_malloc(pv_name->type.len); \
 1629             if (!pv_name->type.s) { \
 1630                 LM_ERR("No more pkg memory\n"); \
 1631                 return -1; \
 1632             } \
 1633             memcpy(pv_name->type.s, (_ptr1), pv_name->type.len); \
 1634         } else if (memcmp(pv_name->type.s, (_ptr1), pv_name->type.len)) { \
 1635             if (_prev_len != pv_name->type.len) { \
 1636                 pv_name->type.s = pkg_realloc(pv_name->type.s, pv_name->type.len); \
 1637                 if (!pv_name->type.s) { \
 1638                     LM_ERR("No more pkg memory\n"); \
 1639                     return -1; \
 1640                 } \
 1641             } \
 1642             memcpy(pv_name->type.s, (_ptr1), pv_name->type.len); \
 1643         } \
 1644     } while (0)
 1645 
 1646         last = name_s->s[name_s->len];
 1647         p1 = name_s->s;
 1648         PARSE_TOKEN(p1, p2, id, pvar_delimiter.s[0]);
 1649         p1 = p2 + 1;
 1650         PARSE_TOKEN(p1, p2, col, pvar_delimiter.s[0]);
 1651         p1 = p2 + 1;
 1652         PARSE_TOKEN(p1, p2, key, last);
 1653 
 1654 #undef PARSE_TOKEN
 1655 
 1656     return 0;
 1657 }
 1658 
 1659 int pv_parse_name(pv_spec_p sp, str *in)
 1660 {
 1661     pv_elem_t *model = NULL, *it;
 1662     pv_name_fix_t *pv_name;
 1663 
 1664     if (!in || !in->s || !sp)
 1665         return -1;
 1666 
 1667     pv_name = pkg_malloc(sizeof(pv_name_fix_t));
 1668     if (!pv_name) {
 1669         LM_ERR("No more pkg memory\n");
 1670         return -1;
 1671     }
 1672     memset(pv_name, 0, sizeof *pv_name);
 1673 
 1674     pv_name->col_offset = -1;
 1675     pv_name->last_str = -1;
 1676 
 1677     sp->pvp.pvn.type = PV_NAME_PVAR;
 1678     sp->pvp.pvn.u.dname = (void *)pv_name;
 1679 
 1680     if (pv_parse_format(in, &model) < 0) {
 1681         LM_ERR("Wrong format for pvar name\n");
 1682         return -1;
 1683     }
 1684 
 1685     for (it = model; it; it = it->next) {
 1686         if (it->spec.type != PVT_NONE)
 1687             break;
 1688     }
 1689     if (it) { /* if there are variables in the name, parse later */
 1690         pv_name->pv_elem_list = model;
 1691     } else {
 1692         if (parse_pv_name_s(pv_name, &(model->text)) < 0)
 1693             return -1;
 1694     }
 1695 
 1696     return 0;
 1697 }
 1698 
 1699 static str valbuff;
 1700 int pv_get_sql_cached_value(struct sip_msg *msg,  pv_param_t *param, pv_value_t *res)
 1701 {
 1702     pv_name_fix_t *pv_name;
 1703     str name_s;
 1704     db_handlers_t *it_db;
 1705     int rc, rc2, int_res = 0, l = 0;
 1706     char *ch = NULL;
 1707     str str_res = {NULL, 0}, cdb_res = {NULL, 0};
 1708     int entry_rld_vers, free_str_res = 0;
 1709 
 1710     if (!param || param->pvn.type != PV_NAME_PVAR ||
 1711         !param->pvn.u.dname) {
 1712         LM_CRIT("Bad pvar get function parameters\n");
 1713         return -1;
 1714     }
 1715 
 1716     pv_name = (pv_name_fix_t *)param->pvn.u.dname;
 1717     if (!pv_name) {
 1718         LM_ERR("Unable to get name struct from dname\n");
 1719         return -1;
 1720     }
 1721 
 1722     if (pv_name->pv_elem_list) {
 1723         /* there are variables in the name which need to be evaluated, then parse */
 1724         if (pv_printf_s(msg, pv_name->pv_elem_list, &name_s) != 0 ||
 1725             name_s.len == 0 || !name_s.s) {
 1726             LM_ERR("Unable to evaluate variables in pv name\n");
 1727             return pv_get_null(msg, param, res);
 1728         }
 1729         if (parse_pv_name_s(pv_name, &name_s) < 0)
 1730             return pv_get_null(msg, param, res);
 1731     }
 1732 
 1733     if (!pv_name->c_entry) {
 1734         for (it_db = db_hdls_list; it_db; it_db = it_db->next)
 1735             if (!str_strcmp(&it_db->c_entry->id, &pv_name->id)) {
 1736                 pv_name->c_entry = it_db->c_entry;
 1737                 pv_name->db_hdls = it_db;
 1738                 break;
 1739             }
 1740         if (!it_db) {
 1741             LM_WARN("Unknown caching id %.*s\n", pv_name->id.len, pv_name->id.s);
 1742             return pv_get_null(msg, param, res);
 1743         }
 1744     }
 1745 
 1746     if (!pv_name->c_entry->on_demand)
 1747         lock_start_read(pv_name->c_entry->ref_lock);
 1748 
 1749     rc = cdb_fetch(pv_name, &cdb_res, &entry_rld_vers);
 1750     if (rc == -1) {
 1751         LM_ERR("Error fetching from cachedb\n");
 1752         if (!pv_name->c_entry->on_demand)
 1753             lock_stop_read(pv_name->c_entry->ref_lock);
 1754         return pv_get_null(msg, param, res);
 1755     }
 1756 
 1757     if (!pv_name->c_entry->on_demand) {
 1758         if (rc == -2) {
 1759             LM_DBG("key: %.*s not found\n", pv_name->key.len, pv_name->key.s);
 1760             lock_stop_read(pv_name->c_entry->ref_lock);
 1761             return pv_get_null(msg, param, res);
 1762         } else {
 1763             if (cdb_res.len == 0 || !cdb_res.s) {
 1764                 LM_ERR("Cache fetch result should not be empty\n");
 1765                 lock_stop_read(pv_name->c_entry->ref_lock);
 1766                 return pv_get_null(msg, param, res);
 1767             }
 1768 
 1769             if (pv_name->last_str == -1)
 1770                 optimize_cdb_decode(pv_name);
 1771             rc2 = cdb_val_decode(pv_name, &cdb_res, entry_rld_vers, &str_res,
 1772                                     &int_res);
 1773 
 1774             lock_stop_read(pv_name->c_entry->ref_lock);
 1775 
 1776             if (rc2 == 2)
 1777                 goto out_free_null;
 1778             if (rc2 == 3) {
 1779                 LM_DBG("key: %.*s not found\n", pv_name->key.len, pv_name->key.s);
 1780                 goto out_free_null;
 1781             }
 1782             if (rc2 == 1) {
 1783                 LM_DBG("NULL value in SQL db\n");
 1784                 goto out_free_null;
 1785             }
 1786         }
 1787     } else {
 1788         if (rc == -2) {  /* key not found in cache */
 1789             rc2 = on_demand_load(pv_name, &str_res, &int_res, entry_rld_vers);
 1790             if (rc2 == 1) {
 1791                 LM_DBG("NULL value in SQL db\n");
 1792                 goto out_free_null;
 1793             } else if (rc2 != 0)
 1794                 goto out_free_null;
 1795 
 1796             free_str_res = 1;
 1797         } else {
 1798             if (cdb_res.len == 0 || !cdb_res.s) {
 1799                 LM_DBG("key: %.*s not found in SQL db\n", pv_name->key.len, pv_name->key.s);
 1800                 return pv_get_null(msg, param, res);
 1801             }
 1802 
 1803             if (pv_name->last_str == -1)
 1804                 optimize_cdb_decode(pv_name);
 1805             rc2 = cdb_val_decode(pv_name, &cdb_res, entry_rld_vers, &str_res,
 1806                                     &int_res);
 1807             if (rc2 == 2)
 1808                 goto out_free_null;
 1809             if (rc2 == 1) {
 1810                 LM_DBG("NULL value in SQL db\n");
 1811                 goto out_free_null;
 1812             }
 1813             if (rc2 == 3) {
 1814                 /* old version(due to reload) so the key should be loaded again */
 1815                 rc2 = on_demand_load(pv_name, &str_res, &int_res, entry_rld_vers);
 1816                 if (rc2 == 1) {
 1817                     LM_DBG("NULL value in SQL db\n");
 1818                     goto out_free_null;
 1819                 } else if (rc2 != 0)
 1820                     goto out_free_null;
 1821 
 1822                 free_str_res = 1;
 1823             }
 1824         }
 1825     }
 1826 
 1827     if (is_str_column(pv_name)) {
 1828         if (pkg_str_extend(&valbuff, str_res.len) != 0) {
 1829             LM_ERR("failed to alloc buffer\n");
 1830             if (free_str_res)
 1831                 pkg_free(str_res.s);
 1832             goto out_free_null;
 1833         }
 1834 
 1835         memcpy(valbuff.s, str_res.s, str_res.len);
 1836 
 1837         if (free_str_res)
 1838             pkg_free(str_res.s);
 1839 
 1840         res->flags = PV_VAL_STR;
 1841         res->rs.s = valbuff.s;
 1842         res->rs.len = str_res.len;
 1843     } else {
 1844         res->ri = int_res;
 1845         ch = int2str(int_res, &l);
 1846         res->rs.s = ch;
 1847         res->rs.len = l;
 1848         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
 1849     }
 1850 
 1851     if (cdb_res.s)
 1852         pkg_free(cdb_res.s);
 1853     return 0;
 1854 
 1855 out_free_null:
 1856     if (cdb_res.s)
 1857         pkg_free(cdb_res.s);
 1858     return pv_get_null(msg, param, res);
 1859 }
 1860 
 1861 static void free_c_entry(cache_entry_t *c)
 1862 {
 1863     int i;
 1864 
 1865     shm_free(c->id.s);
 1866     shm_free(c->db_url.s);
 1867     shm_free(c->cachedb_url.s);
 1868     shm_free(c->table.s);
 1869     shm_free(c->key.s);
 1870     for (i = 0; i < c->nr_columns; i++) {
 1871         shm_free((*c->columns[i]).s);
 1872         shm_free(c->columns[i]);
 1873     }
 1874     shm_free(c->columns);
 1875     lock_destroy_rw(c->ref_lock);
 1876     shm_free(c);
 1877 }
 1878 
 1879 static void destroy(void)
 1880 {
 1881     db_handlers_t *db_hdls;
 1882     struct queried_key *q_it, *q_tmp;
 1883     cache_entry_t *c_it, *c_tmp;
 1884 
 1885     for(db_hdls = db_hdls_list; db_hdls; db_hdls = db_hdls->next) {
 1886         if (db_hdls->cdbcon)
 1887             db_hdls->cdbf.destroy(db_hdls->cdbcon);
 1888         if (db_hdls->db_con)
 1889             db_hdls->db_funcs.close(db_hdls->db_con);
 1890     }
 1891 
 1892     q_it = *queries_in_progress;
 1893     while (q_it) {
 1894         q_tmp = q_it;
 1895         q_it = q_it->next;
 1896         lock_destroy(q_tmp->wait_sql_query);
 1897         lock_dealloc(q_tmp->wait_sql_query);
 1898         shm_free(q_tmp->key.s);
 1899         shm_free(q_tmp);
 1900     }
 1901     shm_free(queries_in_progress);
 1902 
 1903     c_it = *entry_list;
 1904     while (c_it) {
 1905         c_tmp = c_it;
 1906         c_it = c_it->next;
 1907         free_c_entry(c_tmp);
 1908     }
 1909     shm_free(entry_list);
 1910 
 1911     lock_destroy(queries_lock);
 1912     lock_dealloc(queries_lock);
 1913 }