Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:25 2009

## Asterisk developer's documentation

# cdr_odbc.c File Reference

ODBC CDR Backend. More...

`#include <sys/types.h>`
`#include <stdio.h>`
`#include <string.h>`
`#include <stdlib.h>`
`#include <unistd.h>`
`#include <time.h>`
`#include <sql.h>`
`#include <sqlext.h>`
`#include <sqltypes.h>`
`#include "asterisk.h"`
`#include "asterisk/config.h"`
`#include "asterisk/options.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/cdr.h"`
`#include "asterisk/module.h"`
`#include "asterisk/logger.h"`

Include dependency graph for cdr_odbc.c:

Go to the source code of this file.

## Defines

#define | DATE_FORMAT "%Y-%m-%d %T"

## Functions

| AST_MUTEX_DEFINE_STATIC (odbc_lock)
char * | description (void)
| Provides a description of the module.
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module (void)
| Initialize the module.
static void | odbc_disconnect (void)
static int | odbc_do_query (void)
static int | odbc_init (void)
static int | odbc_load_module (void)
static int | odbc_log (struct ast_cdr *cdr)
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 = "cdr_odbc.conf"
static int | connected = 0
static char * | desc = "ODBC CDR Backend"
static int | dispositionstring = 0
static char * | dsn = NULL
static int | loguniqueid = 0
static char * | name = "ODBC"
static SQLHDBC | ODBC_con
static SQLHENV | ODBC_env = SQL_NULL_HANDLE
static SQLHSTMT | ODBC_stmt
static char * | password = NULL
static char * | table = NULL
static int | usegmtime = 0
static char * | username = NULL

## Detailed Description

ODBC CDR Backend.

Author:
  Brian K. West <brian@bkw.org>

See also:

- http://www.unixodbc.org
- CDR configuration

Definition in file cdr_odbc.c.

## Define Documentation

#define DATE_FORMAT "%Y-%m-%d %T"

Definition at line 61 of file cdr_odbc.c.

## Function Documentation

AST_MUTEX_DEFINE_STATIC | ( | odbc_lock |  | ) |

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 206 of file cdr_odbc.c.

    00207 {
    00208    return desc;
    00209 }

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 478 of file cdr_odbc.c.

References ASTERISK_GPL_KEY.

    00479 {
    00480    return ASTERISK_GPL_KEY;
    00481 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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.

TE STUFF END

Definition at line 451 of file cdr_odbc.c.

References odbc_load_module().

    00452 {
    00453    return odbc_load_module();
    00454 }

static void odbc_disconnect | ( | void |  | ) | `[static]`

Definition at line 81 of file cdr_odbc.c.

Referenced by odbc_do_query(), odbc_log(), and odbc_unload_module().

    00082 {
    00083    SQLDisconnect(ODBC_con);
    00084    SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
    00085    SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
    00086    connected = 0;
    00087 }

static int odbc_do_query | ( | void |  | ) | `[static]`

Definition at line 374 of file cdr_odbc.c.

References ast_verbose(), odbc_disconnect(), option_verbose, and VERBOSE_PREFIX_4.

Referenced by odbc_log().

    00375 {
    00376    SQLINTEGER ODBC_err;
    00377    int ODBC_res;
    00378    short int ODBC_mlen;
    00379    char ODBC_msg[200], ODBC_stat[10];
    00380
    00381    ODBC_res = SQLExecute(ODBC_stmt);
    00382
    00383    if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
    00384       if (option_verbose > 10)
    00385          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in Query %d\n", ODBC_res);
    00386       SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
    00387       odbc_disconnect();
    00388       return -1;
    00389    } else {
    00390       if (option_verbose > 10)
    00391          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query Successful!\n");
    00392       connected = 1;
    00393    }
    00394    return 0;
    00395 }

static int odbc_init | ( | void |  | ) | `[static]`

Definition at line 397 of file cdr_odbc.c.

References ast_verbose(), option_verbose, and VERBOSE_PREFIX_4.

Referenced by load_module(), odbc_load_module(), and odbc_log().

    00398 {
    00399    int ODBC_res;
    00400
    00401    if (ODBC_env == SQL_NULL_HANDLE || connected == 0) {
    00402       ODBC_res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &ODBC_env);
    00403       if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
    00404          if (option_verbose > 10)
    00405             ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHandle\n");
    00406          connected = 0;
    00407          return -1;
    00408       }
    00409
    00410       ODBC_res = SQLSetEnvAttr(ODBC_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
    00411
    00412       if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
    00413          if (option_verbose > 10)
    00414             ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SetEnv\n");
    00415          SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
    00416          connected = 0;
    00417          return -1;
    00418       }
    00419
    00420       ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con);
    00421
    00422       if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
    00423          if (option_verbose > 10)
    00424             ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHDB %d\n", ODBC_res);
    00425          SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
    00426          connected = 0;
    00427          return -1;
    00428       }
    00429       SQLSetConnectAttr(ODBC_con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)10, 0);
    00430    }
    00431
    00432    /* Note that the username and password could be NULL here, but that is allowed in ODBC.
    00433            In this case, the default username and password will be used from odbc.conf */
    00434    ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
    00435
    00436    if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
    00437       if (option_verbose > 10)
    00438          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SQLConnect %d\n", ODBC_res);
    00439       SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
    00440       SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
    00441       connected = 0;
    00442       return -1;
    00443    } else {
    00444       if (option_verbose > 10)
    00445          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Connected to %s\n", dsn);
    00446       connected = 1;
    00447    }
    00448    return 0;
    00449 }

static int odbc_load_module | ( | void |  | ) | `[static]`

Definition at line 246 of file cdr_odbc.c.

References ast_cdr_register(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), cfg, LOG_DEBUG, LOG_ERROR, LOG_WARNING, odbc_init(), odbc_log(), option_verbose, strdup, var, and VERBOSE_PREFIX_3.

Referenced by load_module(), and reload().

    00247 {
    00248    int res = 0;
    00249    struct ast_config *cfg;
    00250    struct ast_variable *var;
    00251    char *tmp;
    00252
    00253    ast_mutex_lock(&odbc_lock);
    00254
    00255    cfg = ast_config_load(config);
    00256    if (!cfg) {
    00257       ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config);
    00258       goto out;
    00259    }
    00260
    00261    var = ast_variable_browse(cfg, "global");
    00262    if (!var) {
    00263       /* nothing configured */
    00264       goto out;
    00265    }
    00266
    00267    tmp = ast_variable_retrieve(cfg,"global","dsn");
    00268    if (tmp == NULL) {
    00269       ast_log(LOG_WARNING,"cdr_odbc: dsn not specified.  Assuming asteriskdb\n");
    00270       tmp = "asteriskdb";
    00271    }
    00272    dsn = strdup(tmp);
    00273    if (dsn == NULL) {
    00274       ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
    00275       res = -1;
    00276       goto out;
    00277    }
    00278
    00279    tmp = ast_variable_retrieve(cfg,"global","dispositionstring");
    00280    if (tmp) {
    00281       dispositionstring = ast_true(tmp);
    00282    } else {
    00283       dispositionstring = 0;
    00284    }
    00285
    00286    tmp = ast_variable_retrieve(cfg,"global","username");
    00287    if (tmp) {
    00288       username = strdup(tmp);
    00289       if (username == NULL) {
    00290          ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
    00291          res = -1;
    00292          goto out;
    00293       }
    00294    }
    00295
    00296    tmp = ast_variable_retrieve(cfg,"global","password");
    00297    if (tmp) {
    00298       password = strdup(tmp);
    00299       if (password == NULL) {
    00300          ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
    00301          res = -1;
    00302          goto out;
    00303       }
    00304    }
    00305
    00306    tmp = ast_variable_retrieve(cfg,"global","loguniqueid");
    00307    if (tmp) {
    00308       loguniqueid = ast_true(tmp);
    00309       if (loguniqueid) {
    00310          ast_log(LOG_DEBUG,"cdr_odbc: Logging uniqueid\n");
    00311       } else {
    00312          ast_log(LOG_DEBUG,"cdr_odbc: Not logging uniqueid\n");
    00313       }
    00314    } else {
    00315       ast_log(LOG_DEBUG,"cdr_odbc: Not logging uniqueid\n");
    00316       loguniqueid = 0;
    00317    }
    00318
    00319    tmp = ast_variable_retrieve(cfg,"global","usegmtime");
    00320    if (tmp) {
    00321       usegmtime = ast_true(tmp);
    00322       if (usegmtime) {
    00323          ast_log(LOG_DEBUG,"cdr_odbc: Logging in GMT\n");
    00324       } else {
    00325          ast_log(LOG_DEBUG,"cdr_odbc: Not logging in GMT\n");
    00326       }
    00327    } else {
    00328       ast_log(LOG_DEBUG,"cdr_odbc: Not logging in GMT\n");
    00329       usegmtime = 0;
    00330    }
    00331
    00332    tmp = ast_variable_retrieve(cfg,"global","table");
    00333    if (tmp == NULL) {
    00334       ast_log(LOG_WARNING,"cdr_odbc: table not specified.  Assuming cdr\n");
    00335       tmp = "cdr";
    00336    }
    00337    table = strdup(tmp);
    00338    if (table == NULL) {
    00339       ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n");
    00340       res = -1;
    00341       goto out;
    00342    }
    00343
    00344    if (option_verbose > 2) {
    00345       ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: dsn is %s\n",dsn);
    00346       if (username)
    00347       {
    00348          ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: username is %s\n",username);
    00349          ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: password is [secret]\n");
    00350       }
    00351       else
    00352          ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: retreiving username and password from odbc config\n");
    00353       ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: table is %s\n",table);
    00354    }
    00355
    00356    res = odbc_init();
    00357    if (res < 0) {
    00358       ast_log(LOG_ERROR, "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
    00359       if (option_verbose > 2) {
    00360          ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: Unable to connect to datasource: %s\n", dsn);
    00361       }
    00362    }
    00363    res = ast_cdr_register(name, desc, odbc_log);
    00364    if (res) {
    00365       ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n");
    00366    }
    00367 out:
    00368    if (cfg)
    00369       ast_config_destroy(cfg);
    00370    ast_mutex_unlock(&odbc_lock);
    00371    return res;
    00372 }

static int odbc_log | ( | struct ast_cdr * | cdr | ) | `[static]`

Definition at line 89 of file cdr_odbc.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr_disp2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_cdr::billsec, ast_cdr::channel, ast_cdr::clid, DATE_FORMAT, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::lastapp, ast_cdr::lastdata, odbc_disconnect(), odbc_do_query(), odbc_init(), option_verbose, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, ast_cdr::userfield, and VERBOSE_PREFIX_4.

Referenced by odbc_load_module().

    00090 {
    00091    int ODBC_res;
    00092    char sqlcmd[2048] = "", timestr[128];
    00093    int res = 0;
    00094    struct tm tm;
    00095
    00096    if (usegmtime)
    00097       gmtime_r(&cdr->start.tv_sec,&tm);
    00098    else
    00099       localtime_r(&cdr->start.tv_sec,&tm);
    00100
    00101    ast_mutex_lock(&odbc_lock);
    00102    strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
    00103    memset(sqlcmd,0,2048);
    00104    if (loguniqueid) {
    00105       snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
    00106       "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,"
    00107       "lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) "
    00108       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table);
    00109    } else {
    00110       snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO %s "
    00111       "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,"
    00112       "duration,billsec,disposition,amaflags,accountcode) "
    00113       "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)", table);
    00114    }
    00115
    00116    if (!connected) {
    00117       res = odbc_init();
    00118       if (res < 0) {
    00119          odbc_disconnect();
    00120          ast_mutex_unlock(&odbc_lock);
    00121          return 0;
    00122       }
    00123    }
    00124
    00125    ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, ODBC_con, &ODBC_stmt);
    00126
    00127    if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
    00128       if (option_verbose > 10)
    00129          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Failure in AllocStatement %d\n", ODBC_res);
    00130       SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
    00131       odbc_disconnect();
    00132       ast_mutex_unlock(&odbc_lock);
    00133       return 0;
    00134    }
    00135
    00136    /* We really should only have to do this once.  But for some
    00137       strange reason if I don't it blows holes in memory like
    00138       like a shotgun.  So we just do this so its safe. */
    00139
    00140    ODBC_res = SQLPrepare(ODBC_stmt, (unsigned char *)sqlcmd, SQL_NTS);
    00141
    00142    if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) {
    00143       if (option_verbose > 10)
    00144          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in PREPARE %d\n", ODBC_res);
    00145       SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
    00146       odbc_disconnect();
    00147       ast_mutex_unlock(&odbc_lock);
    00148       return 0;
    00149    }
    00150
    00151    SQLBindParameter(ODBC_stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(timestr), 0, &timestr, 0, NULL);
    00152    SQLBindParameter(ODBC_stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->clid), 0, cdr->clid, 0, NULL);
    00153    SQLBindParameter(ODBC_stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->src), 0, cdr->src, 0, NULL);
    00154    SQLBindParameter(ODBC_stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dst), 0, cdr->dst, 0, NULL);
    00155    SQLBindParameter(ODBC_stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dcontext), 0, cdr->dcontext, 0, NULL);
    00156    SQLBindParameter(ODBC_stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->channel), 0, cdr->channel, 0, NULL);
    00157    SQLBindParameter(ODBC_stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->dstchannel), 0, cdr->dstchannel, 0, NULL);
    00158    SQLBindParameter(ODBC_stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
    00159    SQLBindParameter(ODBC_stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
    00160    SQLBindParameter(ODBC_stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
    00161    SQLBindParameter(ODBC_stmt, 11, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
    00162    if (dispositionstring)
    00163       SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ast_cdr_disp2str(cdr->disposition)) + 1, 0, ast_cdr_disp2str(cdr->disposition), 0, NULL);
    00164    else
    00165       SQLBindParameter(ODBC_stmt, 12, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->disposition, 0, NULL);
    00166    SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL);
    00167    SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL);
    00168
    00169    if (loguniqueid) {
    00170       SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL);
    00171       SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL);
    00172    }
    00173
    00174    if (connected) {
    00175       res = odbc_do_query();
    00176       if (res < 0) {
    00177          if (option_verbose > 10)
    00178             ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
    00179          if (option_verbose > 10)
    00180             ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Reconnecting to dsn %s\n", dsn);
    00181          SQLDisconnect(ODBC_con);
    00182          res = odbc_init();
    00183          if (res < 0) {
    00184             if (option_verbose > 10)
    00185                ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: %s has gone away!\n", dsn);
    00186             odbc_disconnect();
    00187          } else {
    00188             if (option_verbose > 10)
    00189                ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Trying Query again!\n");
    00190             res = odbc_do_query();
    00191             if (res < 0) {
    00192                if (option_verbose > 10)
    00193                   ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
    00194             }
    00195          }
    00196       }
    00197    } else {
    00198       if (option_verbose > 10)
    00199          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n");
    00200    }
    00201    SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
    00202    ast_mutex_unlock(&odbc_lock);
    00203    return 0;
    00204 }

static int odbc_unload_module | ( | void |  | ) | `[static]`

Definition at line 211 of file cdr_odbc.c.

References ast_cdr_unregister(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, odbc_disconnect(), option_verbose, and VERBOSE_PREFIX_4.

Referenced by reload(), and unload_module().

    00212 {
    00213    ast_mutex_lock(&odbc_lock);
    00214    if (connected) {
    00215       if (option_verbose > 10)
    00216          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Disconnecting from %s\n", dsn);
    00217       SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
    00218       odbc_disconnect();
    00219    }
    00220    if (dsn) {
    00221       if (option_verbose > 10)
    00222          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free dsn\n");
    00223       free(dsn);
    00224    }
    00225    if (username) {
    00226       if (option_verbose > 10)
    00227          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free username\n");
    00228       free(username);
    00229    }
    00230    if (password) {
    00231       if (option_verbose > 10)
    00232          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free password\n");
    00233       free(password);
    00234    }
    00235    if (table) {
    00236       if (option_verbose > 10)
    00237          ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free table\n");
    00238       free(table);
    00239    }
    00240
    00241    ast_cdr_unregister(name);
    00242    ast_mutex_unlock(&odbc_lock);
    00243    return 0;
    00244 }

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 461 of file cdr_odbc.c.

References odbc_load_module(), and odbc_unload_module().

    00462 {
    00463    odbc_unload_module();
    00464    return odbc_load_module();
    00465 }

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 456 of file cdr_odbc.c.

References odbc_unload_module().

    00457 {
    00458    return odbc_unload_module();
    00459 }

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 467 of file cdr_odbc.c.

References ast_mutex_trylock(), and ast_mutex_unlock().

    00468 {
    00469    /* Simplistic use count */
    00470    if (ast_mutex_trylock(&odbc_lock)) {
    00471       return 1;
    00472    } else {
    00473       ast_mutex_unlock(&odbc_lock);
    00474       return 0;
    00475    }
    00476 }

## Variable Documentation

char* config = "cdr_odbc.conf"`[static]`

Definition at line 65 of file cdr_odbc.c.

int connected = 0`[static]`

Definition at line 70 of file cdr_odbc.c.

char* desc = "ODBC CDR Backend"`[static]`

Definition at line 63 of file cdr_odbc.c.

int dispositionstring = 0`[static]`

Definition at line 69 of file cdr_odbc.c.

char* dsn = NULL`[static]`

Definition at line 66 of file cdr_odbc.c.

Referenced by load_odbc_config().

int loguniqueid = 0`[static]`

Definition at line 67 of file cdr_odbc.c.

char* name = "ODBC"`[static]`

Definition at line 64 of file cdr_odbc.c.

SQLHDBC ODBC_con`[static]`

Definition at line 78 of file cdr_odbc.c.

SQLHENV ODBC_env = SQL_NULL_HANDLE`[static]`

Definition at line 77 of file cdr_odbc.c.

SQLHSTMT ODBC_stmt`[static]`

Definition at line 79 of file cdr_odbc.c.

char * password = NULL`[static]`

Definition at line 66 of file cdr_odbc.c.

Referenced by add_agent(), auth_exec(), authenticate(), load_odbc_config(), and vm_authenticate().

char * table = NULL`[static]`

Definition at line 66 of file cdr_odbc.c.

Referenced by ast_config_internal_load(), ast_load_realtime(), ast_load_realtime_multientry(), ast_update_realtime(), and read_config_maps().

int usegmtime = 0`[static]`

Definition at line 68 of file cdr_odbc.c.

char * username = NULL`[static]`

Definition at line 66 of file cdr_odbc.c.

Referenced by action_agents(), add_realm_authentication(), agents_show(), build_reply_digest(), forward_message(), load_odbc_config(), reg_source_db(), and sip_register().