cr_db.c

Go to the documentation of this file.
00001 /*
00002  * $Id: cr_db.c 5495 2009-01-21 15:33:51Z henningw $
00003  *
00004  * Copyright (C) 2007-2008 1&1 Internet AG
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00023 /**
00024  * \file cr_db.c
00025  * \brief Functions for loading routing data from a database.
00026  * \ingroup carrierroute
00027  * - Module; \ref carrierroute
00028  */
00029 
00030 #include "../../dprint.h"
00031 #include "../../mem/mem.h"
00032 #include "../../mem/shm_mem.h"
00033 #include "carrierroute.h"
00034 #include "cr_db.h"
00035 #include "cr_carrier.h"
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 
00039 #define QUERY_LEN 2048
00040 
00041 static char query[QUERY_LEN];
00042 
00043 str * columns[COLUMN_NUM] = { &carrierroute_id_col, &carrierroute_carrier_col,
00044    &carrierroute_domain_col,
00045    &carrierroute_scan_prefix_col,
00046    &carrierroute_flags_col,
00047    &carrierroute_mask_col,
00048    &carrierroute_prob_col,
00049    &carrierroute_rewrite_host_col,
00050    &carrierroute_strip_col,
00051    &carrierroute_rewrite_prefix_col,
00052    &carrierroute_rewrite_suffix_col,
00053    &carrierroute_description_col
00054 };
00055 
00056 str * carrier_name_columns[CARRIER_NAME_COLUMN_NUM] = {
00057    &carrier_name_id_col,
00058    &carrier_name_carrier_col
00059 };
00060 
00061 str * domain_name_columns[DOMAIN_NAME_COLUMN_NUM] = {
00062    &domain_name_id_col,
00063    &domain_name_domain_col
00064 };
00065 
00066 str * failure_columns[FAILURE_COLUMN_NUM] = {
00067    &carrierfailureroute_id_col,
00068    &carrierfailureroute_carrier_col,
00069    &carrierfailureroute_domain_col,
00070    &carrierfailureroute_scan_prefix_col,
00071    &carrierfailureroute_host_name_col,
00072    &carrierfailureroute_reply_code_col,
00073    &carrierfailureroute_flags_col,
00074    &carrierfailureroute_mask_col,
00075    &carrierfailureroute_next_domain_col,
00076    &carrierfailureroute_description_col
00077 };
00078 
00079 
00080 static int load_carrier_map(struct route_data_t *rd) {
00081    db_res_t * res = NULL;
00082    int i, count;
00083    if(!rd){
00084       LM_ERR("invalid parameter\n");
00085       return -1;
00086    }
00087    if (carrierroute_dbf.use_table(carrierroute_dbh, &carrier_name_table) < 0) {
00088       LM_ERR("couldn't use table\n");
00089       return -1;
00090    }
00091 
00092    if (carrierroute_dbf.query(carrierroute_dbh, 0, 0, 0, (db_key_t *)carrier_name_columns, 0, CARRIER_NAME_COLUMN_NUM, 0, &res) < 0) {
00093       LM_ERR("couldn't query table\n");
00094       return -1;
00095    }
00096 
00097    count = RES_ROW_N(res);
00098    if (count == 0) {
00099       LM_ERR("empty %.*s table", carrier_name_table.len, carrier_name_table.s);
00100       carrierroute_dbf.free_result(carrierroute_dbh, res);
00101       return 0;
00102    }
00103 
00104    rd->carrier_map = shm_malloc(sizeof(struct name_map_t) * count);
00105    if (rd->carrier_map == NULL) {
00106       SHM_MEM_ERROR;
00107       carrierroute_dbf.free_result(carrierroute_dbh, res);
00108       return -1;
00109    }
00110    memset(rd->carrier_map, 0, sizeof(struct name_map_t) * count);
00111 
00112    for (i=0; i<count; i++) {
00113       rd->carrier_map[i].id = res->rows[i].values[CARRIER_NAME_ID_COL].val.int_val;
00114       rd->carrier_map[i].name.len = strlen(res->rows[i].values[CARRIER_NAME_NAME_COL].val.string_val);
00115       rd->carrier_map[i].name.s = shm_malloc(rd->carrier_map[i].name.len);
00116       if (rd->carrier_map[i].name.s == NULL) {
00117          SHM_MEM_ERROR;
00118          carrierroute_dbf.free_result(carrierroute_dbh, res);
00119          shm_free(rd->carrier_map);
00120          rd->carrier_map = NULL;
00121          return -1;
00122       }
00123       memcpy(rd->carrier_map[i].name.s, res->rows[i].values[CARRIER_NAME_NAME_COL].val.string_val, rd->carrier_map[i].name.len);
00124    }
00125 
00126    /* sort carrier map by id for faster access */
00127    qsort(rd->carrier_map, count, sizeof(rd->carrier_map[0]), compare_name_map);
00128 
00129    carrierroute_dbf.free_result(carrierroute_dbh, res);
00130    return count;
00131 }
00132 
00133 
00134 
00135 
00136 static int load_domain_map(struct route_data_t *rd) {
00137    db_res_t * res = NULL;
00138    int i, count;
00139    if(!rd){
00140       LM_ERR("invalid parameter\n");
00141       return -1;
00142    }
00143    if (carrierroute_dbf.use_table(carrierroute_dbh, &domain_name_table) < 0) {
00144       LM_ERR("couldn't use table\n");
00145       return -1;
00146    }
00147 
00148    if (carrierroute_dbf.query(carrierroute_dbh, 0, 0, 0, (db_key_t *)domain_name_columns, 0, DOMAIN_NAME_COLUMN_NUM, 0, &res) < 0) {
00149       LM_ERR("couldn't query table\n");
00150       return -1;
00151    }
00152 
00153    count = RES_ROW_N(res);
00154    if (count == 0) {
00155       LM_ERR("empty %.*s table", domain_name_table.len, domain_name_table.s);
00156       carrierroute_dbf.free_result(carrierroute_dbh, res);
00157       return 0;
00158    }
00159 
00160    rd->domain_map = shm_malloc(sizeof(struct name_map_t) * count);
00161    if (rd->domain_map == NULL) {
00162       SHM_MEM_ERROR;
00163       carrierroute_dbf.free_result(carrierroute_dbh, res);
00164       return -1;
00165    }
00166    memset(rd->domain_map, 0, sizeof(struct name_map_t) * count);
00167 
00168    for (i=0; i<count; i++) {
00169       rd->domain_map[i].id = res->rows[i].values[DOMAIN_NAME_ID_COL].val.int_val;
00170       rd->domain_map[i].name.len = strlen(res->rows[i].values[DOMAIN_NAME_NAME_COL].val.string_val);
00171       rd->domain_map[i].name.s = shm_malloc(rd->domain_map[i].name.len);
00172       if (rd->domain_map[i].name.s == NULL) {
00173          SHM_MEM_ERROR;
00174          carrierroute_dbf.free_result(carrierroute_dbh, res);
00175          shm_free(rd->domain_map);
00176          rd->domain_map = NULL;
00177          return -1;
00178       }
00179       memcpy(rd->domain_map[i].name.s, res->rows[i].values[DOMAIN_NAME_NAME_COL].val.string_val, rd->domain_map[i].name.len);
00180    }
00181 
00182    /* sort domain map by id for faster access */
00183    qsort(rd->domain_map, count, sizeof(rd->domain_map[0]), compare_name_map);
00184 
00185    carrierroute_dbf.free_result(carrierroute_dbh, res);
00186    return count;
00187 }
00188 
00189 
00190 
00191 
00192 int load_user_carrier(str * user, str * domain) {
00193    db_res_t * res;
00194    db_key_t cols[1];
00195    db_key_t keys[2];
00196    db_val_t vals[2];
00197    db_op_t op[2];
00198    int id;
00199    if (!user || (use_domain && !domain)) {
00200       LM_ERR("NULL pointer in parameter\n");
00201       return -1;
00202    }
00203 
00204    cols[0] = subscriber_columns[SUBSCRIBER_CARRIER_COL];
00205 
00206    keys[0] = subscriber_columns[SUBSCRIBER_USERNAME_COL];
00207    op[0] = OP_EQ;
00208    VAL_TYPE(vals) = DB_STR;
00209    VAL_NULL(vals) = 0;
00210    VAL_STR(vals) = *user;
00211 
00212    keys[1] = subscriber_columns[SUBSCRIBER_DOMAIN_COL];
00213    op[1] = OP_EQ;
00214    VAL_TYPE(vals+1) = DB_STR;
00215    VAL_NULL(vals+1) = 0;
00216    VAL_STR(vals+1) = *domain;
00217 
00218    if (carrierroute_dbf.use_table(carrierroute_dbh, &subscriber_table) < 0) {
00219       LM_ERR("can't use table\n");
00220       return -1;
00221    }
00222 
00223    if (carrierroute_dbf.query(carrierroute_dbh, keys, op, vals, cols, use_domain ? 2 : 1, 1, NULL, &res) < 0) {
00224       LM_ERR("can't query database\n");
00225       return -1;
00226    }
00227 
00228    if (RES_ROW_N(res) == 0) {
00229       carrierroute_dbf.free_result(carrierroute_dbh, res);
00230       return 0;
00231    }
00232 
00233    if (VAL_NULL(ROW_VALUES(RES_ROWS(res)))) {
00234       carrierroute_dbf.free_result(carrierroute_dbh, res);
00235       return 0;
00236    }
00237 
00238    id = VAL_INT(ROW_VALUES(RES_ROWS(res)));
00239    carrierroute_dbf.free_result(carrierroute_dbh, res);
00240    return id;
00241 }
00242 
00243 
00244 
00245 
00246 /**
00247  * Loads the routing data from the database given in global
00248  * variable db_url and stores it in routing tree rd.
00249  *
00250  * @param rd Pointer to the route data tree where the routing data
00251  * shall be loaded into
00252  *
00253  * @return 0 means ok, -1 means an error occured
00254  *
00255  */
00256 int load_route_data_db(struct route_data_t * rd) {
00257    db_res_t * res = NULL;
00258    db_row_t * row = NULL;
00259    int i, ret;
00260    struct carrier_data_t * tmp_carrier_data;
00261    static str query_str;
00262    str tmp_scan_prefix, tmp_rewrite_host, tmp_rewrite_prefix,
00263       tmp_rewrite_suffix, tmp_host_name, tmp_reply_code, tmp_comment;
00264 
00265    if( (strlen("SELECT DISTINCT  FROM  WHERE = ")
00266          + carrierroute_table.len + columns[COL_DOMAIN]->len
00267          + columns[COL_CARRIER]->len + 20) >  QUERY_LEN) {
00268       LM_ERR("query too long\n");
00269       return -1;
00270    }
00271 
00272    if((rd->carrier_num = load_carrier_map(rd)) <= 0){
00273       LM_ERR("error while retrieving carriers\n");
00274       goto errout;
00275    }
00276 
00277    if((rd->domain_num = load_domain_map(rd)) <= 0){
00278       LM_ERR("error while retrieving domains\n");
00279       goto errout;
00280    }
00281 
00282    if ((rd->carriers = shm_malloc(sizeof(struct carrier_data_t *) * rd->carrier_num)) == NULL) {
00283       SHM_MEM_ERROR;
00284       goto errout;
00285    }
00286    memset(rd->carriers, 0, sizeof(struct carrier_data_t *) * rd->carrier_num);
00287 
00288    for (i=0; i<rd->carrier_num; i++) {
00289       memset(query, 0, QUERY_LEN);
00290       ret = snprintf(query, QUERY_LEN, "SELECT DISTINCT %.*s FROM %.*s WHERE %.*s=%i",
00291       columns[COL_DOMAIN]->len, columns[COL_DOMAIN]->s, carrierroute_table.len,
00292       carrierroute_table.s, columns[COL_CARRIER]->len, columns[COL_CARRIER]->s, rd->carrier_map[i].id);
00293       if (ret < 0) {
00294          LM_ERR("error in snprintf");
00295          goto errout;
00296       }
00297       query_str.s = query;
00298       query_str.len = ret;
00299 
00300       if (carrierroute_dbf.raw_query(carrierroute_dbh, &query_str, &res) < 0) {
00301          LM_ERR("Failed to query database.\n");
00302          goto errout;
00303       }
00304       LM_INFO("carrier '%.*s' (id %i) has %i domains\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s, rd->carrier_map[i].id, RES_ROW_N(res));
00305       tmp_carrier_data = create_carrier_data(rd->carrier_map[i].id, &rd->carrier_map[i].name, RES_ROW_N(res));
00306       if (tmp_carrier_data == NULL) {
00307          LM_ERR("can't create new carrier '%.*s'\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s);
00308          goto errout;
00309       }
00310       if (add_carrier_data(rd, tmp_carrier_data) < 0) {
00311          LM_ERR("can't add carrier '%.*s'\n", rd->carrier_map[i].name.len, rd->carrier_map[i].name.s);
00312          destroy_carrier_data(tmp_carrier_data);
00313          goto errout;
00314       }
00315       carrierroute_dbf.free_result(carrierroute_dbh, res);
00316       res = NULL;
00317    }
00318 
00319    if (carrierroute_dbf.use_table(carrierroute_dbh, &carrierroute_table) < 0) {
00320       LM_ERR("Cannot set database table '%.*s'.\n", carrierroute_table.len, carrierroute_table.s);
00321       return -1;
00322    }
00323 
00324    if (DB_CAPABILITY(carrierroute_dbf, DB_CAP_FETCH)) {
00325       if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *) columns, 0,
00326                COLUMN_NUM, NULL, NULL) < 0) {
00327          LM_ERR("Failed to query database to prepare fetch row.\n");
00328          return -1;
00329       }
00330       if(carrierroute_dbf.fetch_result(carrierroute_dbh, &res, cr_fetch_rows) < 0) {
00331          LM_ERR("Fetching rows failed\n");
00332          return -1;
00333       }
00334    } else {
00335       if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *) columns, 0,
00336              COLUMN_NUM, NULL, &res) < 0) {
00337          LM_ERR("Failed to query database.\n");
00338          return -1;
00339       }
00340    }
00341    int n = 0;
00342    do {
00343       LM_DBG("loading, cycle %d", n++);
00344       for (i = 0; i < RES_ROW_N(res); ++i) {
00345          row = &RES_ROWS(res)[i];
00346          tmp_scan_prefix.s=(char *)row->values[COL_SCAN_PREFIX].val.string_val;
00347          tmp_rewrite_host.s=(char *)row->values[COL_REWRITE_HOST].val.string_val;
00348          tmp_rewrite_prefix.s=(char *)row->values[COL_REWRITE_PREFIX].val.string_val;
00349          tmp_rewrite_suffix.s=(char *)row->values[COL_REWRITE_SUFFIX].val.string_val;
00350          tmp_comment.s=(char *)row->values[COL_COMMENT].val.string_val;
00351          if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
00352          if (tmp_rewrite_host.s==NULL) tmp_rewrite_host.s="";
00353          if (tmp_rewrite_prefix.s==NULL) tmp_rewrite_prefix.s="";
00354          if (tmp_rewrite_suffix.s==NULL) tmp_rewrite_suffix.s="";
00355          if (tmp_comment.s==NULL) tmp_comment.s="";
00356          tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
00357          tmp_rewrite_host.len=strlen(tmp_rewrite_host.s);
00358          tmp_rewrite_prefix.len=strlen(tmp_rewrite_prefix.s);
00359          tmp_rewrite_suffix.len=strlen(tmp_rewrite_suffix.s);
00360          tmp_comment.len=strlen(tmp_comment.s);
00361          if (add_route(rd,
00362                row->values[COL_CARRIER].val.int_val,
00363                row->values[COL_DOMAIN].val.int_val,
00364                &tmp_scan_prefix,
00365                row->values[COL_FLAGS].val.int_val,
00366                row->values[COL_MASK].val.int_val,
00367                0,
00368                row->values[COL_PROB].val.double_val,
00369                &tmp_rewrite_host,
00370                row->values[COL_STRIP].val.int_val,
00371                &tmp_rewrite_prefix,
00372                &tmp_rewrite_suffix,
00373                1,
00374                0,
00375                -1,
00376                NULL,
00377                &tmp_comment) == -1) {
00378             goto errout;
00379          }
00380       }
00381       if (DB_CAPABILITY(carrierroute_dbf, DB_CAP_FETCH)) {
00382          if(carrierroute_dbf.fetch_result(carrierroute_dbh, &res, cr_fetch_rows) < 0) {
00383             LM_ERR("fetching rows failed\n");
00384             carrierroute_dbf.free_result(carrierroute_dbh, res);
00385             return -1;
00386          }
00387       } else {
00388          break;
00389       }
00390    } while(RES_ROW_N(res) > 0);
00391 
00392    carrierroute_dbf.free_result(carrierroute_dbh, res);
00393    res = NULL;
00394    
00395    if (carrierroute_dbf.use_table(carrierroute_dbh, &carrierfailureroute_table) < 0) {
00396       LM_ERR("cannot set database table '%.*s'.\n",
00397             carrierfailureroute_table.len, carrierfailureroute_table.s);
00398       return -1;
00399    }
00400    if (carrierroute_dbf.query(carrierroute_dbh, NULL, NULL, NULL, (db_key_t *)failure_columns, 0,
00401                         FAILURE_COLUMN_NUM, NULL, &res) < 0) {
00402       LM_ERR("failed to query database.\n");
00403       return -1;
00404    }
00405    for (i = 0; i < RES_ROW_N(res); ++i) {
00406       row = &RES_ROWS(res)[i];
00407       tmp_scan_prefix.s=(char *)row->values[FCOL_SCAN_PREFIX].val.string_val;
00408       tmp_host_name.s=(char *)row->values[FCOL_HOST_NAME].val.string_val;
00409       tmp_reply_code.s=(char *)row->values[FCOL_REPLY_CODE].val.string_val;
00410       tmp_comment.s=(char *)row->values[FCOL_COMMENT].val.string_val;
00411       if (tmp_scan_prefix.s==NULL) tmp_scan_prefix.s="";
00412       if (tmp_host_name.s==NULL) tmp_host_name.s="";
00413       if (tmp_reply_code.s==NULL) tmp_reply_code.s="";
00414       if (tmp_comment.s==NULL) tmp_comment.s="";
00415       tmp_scan_prefix.len=strlen(tmp_scan_prefix.s);
00416       tmp_host_name.len=strlen(tmp_host_name.s);
00417       tmp_reply_code.len=strlen(tmp_reply_code.s);
00418       tmp_comment.len=strlen(tmp_comment.s);
00419       if (add_failure_route(rd,
00420             row->values[FCOL_CARRIER].val.int_val,
00421             row->values[COL_DOMAIN].val.int_val,
00422             &tmp_scan_prefix,
00423             &tmp_host_name,
00424             &tmp_reply_code,
00425             row->values[FCOL_FLAGS].val.int_val,
00426             row->values[FCOL_MASK].val.int_val,
00427             row->values[FCOL_NEXT_DOMAIN].val.int_val,
00428             &tmp_comment) == -1) {
00429          goto errout;
00430       }
00431    }
00432 
00433    carrierroute_dbf.free_result(carrierroute_dbh, res);
00434    return 0;
00435 
00436 errout:
00437    if (res) {
00438       carrierroute_dbf.free_result(carrierroute_dbh, res);
00439    }
00440    return -1;
00441 }

Generated on Mon May 21 18:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6