00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "../../sr_module.h"
00033 #include "../../cfg/cfg.h"
00034 #include "../../cfg/cfg_ctx.h"
00035 #include "../../lib/srdb2/db.h"
00036 #include "../../error.h"
00037 #include "../../ut.h"
00038 #include <unistd.h>
00039
00040 MODULE_VERSION
00041
00042 #define MODULE_NAME "cfg_db"
00043
00044 static pid_t db_pid = -1;
00045 static db_ctx_t* db_cntx = NULL;
00046 static cfg_ctx_t *cfg_ctx = NULL;
00047
00048 static char *db_url = DEFAULT_DB_URL;
00049
00050 static char *transl_tbl = "cfg_transl";
00051 static char *transl_group_name_fld = "group_name";
00052 static char *transl_cfg_table_fld = "cfg_table";
00053 static char *transl_cfg_table_group_name_field_fld = "cfg_table_group_name_field";
00054 static char *transl_cfg_table_name_field_fld = "cfg_table_name_field";
00055 static char *transl_cfg_table_value_field_fld = "cfg_table_value_field";
00056
00057 static char *def_cfg_table = "cfg_var";
00058 static char *def_cfg_table_group_name_field = "group_name";
00059 static char *def_cfg_table_name_field = "name";
00060 static char *def_cfg_table_value_field = "value";
00061
00062 static char *custom_tbl = "cfg_custom";
00063 static char *custom_tbl_group_name_fld = "group_name";
00064 static char *custom_tbl_name_fld = "name";
00065 static char *custom_tbl_value_type_fld = "value_type";
00066 static char *custom_tbl_min_value_fld = "min_value";
00067 static char *custom_tbl_max_value_fld = "max_value";
00068 static char *custom_tbl_decription_fld = "description";
00069
00070
00071 static int connect_db() {
00072 if (db_pid != getpid()) {
00073 db_pid = getpid();
00074 db_cntx = db_ctx(MODULE_NAME);
00075 if (db_cntx == NULL) {
00076 ERR(MODULE_NAME": Error while initializing database layer\n");
00077 return -1;
00078 }
00079 if (db_add_db(db_cntx, db_url) < 0) {
00080 ERR(MODULE_NAME": Error adding database '%s'\n", db_url);
00081 db_ctx_free(db_cntx);
00082 db_cntx = NULL;
00083 return -1;
00084 }
00085 if (db_connect(db_cntx) < 0) {
00086 ERR(MODULE_NAME": Error connecting database '%s'\n", db_url);
00087 db_ctx_free(db_cntx);
00088 db_cntx = NULL;
00089 return -1;
00090 }
00091 }
00092 if (!db_cntx) return -2;
00093 return 0;
00094 }
00095
00096 static int exec_transl(str *group_name, db_cmd_t **cmd, db_res_t **res) {
00097 db_fld_t cols[5];
00098 db_fld_t params[2];
00099
00100 memset(cols, 0, sizeof(cols));
00101 cols[0].name = transl_cfg_table_fld;
00102 cols[0].type = DB_CSTR;
00103 cols[1].name = transl_cfg_table_group_name_field_fld;
00104 cols[1].type = DB_CSTR;
00105 cols[2].name = transl_cfg_table_name_field_fld;
00106 cols[2].type = DB_CSTR;
00107 cols[3].name = transl_cfg_table_value_field_fld;
00108 cols[3].type = DB_CSTR;
00109
00110 memset(params, 0, sizeof(params));
00111 params[0].name = transl_group_name_fld;
00112 params[0].type = DB_STR;
00113 params[0].op = DB_EQ;
00114
00115
00116 DBG(MODULE_NAME": exec_transl('%.*s', ...)\n", group_name->len, group_name->s);
00117 *cmd = db_cmd(DB_GET, db_cntx, transl_tbl, cols, params, NULL);
00118 if (!*cmd) {
00119 ERR(MODULE_NAME": Error preparing query '%s'\n", transl_tbl);
00120 return -1;
00121 }
00122 (*cmd)->match[0].flags &= ~DB_NULL;
00123 (*cmd)->match[0].v.lstr = *group_name;
00124
00125
00126 db_setopt(*cmd, "key", "pKey");
00127 db_setopt(*cmd, "key_omit", 1);
00128
00129 if (db_exec(res, *cmd) < 0) {
00130 ERR(MODULE_NAME": Error executing query '%s'\n", transl_tbl);
00131 db_cmd_free(*cmd);
00132 return -1;
00133 }
00134 return 0;
00135 }
00136
00137 #define GETCSTR(fld,def) \
00138 ((((fld).flags & DB_NULL) || (strlen(fld.v.cstr)== 0))?def:fld.v.cstr)
00139
00140
00141 static int find_cfg_var(str *group_name, char *def_name, db_res_t *transl_res) {
00142
00143 db_rec_t *transl_rec;
00144 int ret = -1;
00145
00146 DBG(MODULE_NAME": find_cfg_var('%.*s', '%s', ...)\n", group_name->len, group_name->s, def_name);
00147 transl_rec = db_first(transl_res);
00148
00149 while (transl_rec) {
00150
00151 static db_cmd_t* cmd;
00152 db_rec_t *rec;
00153 db_res_t *res;
00154 db_fld_t params[3], cols[2];
00155
00156 memset(cols, 0, sizeof(cols));
00157 cols[0].name = GETCSTR(transl_rec->fld[3], def_cfg_table_value_field);
00158 cols[0].type = DB_NONE;
00159
00160 memset(params, 0, sizeof(params));
00161 params[0].name = GETCSTR(transl_rec->fld[1], def_cfg_table_group_name_field);
00162 params[0].type = DB_STR;
00163 params[0].op = DB_EQ;
00164 params[1].name = GETCSTR(transl_rec->fld[2], def_cfg_table_name_field);
00165 params[1].type = DB_CSTR;
00166 params[1].op = DB_EQ;
00167
00168 DBG(MODULE_NAME": exec_transl: looking in '%s'\n", GETCSTR(transl_rec->fld[0], def_cfg_table));
00169 cmd = db_cmd(DB_GET, db_cntx, GETCSTR(transl_rec->fld[0], def_cfg_table), cols, params, NULL);
00170 if (!cmd) {
00171 ERR(MODULE_NAME": Error preparing query '%s'\n", transl_tbl);
00172 return -1;
00173 }
00174 cmd->match[0].flags &= ~DB_NULL;
00175 cmd->match[0].v.lstr = *group_name;
00176 cmd->match[1].flags &= ~DB_NULL;
00177 cmd->match[1].v.cstr = def_name;
00178
00179
00180 db_setopt(cmd, "key", "bySerGroup");
00181 db_setopt(cmd, "key_omit", 0);
00182
00183 if (db_exec(&res, cmd) < 0) {
00184 ERR(MODULE_NAME": Error executing query '%s'\n", transl_tbl);
00185 db_cmd_free(cmd);
00186 return -1;
00187 }
00188
00189 rec = db_first(res);
00190 if (rec) {
00191 str def_name_s;
00192 def_name_s.s = def_name;
00193 def_name_s.len = strlen(def_name);
00194 DBG(MODULE_NAME": exec_transl: found record, type:%d\n", rec->fld[0].type);
00195
00196 switch (rec->fld[0].type) {
00197 case DB_STR:
00198 if (cfg_set_now(cfg_ctx, group_name, NULL , &def_name_s, &rec->fld[0].v.lstr, CFG_VAR_STR) < 0) goto err;
00199 break;
00200 case DB_CSTR:
00201 if (cfg_set_now_string(cfg_ctx, group_name, NULL , &def_name_s, rec->fld[0].v.cstr) < 0) goto err;
00202 break;
00203 case DB_INT:
00204 if (cfg_set_now_int(cfg_ctx, group_name, NULL , &def_name_s, rec->fld[0].v.int4) < 0) goto err;
00205 break;
00206 default:
00207 ERR(MODULE_NAME": unexpected field type (%d), table:'%s', field:'%s'\n",
00208 rec->fld[0].type,
00209 GETCSTR(transl_rec->fld[0], def_cfg_table),
00210 GETCSTR(transl_rec->fld[3], def_cfg_table_value_field)
00211 );
00212 goto err;
00213 }
00214 ret = 1;
00215 err:
00216 db_res_free(res);
00217 db_cmd_free(cmd);
00218 return ret;
00219 }
00220 db_res_free(res);
00221 db_cmd_free(cmd);
00222
00223 transl_rec = db_next(transl_res);
00224 }
00225 return 0;
00226 }
00227
00228
00229 static void on_declare(str *group_name, cfg_def_t *definition) {
00230 static db_cmd_t* cmd;
00231 db_res_t *res;
00232 cfg_def_t *def;
00233 int ret;
00234 str asterisk_s = STR_STATIC_INIT("*");
00235 DBG(MODULE_NAME": on_declare('%.*s')\n", group_name->len, group_name->s);
00236 if (connect_db() < 0) return;
00237
00238 for (def=definition; def->name; def++) {
00239
00240 if (exec_transl(group_name, &cmd, &res) < 0) return;
00241 ret = find_cfg_var(group_name, def->name, res);
00242 db_res_free(res);
00243 db_cmd_free(cmd);
00244 if (ret > 0) continue;
00245
00246
00247 if (exec_transl(&asterisk_s, &cmd, &res) < 0) return;
00248 find_cfg_var(group_name, def->name, res);
00249 db_res_free(res);
00250 db_cmd_free(cmd);
00251 }
00252 }
00253
00254 #define CSTRDUP(dest, fld) { \
00255 if (((fld).flags & DB_NULL) == 0) { \
00256 int n; \
00257 n = strlen((fld).v.cstr); \
00258 if (n > 0) {\
00259 (dest) = pkg_malloc(n+1); \
00260 if (!(dest)) return E_OUT_OF_MEM; \
00261 memcpy((dest), (fld).v.cstr, n+1); \
00262 } \
00263 } \
00264 }
00265
00266
00267 static int mod_init(void) {
00268 static str default_s = STR_STATIC_INIT("<default>");
00269 db_cmd_t *cmd;
00270 db_res_t *res;
00271 db_rec_t *rec;
00272 db_fld_t cols[7];
00273
00274 DBG(MODULE_NAME": mod_init: initializing\n");
00275
00276
00277 if (connect_db() < 0) return E_CFG;
00278
00279 DBG(MODULE_NAME": mod_init: getting default values from translation table\n");
00280 if (exec_transl(&default_s, &cmd, &res) < 0) return E_CFG;
00281 rec = db_first(res);
00282 if (rec) {
00283 CSTRDUP(def_cfg_table, rec->fld[0]);
00284 CSTRDUP(def_cfg_table_group_name_field, rec->fld[1]);
00285 CSTRDUP(def_cfg_table_name_field, rec->fld[2]);
00286 CSTRDUP(def_cfg_table_value_field, rec->fld[3]);
00287 }
00288
00289 db_res_free(res);
00290 db_cmd_free(cmd);
00291
00292 DBG(MODULE_NAME": mod_init: default values: table='%s', group_name_field='%s', name_field='%s', value_field='%s'\n",
00293 def_cfg_table, def_cfg_table_group_name_field, def_cfg_table_name_field, def_cfg_table_value_field);
00294
00295
00296 DBG(MODULE_NAME": mod_init: getting custom parameters from '%s'\n", custom_tbl);
00297 memset(cols, 0, sizeof(cols));
00298 cols[0].name = custom_tbl_group_name_fld;
00299 cols[0].type = DB_CSTR;
00300 cols[1].name = custom_tbl_name_fld;
00301 cols[1].type = DB_CSTR;
00302 cols[2].name = custom_tbl_value_type_fld;
00303 cols[2].type = DB_CSTR;
00304 cols[3].name = custom_tbl_min_value_fld;
00305 cols[3].type = DB_INT;
00306 cols[4].name = custom_tbl_max_value_fld;
00307 cols[4].type = DB_INT;
00308 cols[5].name = custom_tbl_decription_fld;
00309 cols[5].type = DB_CSTR;
00310
00311 cmd = db_cmd(DB_GET, db_cntx, custom_tbl, cols, NULL, NULL);
00312 if (!cmd) {
00313 ERR(MODULE_NAME": Error preparing query '%s'\n", custom_tbl);
00314 return E_CFG;
00315 }
00316
00317 if (db_exec(&res, cmd) < 0) {
00318 ERR(MODULE_NAME": Error executing query '%s'\n", custom_tbl);
00319 db_cmd_free(cmd);
00320 return E_CFG;
00321 }
00322 rec = db_first(res);
00323 while (rec) {
00324 DBG(MODULE_NAME": custom parameter '%s.%s' type:%s\n", rec->fld[0].v.cstr, rec->fld[1].v.cstr, rec->fld[2].v.cstr);
00325 if (((rec->fld[0].flags & DB_NULL) || strlen(rec->fld[0].v.cstr) == 0) ||
00326 ((rec->fld[1].flags & DB_NULL) || strlen(rec->fld[1].v.cstr) == 0) ||
00327 ((rec->fld[2].flags & DB_NULL) || strlen(rec->fld[2].v.cstr) == 0)) {
00328 ERR(MODULE_NAME": empty group_name,name or type value in table '%s'\n", custom_tbl);
00329 return E_CFG;
00330 }
00331 switch (rec->fld[2].v.cstr[0]) {
00332 case 'i':
00333 case 'I':
00334 if (cfg_declare_int(rec->fld[0].v.cstr, rec->fld[1].v.cstr, 0, rec->fld[3].v.int4, rec->fld[4].v.int4, rec->fld[5].v.cstr) < 0) {
00335 ERR(MODULE_NAME": Error declaring cfg int '%s.%s'\n", rec->fld[0].v.cstr, rec->fld[1].v.cstr);
00336 return E_CFG;
00337 }
00338 break;
00339 case 's':
00340 case 'S':
00341 if (cfg_declare_str(rec->fld[0].v.cstr, rec->fld[1].v.cstr, "", rec->fld[5].v.cstr) < 0) {
00342 ERR(MODULE_NAME": Error declaring cfg str '%s.%s'\n", rec->fld[0].v.cstr, rec->fld[1].v.cstr);
00343 return E_CFG;
00344 }
00345 break;
00346 default:
00347 ERR(MODULE_NAME": bad custom value type '%s'\n", rec->fld[2].v.cstr);
00348 return E_CFG;
00349 }
00350
00351 rec = db_next(res);
00352 }
00353 db_res_free(res);
00354 db_cmd_free(cmd);
00355
00356
00357 DBG(MODULE_NAME": mod_init: registering cfg callback\n");
00358 if (cfg_register_ctx(&cfg_ctx, on_declare) < 0) {
00359 ERR(MODULE_NAME": failed to register cfg context\n");
00360 return -1;
00361 }
00362
00363 return 0;
00364 }
00365
00366
00367
00368
00369 static param_export_t params[] = {
00370 {"db_url", PARAM_STRING, &db_url},
00371 {"transl_tbl", PARAM_STRING, &transl_tbl},
00372
00373
00374
00375
00376
00377
00378 {"custom_tbl", PARAM_STRING, &custom_tbl},
00379
00380 {0, 0, 0}
00381 };
00382
00383
00384 struct module_exports exports = {
00385 MODULE_NAME,
00386 0,
00387 0,
00388 params,
00389 mod_init,
00390 0,
00391 0,
00392 0,
00393 0
00394 };
00395