#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
#include <asterisk/module.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/config.h>
#include <asterisk/res_odbc.h>
#include <asterisk/app.h>
Include dependency graph for func_odbc.c:

Go to the source code of this file.
Functions | |
| static char * | acf_escape (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
| static char * | acf_odbc_read (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
| static void | acf_odbc_write (struct ast_channel *chan, char *cmd, char *data, const char *value) |
| AST_LIST_HEAD_STATIC (queries, acf_odbc_query) | |
| char * | description (void) |
| Provides a description of the module. | |
| static int | free_acf_query (struct acf_odbc_query *query) |
| static int | init_acf_query (struct ast_config *cfg, char *catg, struct acf_odbc_query **query) |
| char * | key () |
| Returns the ASTERISK_GPL_KEY. | |
| int | load_module (void) |
| Initialize the module. | |
| static int | odbc_load_module (void) |
| static int | odbc_unload_module (void) |
| int | reload (void) |
| Reload stuff. | |
| int | unload_module (void) |
| Cleanup all module structures, sockets, etc. | |
| int | usecount (void) |
| Provides a usecount. | |
Variables | |
| static char * | config = "func_odbc.conf" |
| static struct ast_custom_function | escape_function |
| static char * | tdesc = "ODBC lookups" |
Definition in file func_odbc.c.
|
||||||||||||||||||||||||
|
Definition at line 384 of file func_odbc.c. 00385 {
00386 char *in, *out = buf;
00387 for (in = data; *in && out - buf < len; in++) {
00388 if (*in == '\'') {
00389 *out = '\'';
00390 out++;
00391 }
00392 *out = *in;
00393 out++;
00394 }
00395 *out = '\0';
00396 return buf;
00397 }
|
|
||||||||||||||||||||||||
|
Definition at line 237 of file func_odbc.c. References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, ast_verbose(), odbc_obj::con, fetch_odbc_obj(), list, LOG_ERROR, LOG_WARNING, odbc_smart_execute(), option_verbose, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and VERBOSE_PREFIX_4. Referenced by init_acf_query(). 00238 {
00239 odbc_obj *obj;
00240 struct acf_odbc_query *query;
00241 char *s, *arg, sql[2048] = "", varname[15];
00242 int count=0, res, x, buflen = 0;
00243 SQLHSTMT stmt;
00244 SQLSMALLINT colcount=0;
00245 SQLINTEGER indicator;
00246 #ifdef NEEDTRACE
00247 SQLINTEGER enable = 1;
00248 char *tracefile = "/tmp/odbc.trace";
00249 #endif
00250
00251 AST_LIST_LOCK(&queries);
00252 AST_LIST_TRAVERSE(&queries, query, list) {
00253 if (!strcmp(query->acf->name, cmd)) {
00254 break;
00255 }
00256 }
00257
00258 if (!query) {
00259 ast_log(LOG_ERROR, "No such function '%s'\n", cmd);
00260 AST_LIST_UNLOCK(&queries);
00261 return "";
00262 }
00263
00264 obj = fetch_odbc_obj(query->dsn, 0);
00265
00266 if (!obj) {
00267 ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn);
00268 AST_LIST_UNLOCK(&queries);
00269 return "";
00270 }
00271
00272 #ifdef NEEDTRACE
00273 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
00274 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
00275 #endif
00276
00277 /* Parse our arguments */
00278 if (!(s = ast_strdupa(data))) {
00279 AST_LIST_UNLOCK(&queries);
00280 return "";
00281 }
00282
00283 while ((arg = strsep(&s, "|"))) {
00284 count++;
00285 snprintf(varname, sizeof(varname), "ARG%d", count);
00286 /* arg is by definition non-NULL, so this works, here */
00287 pbx_builtin_pushvar_helper(chan, varname, arg);
00288 }
00289
00290 pbx_substitute_variables_helper(chan, query->sql_read, sql, sizeof(sql) - 1);
00291
00292 /* Restore prior values */
00293 for (x = 1; x <= count; x++) {
00294 snprintf(varname, sizeof(varname), "ARG%d", x);
00295 pbx_builtin_setvar_helper(chan, varname, NULL);
00296 }
00297
00298 AST_LIST_UNLOCK(&queries);
00299
00300 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
00301 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00302 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00303 return "";
00304 }
00305
00306 res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
00307 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00308 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00309 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00310 return "";
00311 }
00312
00313 res = odbc_smart_execute(obj, stmt);
00314 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00315 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
00316 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00317 return "";
00318 }
00319
00320 res = SQLNumResultCols(stmt, &colcount);
00321 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00322 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00323 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00324 return "";
00325 }
00326
00327 memset(buf, 0, len);
00328
00329 res = SQLFetch(stmt);
00330 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00331 if (res == SQL_NO_DATA) {
00332 if (option_verbose > 3) {
00333 ast_verbose(VERBOSE_PREFIX_4 "Found no rows [%s]\n", sql);
00334 }
00335 } else if (option_verbose > 3) {
00336 ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql);
00337 }
00338 goto acf_out;
00339 }
00340
00341 for (x = 0; x < colcount; x++) {
00342 int i;
00343 char coldata[256];
00344
00345 buflen = strlen(buf);
00346 res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata, sizeof(coldata), &indicator);
00347 if (indicator == SQL_NULL_DATA) {
00348 coldata[0] = '\0';
00349 res = SQL_SUCCESS;
00350 }
00351
00352 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00353 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00354 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00355 return "";
00356 }
00357
00358 /* Copy data, encoding '\' and ',' for the argument parser */
00359 for (i = 0; i < sizeof(coldata); i++) {
00360 if (coldata[i] == '\\' || coldata[i] == ',') {
00361 buf[buflen++] = '\\';
00362 }
00363 buf[buflen++] = coldata[i];
00364
00365 if (buflen >= len - 2) {
00366 buf[buflen >= len ? len - 1 : buflen] = '\0';
00367 break;
00368 }
00369
00370 if (coldata[i] == '\0')
00371 break;
00372 }
00373
00374 buf[buflen - 1] = ',';
00375 }
00376 /* Trim trailing comma */
00377 buf[buflen - 1] = '\0';
00378
00379 acf_out:
00380 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00381 return buf;
00382 }
|
|
||||||||||||||||||||
|
Definition at line 76 of file func_odbc.c. References ast_channel_alloc(), ast_channel_free(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, odbc_obj::con, fetch_odbc_obj(), list, LOG_ERROR, LOG_WARNING, odbc_obj_connect(), odbc_obj_disconnect(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and t. Referenced by init_acf_query(). 00077 {
00078 odbc_obj *obj;
00079 struct acf_odbc_query *query;
00080 char *s, *t, *arg, buf[2048]="", varname[15];
00081 int res, argcount=0, valcount=0, i, retry=0;
00082 struct ast_channel *ast;
00083 SQLHSTMT stmt;
00084 SQLINTEGER nativeerror=0, numfields=0, rows=0;
00085 SQLSMALLINT diagbytes=0;
00086 unsigned char state[10], diagnostic[256];
00087 #ifdef NEEDTRACE
00088 SQLINTEGER enable = 1;
00089 char *tracefile = "/tmp/odbc.trace";
00090 #endif
00091
00092 AST_LIST_LOCK(&queries);
00093 AST_LIST_TRAVERSE(&queries, query, list) {
00094 if (!strcmp(query->acf->name, cmd)) {
00095 break;
00096 }
00097 }
00098
00099 if (!query) {
00100 ast_log(LOG_ERROR, "No such function '%s'\n", cmd);
00101 AST_LIST_UNLOCK(&queries);
00102 return;
00103 }
00104
00105 obj = fetch_odbc_obj(query->dsn, 0);
00106
00107 if (!obj) {
00108 ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn);
00109 AST_LIST_UNLOCK(&queries);
00110 return;
00111 }
00112
00113 /* Parse our arguments */
00114 s = ast_strdupa(data);
00115 if (value) {
00116 t = ast_strdupa(value);
00117 } else {
00118 t = "";
00119 }
00120
00121 if (!s || !t) {
00122 ast_log(LOG_ERROR, "Out of memory\n");
00123 AST_LIST_UNLOCK(&queries);
00124 return;
00125 }
00126
00127 /* XXX You might be tempted to change this section into using
00128 * pbx_builtin_pushvar_helper(). However, note that if you try
00129 * to set a NULL (like for VALUE), then nothing gets set, and the
00130 * value doesn't get masked out. Even worse, when you subsequently
00131 * try to remove the value you just set, you'll wind up unsetting
00132 * the previous value (which is wholly undesireable). Hence, this
00133 * has to remain the way it is done here. XXX
00134 */
00135
00136 /* Save old arguments as variables in a fake channel */
00137 ast = ast_channel_alloc(0);
00138 while ((arg = strsep(&s, "|"))) {
00139 argcount++;
00140 snprintf(varname, sizeof(varname), "ARG%d", argcount);
00141 pbx_builtin_setvar_helper(ast, varname, pbx_builtin_getvar_helper(chan, varname));
00142 pbx_builtin_setvar_helper(chan, varname, arg);
00143 }
00144
00145 /* Parse values, just like arguments */
00146 while ((arg = strsep(&t, "|"))) {
00147 valcount++;
00148 snprintf(varname, sizeof(varname), "VAL%d", valcount);
00149 pbx_builtin_setvar_helper(ast, varname, pbx_builtin_getvar_helper(chan, varname));
00150 pbx_builtin_setvar_helper(chan, varname, arg);
00151 }
00152
00153 /* Additionally set the value as a whole */
00154 /* Note that pbx_builtin_setvar_helper will quite happily take a NULL for the 3rd argument */
00155 pbx_builtin_setvar_helper(ast, "VALUE", pbx_builtin_getvar_helper(chan, "VALUE"));
00156 pbx_builtin_setvar_helper(chan, "VALUE", value);
00157
00158 pbx_substitute_variables_helper(chan, query->sql_write, buf, sizeof(buf) - 1);
00159
00160 /* Restore prior values */
00161 for (i=1; i<=argcount; i++) {
00162 snprintf(varname, sizeof(varname), "ARG%d", argcount);
00163 pbx_builtin_setvar_helper(chan, varname, pbx_builtin_getvar_helper(ast, varname));
00164 }
00165
00166 for (i=1; i<=valcount; i++) {
00167 snprintf(varname, sizeof(varname), "VAL%d", argcount);
00168 pbx_builtin_setvar_helper(chan, varname, pbx_builtin_getvar_helper(ast, varname));
00169 }
00170 pbx_builtin_setvar_helper(chan, "VALUE", pbx_builtin_getvar_helper(ast, "VALUE"));
00171
00172 ast_channel_free(ast);
00173 AST_LIST_UNLOCK(&queries);
00174
00175 retry_write:
00176 #ifdef NEEDTRACE
00177 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
00178 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
00179 #endif
00180
00181 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
00182 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00183 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00184 pbx_builtin_setvar_helper(chan, "ODBCROWS", "-1");
00185 return;
00186 }
00187
00188 res = SQLPrepare(stmt, (unsigned char *)buf, SQL_NTS);
00189 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00190 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", buf);
00191 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00192 pbx_builtin_setvar_helper(chan, "ODBCROWS", "-1");
00193 return;
00194 }
00195
00196 res = SQLExecute(stmt);
00197 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00198 if (res == SQL_ERROR) {
00199 SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
00200 for (i = 0; i <= numfields; i++) {
00201 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
00202 ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
00203 if (i > 10) {
00204 ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields);
00205 break;
00206 }
00207 }
00208 }
00209 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00210 odbc_obj_disconnect(obj);
00211 /* All handles are now invalid (after a disconnect), so we gotta redo all handles */
00212 odbc_obj_connect(obj);
00213 if (!retry) {
00214 retry = 1;
00215 goto retry_write;
00216 }
00217 rows = -1;
00218 } else {
00219 /* Rows affected */
00220 SQLRowCount(stmt, &rows);
00221 }
00222
00223 /* Output the affected rows, for all cases. In the event of failure, we
00224 * flag this as -1 rows. Note that this is different from 0 affected rows
00225 * which would be the case if we succeeded in our query, but the values did
00226 * not change. */
00227 snprintf(varname, sizeof(varname), "%d", (int)rows);
00228 pbx_builtin_setvar_helper(chan, "ODBCROWS", varname);
00229
00230 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00231 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", buf);
00232 }
00233
00234 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00235 }
|
|
||||||||||||
|
|
|
|
Provides a description of the module.
Definition at line 640 of file func_odbc.c. References tdesc. 00641 {
00642 return tdesc;
00643 }
|
|
|
Definition at line 516 of file func_odbc.c. References free. Referenced by odbc_load_module(), odbc_unload_module(), and reload(). 00517 {
00518 if (query) {
00519 if (query->acf) {
00520 if (query->acf->name)
00521 free(query->acf->name);
00522 if (query->acf->syntax)
00523 free(query->acf->syntax);
00524 if (query->acf->desc)
00525 free(query->acf->desc);
00526 free(query->acf);
00527 }
00528 free(query);
00529 }
00530 return 0;
00531 }
|
|
||||||||||||||||
|
Definition at line 413 of file func_odbc.c. References acf_odbc_read(), acf_odbc_write(), ast_strlen_zero(), ast_variable_retrieve(), calloc, and free. Referenced by odbc_load_module(), and reload(). 00414 {
00415 char *tmp;
00416
00417 if (!cfg || !catg) {
00418 return -1;
00419 }
00420
00421 *query = calloc(1, sizeof(struct acf_odbc_query));
00422 if (! (*query))
00423 return -1;
00424
00425 if ((tmp = ast_variable_retrieve(cfg, catg, "dsn"))) {
00426 ast_copy_string((*query)->dsn, tmp, sizeof((*query)->dsn));
00427 } else {
00428 return -1;
00429 }
00430
00431 if ((tmp = ast_variable_retrieve(cfg, catg, "read"))) {
00432 ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read));
00433 }
00434
00435 if ((tmp = ast_variable_retrieve(cfg, catg, "write"))) {
00436 ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write));
00437 }
00438
00439 (*query)->acf = calloc(1, sizeof(struct ast_custom_function));
00440 if (! (*query)->acf) {
00441 free(*query);
00442 return -1;
00443 }
00444
00445 if ((tmp = ast_variable_retrieve(cfg, catg, "prefix")) && !ast_strlen_zero(tmp)) {
00446 asprintf((char **)&((*query)->acf->name), "%s_%s", tmp, catg);
00447 } else {
00448 asprintf((char **)&((*query)->acf->name), "ODBC_%s", catg);
00449 }
00450
00451 if (!((*query)->acf->name)) {
00452 free((*query)->acf);
00453 free(*query);
00454 return -1;
00455 }
00456
00457 asprintf((char **)&((*query)->acf->syntax), "%s(<arg1>[...[,<argN>]])", (*query)->acf->name);
00458
00459 if (!((*query)->acf->syntax)) {
00460 free((char *)(*query)->acf->name);
00461 free((*query)->acf);
00462 free(*query);
00463 return -1;
00464 }
00465
00466 (*query)->acf->synopsis = "Runs the referenced query with the specified arguments";
00467 if (!ast_strlen_zero((*query)->sql_read) && !ast_strlen_zero((*query)->sql_write)) {
00468 asprintf((char **)&((*query)->acf->desc),
00469 "Runs the following query, as defined in func_odbc.conf, performing\n"
00470 "substitution of the arguments into the query as specified by ${ARG1},\n"
00471 "${ARG2}, ... ${ARGn}. When setting the function, the values are provided\n"
00472 "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
00473 "\nRead:\n%s\n\nWrite:\n%s\n",
00474 (*query)->sql_read,
00475 (*query)->sql_write);
00476 } else if (!ast_strlen_zero((*query)->sql_read)) {
00477 asprintf((char **)&((*query)->acf->desc),
00478 "Runs the following query, as defined in func_odbc.conf, performing\n"
00479 "substitution of the arguments into the query as specified by ${ARG1},\n"
00480 "${ARG2}, ... ${ARGn}. This function may only be read, not set.\n\nSQL:\n%s\n",
00481 (*query)->sql_read);
00482 } else if (!ast_strlen_zero((*query)->sql_write)) {
00483 asprintf((char **)&((*query)->acf->desc),
00484 "Runs the following query, as defined in func_odbc.conf, performing\n"
00485 "substitution of the arguments into the query as specified by ${ARG1},\n"
00486 "${ARG2}, ... ${ARGn}. The values are provided either in whole as\n"
00487 "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
00488 "This function may only be set.\nSQL:\n%s\n",
00489 (*query)->sql_write);
00490 }
00491
00492 /* Could be out of memory, or could be we have neither sql_read nor sql_write */
00493 if (! ((*query)->acf->desc)) {
00494 free((char *)(*query)->acf->syntax);
00495 free((char *)(*query)->acf->name);
00496 free((*query)->acf);
00497 free(*query);
00498 return -1;
00499 }
00500
00501 if (ast_strlen_zero((*query)->sql_read)) {
00502 (*query)->acf->read = NULL;
00503 } else {
00504 (*query)->acf->read = acf_odbc_read;
00505 }
00506
00507 if (ast_strlen_zero((*query)->sql_write)) {
00508 (*query)->acf->write = NULL;
00509 } else {
00510 (*query)->acf->write = acf_odbc_write;
00511 }
00512
00513 return 0;
00514 }
|
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 655 of file func_odbc.c. References ASTERISK_GPL_KEY. 00656 {
00657 return ASTERISK_GPL_KEY;
00658 }
|
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 635 of file func_odbc.c. References odbc_load_module(). 00636 {
00637 return odbc_load_module();
00638 }
|
|
|
Definition at line 533 of file func_odbc.c. References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_custom_function_register(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), cfg, config, free_acf_query(), init_acf_query(), list, LOG_ERROR, and LOG_WARNING. Referenced by load_module(), and reload(). 00534 {
00535 int res = 0;
00536 struct ast_config *cfg;
00537 char *catg;
00538
00539 AST_LIST_LOCK(&queries);
00540
00541 cfg = ast_config_load(config);
00542 if (!cfg) {
00543 ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config);
00544 AST_LIST_UNLOCK(&queries);
00545 return -1;
00546 }
00547
00548 for (catg = ast_category_browse(cfg, NULL);
00549 catg;
00550 catg = ast_category_browse(cfg, catg)) {
00551 struct acf_odbc_query *query = NULL;
00552
00553 if (init_acf_query(cfg, catg, &query)) {
00554 ast_log(LOG_ERROR, "Out of memory\n");
00555 free_acf_query(query);
00556 } else {
00557 AST_LIST_INSERT_HEAD(&queries, query, list);
00558 ast_custom_function_register(query->acf);
00559 }
00560 }
00561
00562 ast_config_destroy(cfg);
00563 ast_custom_function_register(&escape_function);
00564
00565 AST_LIST_UNLOCK(&queries);
00566 return res;
00567 }
|
|
|
Definition at line 569 of file func_odbc.c. References ast_custom_function_unregister(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, free_acf_query(), and list. Referenced by reload(), and unload_module(). 00570 {
00571 struct acf_odbc_query *query;
00572
00573 AST_LIST_LOCK(&queries);
00574 while (!AST_LIST_EMPTY(&queries)) {
00575 query = AST_LIST_REMOVE_HEAD(&queries, list);
00576 ast_custom_function_unregister(query->acf);
00577 free_acf_query(query);
00578 }
00579
00580 ast_custom_function_unregister(&escape_function);
00581
00582 /* Allow any threads waiting for this lock to pass (avoids a race) */
00583 AST_LIST_UNLOCK(&queries);
00584 AST_LIST_LOCK(&queries);
00585
00586 AST_LIST_UNLOCK(&queries);
00587 return 0;
00588 }
|
|
|
Reload stuff. This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.
Definition at line 590 of file func_odbc.c. References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_custom_function_register(), ast_custom_function_unregister(), AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), cfg, config, free_acf_query(), init_acf_query(), list, LOG_ERROR, and LOG_WARNING. 00591 {
00592 int res = 0;
00593 struct ast_config *cfg;
00594 struct acf_odbc_query *oldquery;
00595 char *catg;
00596
00597 AST_LIST_LOCK(&queries);
00598
00599 while (!AST_LIST_EMPTY(&queries)) {
00600 oldquery = AST_LIST_REMOVE_HEAD(&queries, list);
00601 ast_custom_function_unregister(oldquery->acf);
00602 free_acf_query(oldquery);
00603 }
00604
00605 cfg = ast_config_load(config);
00606 if (!cfg) {
00607 ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config);
00608 goto reload_out;
00609 }
00610
00611 for (catg = ast_category_browse(cfg, NULL);
00612 catg;
00613 catg = ast_category_browse(cfg, catg)) {
00614 struct acf_odbc_query *query = NULL;
00615
00616 if (init_acf_query(cfg, catg, &query)) {
00617 ast_log(LOG_ERROR, "Cannot initialize query %s\n", catg);
00618 } else {
00619 AST_LIST_INSERT_HEAD(&queries, query, list);
00620 ast_custom_function_register(query->acf);
00621 }
00622 }
00623
00624 ast_config_destroy(cfg);
00625 reload_out:
00626 AST_LIST_UNLOCK(&queries);
00627 return res;
00628 }
|
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 630 of file func_odbc.c. References odbc_unload_module(). 00631 {
00632 return odbc_unload_module();
00633 }
|
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 645 of file func_odbc.c. References ast_mutex_trylock(), ast_mutex_unlock(), and lock. 00646 {
00647 if (! ast_mutex_trylock(&(&queries)->lock)) {
00648 ast_mutex_unlock(&(&queries)->lock);
00649 return 0;
00650 } else {
00651 return 1;
00652 }
00653 }
|
|
|
Definition at line 50 of file func_odbc.c. |
|
|
Definition at line 399 of file func_odbc.c. |
|
|
Definition at line 48 of file func_odbc.c. |
1.4.2