Sun Aug 6 15:11:47 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

func_odbc.c File Reference

ODBC lookups. More...

#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"


Detailed Description

ODBC lookups.

Author:
Tilghman Lesher <func_odbc__200604@the-tilghman.com>

Definition in file func_odbc.c.


Function Documentation

static char* acf_escape struct ast_channel chan,
char *  cmd,
char *  data,
char *  buf,
size_t  len
[static]
 

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 }

static char* acf_odbc_read struct ast_channel chan,
char *  cmd,
char *  data,
char *  buf,
size_t  len
[static]
 

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 }

static void acf_odbc_write struct ast_channel chan,
char *  cmd,
char *  data,
const char *  value
[static]
 

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 }

AST_LIST_HEAD_STATIC queries  ,
acf_odbc_query 
 

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 640 of file func_odbc.c.

References tdesc.

00641 {
00642    return tdesc;
00643 }

static int free_acf_query struct acf_odbc_query query  )  [static]
 

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 }

static int init_acf_query struct ast_config cfg,
char *  catg,
struct acf_odbc_query **  query
[static]
 

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 }

char* key void   ) 
 

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;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 655 of file func_odbc.c.

References ASTERISK_GPL_KEY.

00656 {
00657    return ASTERISK_GPL_KEY;
00658 }

int load_module void   ) 
 

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.

Returns:
int Always 0.

Definition at line 635 of file func_odbc.c.

References odbc_load_module().

00636 {
00637    return odbc_load_module();
00638 }

static int odbc_load_module void   )  [static]
 

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 }

static int odbc_unload_module void   )  [static]
 

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 }

int reload void   ) 
 

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
The return value is not used.

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 }

int unload_module void   ) 
 

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).

Returns:
Zero on success, or non-zero on error.

Definition at line 630 of file func_odbc.c.

References odbc_unload_module().

00631 {
00632    return odbc_unload_module();
00633 }

int usecount void   ) 
 

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.

Returns:
The module's usecount.

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 }


Variable Documentation

char* config = "func_odbc.conf" [static]
 

Definition at line 50 of file func_odbc.c.

struct ast_custom_function escape_function [static]
 

Definition at line 399 of file func_odbc.c.

char* tdesc = "ODBC lookups" [static]
 

Definition at line 48 of file func_odbc.c.


Generated on Sun Aug 6 15:11:48 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2