Sat Sep 16 07:28:20 2006

Asterisk developer's documentation


res_odbc.h File Reference

ODBC resource manager. More...

#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>

Go to the source code of this file.

Data Structures

struct  odbc_obj

Typedefs

typedef odbc_obj odbc_obj

Enumerations

enum  odbc_status { ODBC_SUCCESS = 0, ODBC_FAIL = -1 }

Functions

void destroy_odbc_obj (odbc_obj **obj)
odbc_objfetch_odbc_obj (const char *name, int check)
odbc_objnew_odbc_obj (char *name, char *dsn, char *username, char *password)
int odbc_dump_fd (int fd, odbc_obj *obj)
odbc_status odbc_obj_connect (odbc_obj *obj)
odbc_status odbc_obj_disconnect (odbc_obj *obj)
SQLHSTMT odbc_prepare_and_execute (odbc_obj *obj, SQLHSTMT(*prepare_cb)(odbc_obj *obj, void *data), void *data)
int odbc_sanity_check (odbc_obj *obj)
int odbc_smart_direct_execute (odbc_obj *obj, SQLHSTMT stmt, char *sql)
int odbc_smart_execute (odbc_obj *obj, SQLHSTMT stmt)
int register_odbc_obj (char *name, odbc_obj *obj)


Detailed Description

ODBC resource manager.

Definition in file res_odbc.h.


Typedef Documentation

typedef struct odbc_obj odbc_obj

Definition at line 32 of file res_odbc.h.


Enumeration Type Documentation

enum odbc_status

Enumerator:
ODBC_SUCCESS 
ODBC_FAIL 

Definition at line 34 of file res_odbc.h.


Function Documentation

void destroy_odbc_obj ( odbc_obj **  obj  ) 

Definition at line 468 of file res_odbc.c.

References ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), free, and odbc_obj_disconnect().

Referenced by odbc_destroy().

00469 {
00470    odbc_obj_disconnect(*obj);
00471 
00472    ast_mutex_lock(&(*obj)->lock);
00473    SQLFreeHandle(SQL_HANDLE_STMT, (*obj)->stmt);
00474    SQLFreeHandle(SQL_HANDLE_DBC, (*obj)->con);
00475    SQLFreeHandle(SQL_HANDLE_ENV, (*obj)->env);
00476 
00477    free((*obj)->name);
00478    free((*obj)->dsn);
00479    if ((*obj)->username)
00480       free((*obj)->username);
00481    if ((*obj)->password)
00482       free((*obj)->password);
00483    ast_mutex_unlock(&(*obj)->lock);
00484    ast_mutex_destroy(&(*obj)->lock);
00485    free(*obj);
00486 }

odbc_obj* fetch_odbc_obj ( const char *  name,
int  check 
)

Definition at line 417 of file res_odbc.c.

References odbc_read(), ODBC_REGISTRY, and odbc_sanity_check().

Referenced by config_odbc(), realtime_multi_odbc(), realtime_odbc(), and update_odbc().

00418 {
00419    odbc_obj *obj = NULL;
00420    if((obj = (odbc_obj *) odbc_read(ODBC_REGISTRY, name))) {
00421       if(check)
00422          odbc_sanity_check(obj);
00423    }
00424    return obj;
00425 }

odbc_obj* new_odbc_obj ( char *  name,
char *  dsn,
char *  username,
char *  password 
)

Definition at line 427 of file res_odbc.c.

References ast_mutex_init(), calloc, cleanup(), free, and malloc.

Referenced by load_odbc_config().

00428 {
00429    static odbc_obj *new;
00430 
00431    if (!(new = calloc(1, sizeof(*new))) || 
00432        !(new->name = malloc(strlen(name) + 1)) || 
00433        !(new->dsn = malloc(strlen(dsn) + 1)))
00434          goto cleanup;
00435 
00436    if (username) {
00437       if (!(new->username = malloc(strlen(username) + 1)))
00438          goto cleanup;
00439       strcpy(new->username, username);
00440    }
00441 
00442    if (password) {
00443       if (!(new->password = malloc(strlen(password) + 1)))
00444          goto cleanup;
00445       strcpy(new->password, password);
00446    }
00447 
00448    strcpy(new->name, name);
00449    strcpy(new->dsn, dsn);
00450    new->env = SQL_NULL_HANDLE;
00451    new->up = 0;
00452    ast_mutex_init(&new->lock);
00453    return new;
00454 
00455 cleanup:
00456    if (new) {
00457       free(new->name);
00458       free(new->dsn);
00459       free(new->username);
00460       free(new->password);
00461 
00462       free(new);  
00463    }
00464 
00465    return NULL;
00466 }

int odbc_dump_fd ( int  fd,
odbc_obj obj 
)

Definition at line 309 of file res_odbc.c.

References ast_cli(), odbc_obj::dsn, odbc_obj::name, odbc_sanity_check(), and odbc_obj::up.

Referenced by odbc_show_command().

00310 {
00311    /* make sure the connection is up before we lie to our master.*/
00312    odbc_sanity_check(obj);
00313    ast_cli(fd, "Name: %s\nDSN: %s\nConnected: %s\n\n", obj->name, obj->dsn, obj->up ? "yes" : "no");
00314    return 0;
00315 }

odbc_status odbc_obj_connect ( odbc_obj obj  ) 

Definition at line 507 of file res_odbc.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), odbc_obj::con, odbc_obj::dsn, odbc_obj::env, odbc_obj::lock, LOG_NOTICE, LOG_WARNING, odbc_obj::name, ODBC_FAIL, odbc_obj_disconnect(), ODBC_SUCCESS, option_verbose, odbc_obj::password, odbc_obj::up, and odbc_obj::username.

Referenced by load_odbc_config(), odbc_connect_command(), odbc_prepare_and_execute(), odbc_sanity_check(), and odbc_smart_direct_execute().

00508 {
00509    int res;
00510    SQLINTEGER err;
00511    short int mlen;
00512    unsigned char msg[200], stat[10];
00513 
00514    ast_mutex_lock(&obj->lock);
00515 
00516    if (obj->env == SQL_NULL_HANDLE) {
00517       res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &obj->env);
00518 
00519       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00520          if (option_verbose > 3)
00521             ast_log(LOG_WARNING, "res_odbc: Error AllocHandle\n");
00522          ast_mutex_unlock(&obj->lock);
00523          return ODBC_FAIL;
00524       }
00525 
00526       res = SQLSetEnvAttr(obj->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
00527 
00528       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00529          if (option_verbose > 3)
00530             ast_log(LOG_WARNING, "res_odbc: Error SetEnv\n");
00531          SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
00532          ast_mutex_unlock(&obj->lock);
00533          return ODBC_FAIL;
00534       }
00535 
00536       res = SQLAllocHandle(SQL_HANDLE_DBC, obj->env, &obj->con);
00537 
00538       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00539 
00540          if (option_verbose > 3)
00541             ast_log(LOG_WARNING, "res_odbc: Error AllocHDB %d\n", res);
00542          SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
00543 
00544          ast_mutex_unlock(&obj->lock);
00545          return ODBC_FAIL;
00546       }
00547       SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
00548    }
00549    if(obj->up) {
00550       odbc_obj_disconnect(obj);
00551       ast_log(LOG_NOTICE,"Re-connecting %s\n", obj->name);
00552    }
00553 
00554    ast_log(LOG_NOTICE, "Connecting %s\n", obj->name);
00555 
00556    res = SQLConnect(obj->con,
00557          (SQLCHAR *) obj->dsn, SQL_NTS,
00558          (SQLCHAR *) obj->username, SQL_NTS,
00559          (SQLCHAR *) obj->password, SQL_NTS);
00560 
00561    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00562       SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, 1, stat, &err, msg, 100, &mlen);
00563       SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
00564       ast_mutex_unlock(&obj->lock);
00565       ast_log(LOG_WARNING, "res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (int)err, msg);
00566       return ODBC_FAIL;
00567    } else {
00568 
00569       ast_log(LOG_NOTICE, "res_odbc: Connected to %s [%s]\n", obj->name, obj->dsn);
00570       obj->up = 1;
00571    }
00572 
00573    ast_mutex_unlock(&obj->lock);
00574    return ODBC_SUCCESS;
00575 }

odbc_status odbc_obj_disconnect ( odbc_obj obj  ) 

Definition at line 488 of file res_odbc.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), odbc_obj::con, odbc_obj::dsn, odbc_obj::lock, LOG_WARNING, odbc_obj::name, ODBC_SUCCESS, and odbc_obj::up.

Referenced by destroy_odbc_obj(), odbc_disconnect_command(), odbc_obj_connect(), odbc_prepare_and_execute(), odbc_sanity_check(), and odbc_smart_direct_execute().

00489 {
00490    int res;
00491    ast_mutex_lock(&obj->lock);
00492 
00493    res = SQLDisconnect(obj->con);
00494 
00495 
00496    if (res == ODBC_SUCCESS) {
00497       ast_log(LOG_WARNING, "res_odbc: disconnected %d from %s [%s]\n", res, obj->name, obj->dsn);
00498    } else {
00499       ast_log(LOG_WARNING, "res_odbc: %s [%s] already disconnected\n",
00500       obj->name, obj->dsn);
00501    }
00502    obj->up = 0;
00503    ast_mutex_unlock(&obj->lock);
00504    return ODBC_SUCCESS;
00505 }

SQLHSTMT odbc_prepare_and_execute ( odbc_obj obj,
SQLHSTMT(*)(odbc_obj *obj, void *data)  prepare_cb,
void *  data 
)

Definition at line 110 of file res_odbc.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, odbc_obj_connect(), and odbc_obj_disconnect().

00111 {
00112    int res = 0, i, attempt;
00113    SQLINTEGER nativeerror=0, numfields=0;
00114    SQLSMALLINT diagbytes=0;
00115    unsigned char state[10], diagnostic[256];
00116    SQLHSTMT stmt;
00117 
00118    for (attempt = 0; attempt < 2; attempt++) {
00119       /* This prepare callback may do more than just prepare -- it may also
00120        * bind parameters, bind results, etc.  The real key, here, is that
00121        * when we disconnect, all handles become invalid for most databases.
00122        * We must therefore redo everything when we establish a new
00123        * connection. */
00124       stmt = prepare_cb(obj, data);
00125 
00126       if (stmt) {
00127          res = SQLExecute(stmt);
00128          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
00129             if (res == SQL_ERROR) {
00130                SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
00131                for (i=0; i< numfields + 1; i++) {
00132                   SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
00133                   ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
00134                   if (i > 10) {
00135                      ast_log(LOG_WARNING, "Oh, that was good.  There are really %d diagnostics?\n", (int)numfields);
00136                      break;
00137                   }
00138                }
00139             }
00140 
00141             ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res);
00142             SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00143 
00144             ast_mutex_lock(&obj->lock);
00145             obj->up = 0;
00146             ast_mutex_unlock(&obj->lock);
00147             odbc_obj_disconnect(obj);
00148             odbc_obj_connect(obj);
00149             continue;
00150          }
00151          break;
00152       }
00153    }
00154 
00155    return stmt;
00156 }

int odbc_sanity_check ( odbc_obj obj  ) 

Definition at line 211 of file res_odbc.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), odbc_obj::con, odbc_obj::lock, LOG_WARNING, odbc_list::obj, odbc_obj_connect(), odbc_obj_disconnect(), and odbc_obj::up.

Referenced by fetch_odbc_obj(), and odbc_dump_fd().

00212 {
00213    char *test_sql = "select 1";
00214    SQLHSTMT stmt;
00215    int res = 0;
00216 
00217    ast_mutex_lock(&obj->lock);
00218    if(obj->up) { /* so you say... let's make sure */
00219       res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
00220       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00221          obj->up = 0; /* Liar!*/
00222       } else {
00223          res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS);
00224          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00225             obj->up = 0; /* Liar!*/
00226          } else {
00227             res = SQLExecute(stmt);
00228             if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00229                obj->up = 0; /* Liar!*/
00230             }
00231          }
00232       }
00233       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00234    }
00235    ast_mutex_unlock(&obj->lock);
00236 
00237    if(!obj->up) { /* Try to reconnect! */
00238       ast_log(LOG_WARNING, "Connection is down attempting to reconnect...\n");
00239       odbc_obj_disconnect(obj);
00240       odbc_obj_connect(obj);
00241    }
00242    return obj->up;
00243 }

int odbc_smart_direct_execute ( odbc_obj obj,
SQLHSTMT  stmt,
char *  sql 
)

Definition at line 193 of file res_odbc.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), odbc_obj::lock, LOG_WARNING, odbc_list::obj, odbc_obj_connect(), odbc_obj_disconnect(), and odbc_obj::up.

Referenced by config_odbc().

00194 {
00195    int res = 0;
00196 
00197    res = SQLExecDirect (stmt, (unsigned char *)sql, SQL_NTS);
00198    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00199       ast_log(LOG_WARNING, "SQL Execute error! Attempting a reconnect...\n");
00200       ast_mutex_lock(&obj->lock);
00201       obj->up = 0;
00202       ast_mutex_unlock(&obj->lock);
00203       odbc_obj_disconnect(obj);
00204       odbc_obj_connect(obj);
00205       res = SQLExecDirect (stmt, (unsigned char *)sql, SQL_NTS);
00206    }
00207    
00208    return res;
00209 }

int odbc_smart_execute ( odbc_obj obj,
SQLHSTMT  stmt 
)

Definition at line 158 of file res_odbc.c.

References ast_log(), and LOG_WARNING.

Referenced by realtime_multi_odbc(), realtime_odbc(), and update_odbc().

00159 {
00160    int res = 0, i;
00161    SQLINTEGER nativeerror=0, numfields=0;
00162    SQLSMALLINT diagbytes=0;
00163    unsigned char state[10], diagnostic[256];
00164 
00165    res = SQLExecute(stmt);
00166    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
00167       if (res == SQL_ERROR) {
00168          SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
00169          for (i=0; i< numfields + 1; i++) {
00170             SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
00171             ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
00172             if (i > 10) {
00173                ast_log(LOG_WARNING, "Oh, that was good.  There are really %d diagnostics?\n", (int)numfields);
00174                break;
00175             }
00176          }
00177       }
00178 /*
00179       ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res);
00180       ast_mutex_lock(&obj->lock);
00181       obj->up = 0;
00182       ast_mutex_unlock(&obj->lock);
00183       odbc_obj_disconnect(obj);
00184       odbc_obj_connect(obj);
00185       res = SQLExecute(stmt);
00186 */
00187    }
00188    
00189    return res;
00190 }

int register_odbc_obj ( char *  name,
odbc_obj obj 
)

Definition at line 410 of file res_odbc.c.

References ODBC_REGISTRY, and odbc_write().

Referenced by load_odbc_config().

00411 {
00412    if (obj != NULL)
00413       return odbc_write(ODBC_REGISTRY, name, obj);
00414    return 0;
00415 }


Generated on Sat Sep 16 07:28:20 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7