ast_str_SQLGetData is *not* part of the ast_str API, it's part of the ast_odbc API...
[asterisk/asterisk.git] / res / res_odbc.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * res_odbc.c <ODBC resource manager>
9  * Copyright (C) 2004 - 2005 Anthony Minessale II <anthmct@yahoo.com>
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21
22 /*! \file
23  *
24  * \brief ODBC resource manager
25  * 
26  * \author Mark Spencer <markster@digium.com>
27  * \author Anthony Minessale II <anthmct@yahoo.com>
28  *
29  * \arg See also: \ref cdr_odbc
30  */
31
32 /*** MODULEINFO
33         <depend>generic_odbc</depend>
34         <depend>ltdl</depend>
35  ***/
36
37 #include "asterisk.h"
38
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40
41 #include "asterisk/file.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/config.h"
44 #include "asterisk/pbx.h"
45 #include "asterisk/module.h"
46 #include "asterisk/cli.h"
47 #include "asterisk/lock.h"
48 #include "asterisk/res_odbc.h"
49 #include "asterisk/time.h"
50 #include "asterisk/astobj2.h"
51 #include "asterisk/strings.h"
52
53 struct odbc_class
54 {
55         AST_LIST_ENTRY(odbc_class) list;
56         char name[80];
57         char dsn[80];
58         char *username;
59         char *password;
60         char *sanitysql;
61         SQLHENV env;
62         unsigned int haspool:1;              /* Boolean - TDS databases need this */
63         unsigned int delme:1;                /* Purge the class */
64         unsigned int backslash_is_escape:1;  /* On this database, the backslash is a native escape sequence */
65         unsigned int limit;                  /* 1023 wasn't enough for some people */
66         unsigned int count;                  /* Running count of pooled connections */
67         unsigned int idlecheck;              /* Recheck the connection if it is idle for this long */
68         struct ao2_container *obj_container;
69 };
70
71 struct ao2_container *class_container;
72
73 static AST_RWLIST_HEAD_STATIC(odbc_tables, odbc_cache_tables);
74
75 static odbc_status odbc_obj_connect(struct odbc_obj *obj);
76 static odbc_status odbc_obj_disconnect(struct odbc_obj *obj);
77 static int odbc_register_class(struct odbc_class *class, int connect);
78
79 static void odbc_class_destructor(void *data)
80 {
81         struct odbc_class *class = data;
82         /* Due to refcounts, we can safely assume that any objects with a reference
83          * to us will prevent our destruction, so we don't need to worry about them.
84          */
85         if (class->username)
86                 ast_free(class->username);
87         if (class->password)
88                 ast_free(class->password);
89         if (class->sanitysql)
90                 ast_free(class->sanitysql);
91         ao2_ref(class->obj_container, -1);
92         SQLFreeHandle(SQL_HANDLE_ENV, class->env);
93 }
94
95 static int null_hash_fn(const void *obj, const int flags)
96 {
97         return 0;
98 }
99
100 static void odbc_obj_destructor(void *data)
101 {
102         struct odbc_obj *obj = data;
103         odbc_obj_disconnect(obj);
104         ast_mutex_destroy(&obj->lock);
105         ao2_ref(obj->parent, -1);
106 }
107
108 static void destroy_table_cache(struct odbc_cache_tables *table) {
109         struct odbc_cache_columns *col;
110         ast_debug(1, "Destroying table cache for %s\n", table->table);
111         AST_RWLIST_WRLOCK(&table->columns);
112         while ((col = AST_RWLIST_REMOVE_HEAD(&table->columns, list))) {
113                 ast_free(col);
114         }
115         AST_RWLIST_UNLOCK(&table->columns);
116         AST_RWLIST_HEAD_DESTROY(&table->columns);
117         ast_free(table);
118 }
119
120 /*!
121  * \brief Find or create an entry describing the table specified.
122  * \param obj An active ODBC handle on which to query the table
123  * \param table Tablename to describe
124  * \retval A structure describing the table layout, or NULL, if the table is not found or another error occurs.
125  * When a structure is returned, the contained columns list will be
126  * rdlock'ed, to ensure that it will be retained in memory.
127  */
128 struct odbc_cache_tables *ast_odbc_find_table(const char *database, const char *tablename)
129 {
130         struct odbc_cache_tables *tableptr;
131         struct odbc_cache_columns *entry;
132         char columnname[80];
133         SQLLEN sqlptr;
134         SQLHSTMT stmt = NULL;
135         int res = 0, error = 0, try = 0;
136         struct odbc_obj *obj = ast_odbc_request_obj(database, 0);
137
138         AST_RWLIST_RDLOCK(&odbc_tables);
139         AST_RWLIST_TRAVERSE(&odbc_tables, tableptr, list) {
140                 if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
141                         break;
142                 }
143         }
144         if (tableptr) {
145                 AST_RWLIST_RDLOCK(&tableptr->columns);
146                 AST_RWLIST_UNLOCK(&odbc_tables);
147                 if (obj) {
148                         ast_odbc_release_obj(obj);
149                 }
150                 return tableptr;
151         }
152
153         if (!obj) {
154                 ast_log(LOG_WARNING, "Unable to retrieve database handle for table description '%s@%s'\n", tablename, database);
155                 return NULL;
156         }
157
158         /* Table structure not already cached; build it now. */
159         do {
160 retry:
161                 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
162                 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
163                         if (try == 0) {
164                                 try = 1;
165                                 ast_odbc_sanity_check(obj);
166                                 goto retry;
167                         }
168                         ast_log(LOG_WARNING, "SQL Alloc Handle failed on connection '%s'!\n", database);
169                         break;
170                 }
171
172                 res = SQLColumns(stmt, NULL, 0, NULL, 0, (unsigned char *)tablename, SQL_NTS, (unsigned char *)"%", SQL_NTS);
173                 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
174                         if (try == 0) {
175                                 try = 1;
176                                 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
177                                 ast_odbc_sanity_check(obj);
178                                 goto retry;
179                         }
180                         ast_log(LOG_ERROR, "Unable to query database columns on connection '%s'.\n", database);
181                         break;
182                 }
183
184                 if (!(tableptr = ast_calloc(sizeof(char), sizeof(*tableptr) + strlen(database) + 1 + strlen(tablename) + 1))) {
185                         ast_log(LOG_ERROR, "Out of memory creating entry for table '%s' on connection '%s'\n", tablename, database);
186                         break;
187                 }
188
189                 tableptr->connection = (char *)tableptr + sizeof(*tableptr);
190                 tableptr->table = (char *)tableptr + sizeof(*tableptr) + strlen(database) + 1;
191                 strcpy(tableptr->connection, database); /* SAFE */
192                 strcpy(tableptr->table, tablename); /* SAFE */
193                 AST_RWLIST_HEAD_INIT(&(tableptr->columns));
194
195                 while ((res = SQLFetch(stmt)) != SQL_NO_DATA && res != SQL_ERROR) {
196                         SQLGetData(stmt,  4, SQL_C_CHAR, columnname, sizeof(columnname), &sqlptr);
197
198                         if (!(entry = ast_calloc(sizeof(char), sizeof(*entry) + strlen(columnname) + 1))) {
199                                 ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, tablename, database);
200                                 error = 1;
201                                 break;
202                         }
203                         entry->name = (char *)entry + sizeof(*entry);
204                         strcpy(entry->name, columnname);
205
206                         SQLGetData(stmt,  5, SQL_C_SHORT, &entry->type, sizeof(entry->type), NULL);
207                         SQLGetData(stmt,  7, SQL_C_LONG, &entry->size, sizeof(entry->size), NULL);
208                         SQLGetData(stmt,  9, SQL_C_SHORT, &entry->decimals, sizeof(entry->decimals), NULL);
209                         SQLGetData(stmt, 10, SQL_C_SHORT, &entry->radix, sizeof(entry->radix), NULL);
210                         SQLGetData(stmt, 11, SQL_C_SHORT, &entry->nullable, sizeof(entry->nullable), NULL);
211                         SQLGetData(stmt, 16, SQL_C_LONG, &entry->octetlen, sizeof(entry->octetlen), NULL);
212
213                         /* Specification states that the octenlen should be the maximum number of bytes
214                          * returned in a char or binary column, but it seems that some drivers just set
215                          * it to NULL. (Bad Postgres! No biscuit!) */
216                         if (entry->octetlen == 0) {
217                                 entry->octetlen = entry->size;
218                         }
219
220                         ast_verb(10, "Found %s column with type %hd with len %ld, octetlen %ld, and numlen (%hd,%hd)\n", entry->name, entry->type, (long) entry->size, (long) entry->octetlen, entry->decimals, entry->radix);
221                         /* Insert column info into column list */
222                         AST_LIST_INSERT_TAIL(&(tableptr->columns), entry, list);
223                 }
224                 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
225
226                 AST_RWLIST_INSERT_TAIL(&odbc_tables, tableptr, list);
227                 AST_RWLIST_RDLOCK(&(tableptr->columns));
228         } while (0);
229
230         AST_RWLIST_UNLOCK(&odbc_tables);
231
232         if (error) {
233                 destroy_table_cache(tableptr);
234                 tableptr = NULL;
235         }
236         if (obj) {
237                 ast_odbc_release_obj(obj);
238         }
239         return tableptr;
240 }
241
242 struct odbc_cache_columns *ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
243 {
244         struct odbc_cache_columns *col;
245         AST_RWLIST_TRAVERSE(&table->columns, col, list) {
246                 if (strcasecmp(col->name, colname) == 0) {
247                         return col;
248                 }
249         }
250         return NULL;
251 }
252
253 int ast_odbc_clear_cache(const char *database, const char *tablename)
254 {
255         struct odbc_cache_tables *tableptr;
256
257         AST_RWLIST_WRLOCK(&odbc_tables);
258         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&odbc_tables, tableptr, list) {
259                 if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
260                         AST_LIST_REMOVE_CURRENT(list);
261                         destroy_table_cache(tableptr);
262                         break;
263                 }
264         }
265         AST_RWLIST_TRAVERSE_SAFE_END
266         AST_RWLIST_UNLOCK(&odbc_tables);
267         return tableptr ? 0 : -1;
268 }
269
270 SQLHSTMT ast_odbc_direct_execute(struct odbc_obj *obj, SQLHSTMT (*exec_cb)(struct odbc_obj *obj, void *data), void *data)
271 {
272         int attempt;
273         SQLHSTMT stmt;
274
275         for (attempt = 0; attempt < 2; attempt++) {
276                 stmt = exec_cb(obj, data);
277
278                 if (stmt) {
279                         break;
280                 } else {
281                         obj->up = 0;
282                         ast_log(LOG_WARNING, "SQL Exec Direct failed.  Attempting a reconnect...\n");
283
284                         odbc_obj_disconnect(obj);
285                         odbc_obj_connect(obj);
286                 }
287         }
288
289         return stmt;
290 }
291
292 SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
293 {
294         int res = 0, i, attempt;
295         SQLINTEGER nativeerror=0, numfields=0;
296         SQLSMALLINT diagbytes=0;
297         unsigned char state[10], diagnostic[256];
298         SQLHSTMT stmt;
299
300         for (attempt = 0; attempt < 2; attempt++) {
301                 /* This prepare callback may do more than just prepare -- it may also
302                  * bind parameters, bind results, etc.  The real key, here, is that
303                  * when we disconnect, all handles become invalid for most databases.
304                  * We must therefore redo everything when we establish a new
305                  * connection. */
306                 stmt = prepare_cb(obj, data);
307
308                 if (stmt) {
309                         res = SQLExecute(stmt);
310                         if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
311                                 if (res == SQL_ERROR) {
312                                         SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
313                                         for (i = 0; i < numfields; i++) {
314                                                 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
315                                                 ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
316                                                 if (i > 10) {
317                                                         ast_log(LOG_WARNING, "Oh, that was good.  There are really %d diagnostics?\n", (int)numfields);
318                                                         break;
319                                                 }
320                                         }
321                                 }
322
323                                 ast_log(LOG_WARNING, "SQL Execute error %d! Attempting a reconnect...\n", res);
324                                 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
325                                 stmt = NULL;
326
327                                 obj->up = 0;
328                                 /*
329                                  * While this isn't the best way to try to correct an error, this won't automatically
330                                  * fail when the statement handle invalidates.
331                                  */
332                                 ast_odbc_sanity_check(obj);
333                                 continue;
334                         } else
335                                 obj->last_used = ast_tvnow();
336                         break;
337                 } else if (attempt == 0)
338                         ast_odbc_sanity_check(obj);
339         }
340
341         return stmt;
342 }
343
344 int ast_odbc_smart_execute(struct odbc_obj *obj, SQLHSTMT stmt) 
345 {
346         int res = 0, i;
347         SQLINTEGER nativeerror=0, numfields=0;
348         SQLSMALLINT diagbytes=0;
349         unsigned char state[10], diagnostic[256];
350
351         res = SQLExecute(stmt);
352         if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
353                 if (res == SQL_ERROR) {
354                         SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
355                         for (i = 0; i < numfields; i++) {
356                                 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
357                                 ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes);
358                                 if (i > 10) {
359                                         ast_log(LOG_WARNING, "Oh, that was good.  There are really %d diagnostics?\n", (int)numfields);
360                                         break;
361                                 }
362                         }
363                 }
364         } else
365                 obj->last_used = ast_tvnow();
366         
367         return res;
368 }
369
370 SQLRETURN ast_odbc_ast_str_SQLGetData(struct ast_str **buf, int pmaxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind)
371 {
372         SQLRETURN res;
373
374         if (pmaxlen == 0) {
375                 if (SQLGetData(StatementHandle, ColumnNumber, TargetType, ast_str_buffer(*buf), 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
376                         ast_str_make_space(buf, *StrLen_or_Ind + 1);
377                 }
378         } else if (pmaxlen > 0) {
379                 ast_str_make_space(buf, pmaxlen);
380         }
381         res = SQLGetData(StatementHandle, ColumnNumber, TargetType, ast_str_buffer(*buf), ast_str_size(*buf), StrLen_or_Ind);
382         ast_str_update(*buf);
383
384         return res;
385 }
386
387 int ast_odbc_sanity_check(struct odbc_obj *obj) 
388 {
389         char *test_sql = "select 1";
390         SQLHSTMT stmt;
391         int res = 0;
392
393         if (!ast_strlen_zero(obj->parent->sanitysql))
394                 test_sql = obj->parent->sanitysql;
395
396         if (obj->up) {
397                 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
398                 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
399                         obj->up = 0;
400                 } else {
401                         res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS);
402                         if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
403                                 obj->up = 0;
404                         } else {
405                                 res = SQLExecute(stmt);
406                                 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
407                                         obj->up = 0;
408                                 }
409                         }
410                 }
411                 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
412         }
413
414         if (!obj->up) { /* Try to reconnect! */
415                 ast_log(LOG_WARNING, "Connection is down attempting to reconnect...\n");
416                 odbc_obj_disconnect(obj);
417                 odbc_obj_connect(obj);
418         }
419         return obj->up;
420 }
421
422 static int load_odbc_config(void)
423 {
424         static char *cfg = "res_odbc.conf";
425         struct ast_config *config;
426         struct ast_variable *v;
427         char *cat;
428         const char *dsn, *username, *password, *sanitysql;
429         int enabled, pooling, limit, bse;
430         unsigned int idlecheck;
431         int preconnect = 0, res = 0;
432         struct ast_flags config_flags = { 0 };
433
434         struct odbc_class *new;
435
436         config = ast_config_load(cfg, config_flags);
437         if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
438                 ast_log(LOG_WARNING, "Unable to load config file res_odbc.conf\n");
439                 return -1;
440         }
441         for (cat = ast_category_browse(config, NULL); cat; cat=ast_category_browse(config, cat)) {
442                 if (!strcasecmp(cat, "ENV")) {
443                         for (v = ast_variable_browse(config, cat); v; v = v->next) {
444                                 setenv(v->name, v->value, 1);
445                                 ast_log(LOG_NOTICE, "Adding ENV var: %s=%s\n", v->name, v->value);
446                         }
447                 } else {
448                         /* Reset all to defaults for each class of odbc connections */
449                         dsn = username = password = sanitysql = NULL;
450                         enabled = 1;
451                         preconnect = idlecheck = 0;
452                         pooling = 0;
453                         limit = 0;
454                         bse = 1;
455                         for (v = ast_variable_browse(config, cat); v; v = v->next) {
456                                 if (!strcasecmp(v->name, "pooling")) {
457                                         if (ast_true(v->value))
458                                                 pooling = 1;
459                                 } else if (!strncasecmp(v->name, "share", 5)) {
460                                         /* "shareconnections" is a little clearer in meaning than "pooling" */
461                                         if (ast_false(v->value))
462                                                 pooling = 1;
463                                 } else if (!strcasecmp(v->name, "limit")) {
464                                         sscanf(v->value, "%d", &limit);
465                                         if (ast_true(v->value) && !limit) {
466                                                 ast_log(LOG_WARNING, "Limit should be a number, not a boolean: '%s'.  Setting limit to 1023 for ODBC class '%s'.\n", v->value, cat);
467                                                 limit = 1023;
468                                         } else if (ast_false(v->value)) {
469                                                 ast_log(LOG_WARNING, "Limit should be a number, not a boolean: '%s'.  Disabling ODBC class '%s'.\n", v->value, cat);
470                                                 enabled = 0;
471                                                 break;
472                                         }
473                                 } else if (!strcasecmp(v->name, "idlecheck")) {
474                                         sscanf(v->value, "%d", &idlecheck);
475                                 } else if (!strcasecmp(v->name, "enabled")) {
476                                         enabled = ast_true(v->value);
477                                 } else if (!strcasecmp(v->name, "pre-connect")) {
478                                         preconnect = ast_true(v->value);
479                                 } else if (!strcasecmp(v->name, "dsn")) {
480                                         dsn = v->value;
481                                 } else if (!strcasecmp(v->name, "username")) {
482                                         username = v->value;
483                                 } else if (!strcasecmp(v->name, "password")) {
484                                         password = v->value;
485                                 } else if (!strcasecmp(v->name, "sanitysql")) {
486                                         sanitysql = v->value;
487                                 } else if (!strcasecmp(v->name, "backslash_is_escape")) {
488                                         bse = ast_true(v->value);
489                                 }
490                         }
491
492                         if (enabled && !ast_strlen_zero(dsn)) {
493                                 new = ao2_alloc(sizeof(*new), odbc_class_destructor);
494
495                                 if (!new) {
496                                         res = -1;
497                                         break;
498                                 }
499
500                                 SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env);
501                                 res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
502
503                                 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
504                                         ast_log(LOG_WARNING, "res_odbc: Error SetEnv\n");
505                                         ao2_ref(new, -1);
506                                         return res;
507                                 }
508
509                                 new->obj_container = ao2_container_alloc(1, null_hash_fn, ao2_match_by_addr);
510
511                                 if (pooling) {
512                                         new->haspool = pooling;
513                                         if (limit) {
514                                                 new->limit = limit;
515                                         } else {
516                                                 ast_log(LOG_WARNING, "Pooling without also setting a limit is pointless.  Changing limit from 0 to 5.\n");
517                                                 new->limit = 5;
518                                         }
519                                 }
520
521                                 new->backslash_is_escape = bse ? 1 : 0;
522                                 new->idlecheck = idlecheck;
523
524                                 if (cat)
525                                         ast_copy_string(new->name, cat, sizeof(new->name));
526                                 if (dsn)
527                                         ast_copy_string(new->dsn, dsn, sizeof(new->dsn));
528                                 if (username && !(new->username = ast_strdup(username))) {
529                                         ao2_ref(new, -1);
530                                         break;
531                                 }
532                                 if (password && !(new->password = ast_strdup(password))) {
533                                         ao2_ref(new, -1);
534                                         break;
535                                 }
536                                 if (sanitysql && !(new->sanitysql = ast_strdup(sanitysql))) {
537                                         ao2_ref(new, -1);
538                                         break;
539                                 }
540
541                                 odbc_register_class(new, preconnect);
542                                 ast_log(LOG_NOTICE, "Registered ODBC class '%s' dsn->[%s]\n", cat, dsn);
543                                 ao2_ref(new, -1);
544                                 new = NULL;
545                         }
546                 }
547         }
548         ast_config_destroy(config);
549         return res;
550 }
551
552 static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
553 {
554         struct ao2_iterator aoi = ao2_iterator_init(class_container, 0);
555         struct odbc_class *class;
556         struct odbc_obj *current;
557         int length = 0;
558         int which = 0;
559         char *ret = NULL;
560
561         switch (cmd) {
562         case CLI_INIT:
563                 e->command = "odbc show";
564                 e->usage =
565                                 "Usage: odbc show [class]\n"
566                                 "       List settings of a particular ODBC class or,\n"
567                                 "       if not specified, all classes.\n";
568                 return NULL;
569         case CLI_GENERATE:
570                 if (a->pos != 2)
571                         return NULL;
572                 length = strlen(a->word);
573                 while ((class = ao2_iterator_next(&aoi))) {
574                         if (!strncasecmp(a->word, class->name, length) && ++which > a->n) {
575                                 ret = ast_strdup(class->name);
576                                 ao2_ref(class, -1);
577                                 break;
578                         }
579                         ao2_ref(class, -1);
580                 }
581                 if (!ret && !strncasecmp(a->word, "all", length) && ++which > a->n) {
582                         ret = ast_strdup("all");
583                 }
584                 return ret;
585         }
586
587         ast_cli(a->fd, "\nODBC DSN Settings\n");
588         ast_cli(a->fd,   "-----------------\n\n");
589         aoi = ao2_iterator_init(class_container, 0);
590         while ((class = ao2_iterator_next(&aoi))) {
591                 if ((a->argc == 2) || (a->argc == 3 && !strcmp(a->argv[2], "all")) || (!strcmp(a->argv[2], class->name))) {
592                         int count = 0;
593                         ast_cli(a->fd, "  Name:   %s\n  DSN:    %s\n", class->name, class->dsn);
594
595                         if (class->haspool) {
596                                 struct ao2_iterator aoi2 = ao2_iterator_init(class->obj_container, 0);
597
598                                 ast_cli(a->fd, "  Pooled: Yes\n  Limit:  %d\n  Connections in use: %d\n", class->limit, class->count);
599
600                                 while ((current = ao2_iterator_next(&aoi2))) {
601                                         ast_mutex_lock(&current->lock);
602 #ifdef DEBUG_THREADS
603                                         ast_cli(a->fd, "    - Connection %d: %s (%s:%d %s)\n", ++count,
604                                                 current->used ? "in use" :
605                                                 current->up && ast_odbc_sanity_check(current) ? "connected" : "disconnected",
606                                                 current->file, current->lineno, current->function);
607 #else
608                                         ast_cli(a->fd, "    - Connection %d: %s\n", ++count,
609                                                 current->used ? "in use" :
610                                                 current->up && ast_odbc_sanity_check(current) ? "connected" : "disconnected");
611 #endif
612                                         ast_mutex_unlock(&current->lock);
613                                         ao2_ref(current, -1);
614                                 }
615                         } else {
616                                 /* Should only ever be one of these */
617                                 struct ao2_iterator aoi2 = ao2_iterator_init(class->obj_container, 0);
618                                 while ((current = ao2_iterator_next(&aoi2))) {
619                                         ast_cli(a->fd, "  Pooled: No\n  Connected: %s\n", current->up && ast_odbc_sanity_check(current) ? "Yes" : "No");
620                                         ao2_ref(current, -1);
621                                 }
622                         }
623                         ast_cli(a->fd, "\n");
624                 }
625                 ao2_ref(class, -1);
626         }
627
628         return CLI_SUCCESS;
629 }
630
631 static struct ast_cli_entry cli_odbc[] = {
632         AST_CLI_DEFINE(handle_cli_odbc_show, "List ODBC DSN(s)")
633 };
634
635 static int odbc_register_class(struct odbc_class *class, int preconnect)
636 {
637         struct odbc_obj *obj;
638         if (class) {
639                 ao2_link(class_container, class);
640                 /* I still have a reference in the caller, so a deref is NOT missing here. */
641
642                 if (preconnect) {
643                         /* Request and release builds a connection */
644                         obj = ast_odbc_request_obj(class->name, 0);
645                         if (obj)
646                                 ast_odbc_release_obj(obj);
647                 }
648
649                 return 0;
650         } else {
651                 ast_log(LOG_WARNING, "Attempted to register a NULL class?\n");
652                 return -1;
653         }
654 }
655
656 void ast_odbc_release_obj(struct odbc_obj *obj)
657 {
658         /* For pooled connections, this frees the connection to be
659          * reused.  For non-pooled connections, it does nothing. */
660         obj->used = 0;
661 #ifdef DEBUG_THREADS
662         obj->file[0] = '\0';
663         obj->function[0] = '\0';
664         obj->lineno = 0;
665 #endif
666         ao2_ref(obj, -1);
667 }
668
669 int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
670 {
671         return obj->parent->backslash_is_escape;
672 }
673
674 #ifdef DEBUG_THREADS
675 struct odbc_obj *_ast_odbc_request_obj(const char *name, int check, const char *file, const char *function, int lineno)
676 #else
677 struct odbc_obj *ast_odbc_request_obj(const char *name, int check)
678 #endif
679 {
680         struct odbc_obj *obj = NULL;
681         struct odbc_class *class;
682         struct ao2_iterator aoi = ao2_iterator_init(class_container, 0);
683
684         while ((class = ao2_iterator_next(&aoi))) {
685                 if (!strcmp(class->name, name) && !class->delme) {
686                         break;
687                 }
688                 ao2_ref(class, -1);
689         }
690
691         if (!class)
692                 return NULL;
693
694         if (class->haspool) {
695                 /* Recycle connections before building another */
696                 aoi = ao2_iterator_init(class->obj_container, 0);
697                 while ((obj = ao2_iterator_next(&aoi))) {
698                         if (! obj->used) {
699                                 ast_mutex_lock(&obj->lock);
700                                 obj->used = 1;
701                                 ast_mutex_unlock(&obj->lock);
702                                 break;
703                         }
704                         ao2_ref(obj, -1);
705                 }
706
707                 if (!obj && (class->count < class->limit)) {
708                         class->count++;
709                         obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
710                         if (!obj) {
711                                 ao2_ref(class, -1);
712                                 return NULL;
713                         }
714                         ast_mutex_init(&obj->lock);
715                         /* obj inherits the outstanding reference to class */
716                         obj->parent = class;
717                         if (odbc_obj_connect(obj) == ODBC_FAIL) {
718                                 ast_log(LOG_WARNING, "Failed to connect to %s\n", name);
719                                 ao2_ref(obj, -1);
720                                 obj = NULL;
721                         } else {
722                                 obj->used = 1;
723                                 ao2_link(class->obj_container, obj);
724                         }
725                         class = NULL;
726                 } else {
727                         /* Object is not constructed, so delete outstanding reference to class. */
728                         ao2_ref(class, -1);
729                         class = NULL;
730                 }
731         } else {
732                 /* Non-pooled connection: multiple modules can use the same connection. */
733                 aoi = ao2_iterator_init(class->obj_container, 0);
734                 while ((obj = ao2_iterator_next(&aoi))) {
735                         /* Non-pooled connection: if there is an entry, return it */
736                         break;
737                 }
738
739                 if (obj) {
740                         /* Object is not constructed, so delete outstanding reference to class. */
741                         ao2_ref(class, -1);
742                         class = NULL;
743                 } else {
744                         /* No entry: build one */
745                         obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
746                         if (!obj) {
747                                 ao2_ref(class, -1);
748                                 return NULL;
749                         }
750                         ast_mutex_init(&obj->lock);
751                         /* obj inherits the outstanding reference to class */
752                         obj->parent = class;
753                         if (odbc_obj_connect(obj) == ODBC_FAIL) {
754                                 ast_log(LOG_WARNING, "Failed to connect to %s\n", name);
755                                 ao2_ref(obj, -1);
756                                 obj = NULL;
757                         } else {
758                                 ao2_link(class->obj_container, obj);
759                         }
760                         class = NULL;
761                 }
762         }
763
764         if (obj && check) {
765                 ast_odbc_sanity_check(obj);
766         } else if (obj && obj->parent->idlecheck > 0 && ast_tvdiff_sec(ast_tvnow(), obj->last_used) > obj->parent->idlecheck)
767                 odbc_obj_connect(obj);
768
769 #ifdef DEBUG_THREADS
770         if (obj) {
771                 ast_copy_string(obj->file, file, sizeof(obj->file));
772                 ast_copy_string(obj->function, function, sizeof(obj->function));
773                 obj->lineno = lineno;
774         }
775 #endif
776         ast_assert(class == NULL);
777
778         return obj;
779 }
780
781 static odbc_status odbc_obj_disconnect(struct odbc_obj *obj)
782 {
783         int res;
784         SQLINTEGER err;
785         short int mlen;
786         unsigned char msg[200], state[10];
787
788         /* Nothing to disconnect */
789         if (!obj->con) {
790                 return ODBC_SUCCESS;
791         }
792
793         ast_mutex_lock(&obj->lock);
794
795         res = SQLDisconnect(obj->con);
796
797         if (res == SQL_SUCCESS || res == SQL_SUCCESS_WITH_INFO) {
798                 ast_log(LOG_DEBUG, "Disconnected %d from %s [%s]\n", res, obj->parent->name, obj->parent->dsn);
799         } else {
800                 ast_log(LOG_DEBUG, "res_odbc: %s [%s] already disconnected\n", obj->parent->name, obj->parent->dsn);
801         }
802
803         if ((res = SQLFreeHandle(SQL_HANDLE_DBC, obj->con) == SQL_SUCCESS)) {
804                 obj->con = NULL;
805                 ast_log(LOG_DEBUG, "Database handle deallocated\n");
806         } else {
807                 SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, 1, state, &err, msg, 100, &mlen);
808                 ast_log(LOG_WARNING, "Unable to deallocate database handle? %d errno=%d %s\n", res, (int)err, msg);
809         }
810
811         obj->up = 0;
812         ast_mutex_unlock(&obj->lock);
813         return ODBC_SUCCESS;
814 }
815
816 static odbc_status odbc_obj_connect(struct odbc_obj *obj)
817 {
818         int res;
819         SQLINTEGER err;
820         short int mlen;
821         unsigned char msg[200], state[10];
822 #ifdef NEEDTRACE
823         SQLINTEGER enable = 1;
824         char *tracefile = "/tmp/odbc.trace";
825 #endif
826         ast_mutex_lock(&obj->lock);
827
828         if (obj->up) {
829                 odbc_obj_disconnect(obj);
830                 ast_log(LOG_NOTICE, "Re-connecting %s\n", obj->parent->name);
831         } else {
832                 ast_log(LOG_NOTICE, "Connecting %s\n", obj->parent->name);
833         }
834
835         res = SQLAllocHandle(SQL_HANDLE_DBC, obj->parent->env, &obj->con);
836
837         if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
838                 ast_log(LOG_WARNING, "res_odbc: Error AllocHDB %d\n", res);
839                 ast_mutex_unlock(&obj->lock);
840                 return ODBC_FAIL;
841         }
842         SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
843         SQLSetConnectAttr(obj->con, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER *) 10, 0);
844 #ifdef NEEDTRACE
845         SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
846         SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
847 #endif
848
849         res = SQLConnect(obj->con,
850                    (SQLCHAR *) obj->parent->dsn, SQL_NTS,
851                    (SQLCHAR *) obj->parent->username, SQL_NTS,
852                    (SQLCHAR *) obj->parent->password, SQL_NTS);
853
854         if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
855                 SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, 1, state, &err, msg, 100, &mlen);
856                 ast_mutex_unlock(&obj->lock);
857                 ast_log(LOG_WARNING, "res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (int)err, msg);
858                 return ODBC_FAIL;
859         } else {
860                 ast_log(LOG_NOTICE, "res_odbc: Connected to %s [%s]\n", obj->parent->name, obj->parent->dsn);
861                 obj->up = 1;
862                 obj->last_used = ast_tvnow();
863         }
864
865         ast_mutex_unlock(&obj->lock);
866         return ODBC_SUCCESS;
867 }
868
869 static int reload(void)
870 {
871         struct odbc_cache_tables *table;
872         struct odbc_class *class;
873         struct odbc_obj *current;
874         struct ao2_iterator aoi = ao2_iterator_init(class_container, 0);
875
876         /* First, mark all to be purged */
877         while ((class = ao2_iterator_next(&aoi))) {
878                 class->delme = 1;
879                 ao2_ref(class, -1);
880         }
881
882         load_odbc_config();
883
884         /* Purge remaining classes */
885
886         /* Note on how this works; this is a case of circular references, so we
887          * explicitly do NOT want to use a callback here (or we wind up in
888          * recursive hell).
889          *
890          * 1. Iterate through all the classes.  Note that the classes will currently
891          * contain two classes of the same name, one of which is marked delme and
892          * will be purged when all remaining objects of the class are released, and
893          * the other, which was created above when we re-parsed the config file.
894          * 2. On each class, there is a reference held by the master container and
895          * a reference held by each connection object.  There are two cases for
896          * destruction of the class, noted below.  However, in all cases, all O-refs
897          * (references to objects) will first be freed, which will cause the C-refs
898          * (references to classes) to be decremented (but never to 0, because the
899          * class container still has a reference).
900          *    a) If the class has outstanding objects, the C-ref by the class
901          *    container will then be freed, which leaves only C-refs by any
902          *    outstanding objects.  When the final outstanding object is released
903          *    (O-refs held by applications and dialplan functions), it will in turn
904          *    free the final C-ref, causing class destruction.
905          *    b) If the class has no outstanding objects, when the class container
906          *    removes the final C-ref, the class will be destroyed.
907          */
908         aoi = ao2_iterator_init(class_container, 0);
909         while ((class = ao2_iterator_next(&aoi))) { /* C-ref++ (by iterator) */
910                 if (class->delme) {
911                         struct ao2_iterator aoi2 = ao2_iterator_init(class->obj_container, 0);
912                         while ((current = ao2_iterator_next(&aoi2))) { /* O-ref++ (by iterator) */
913                                 ao2_unlink(class->obj_container, current); /* unlink O-ref from class (reference handled implicitly) */
914                                 ao2_ref(current, -1); /* O-ref-- (by iterator) */
915                                 /* At this point, either
916                                  * a) there's an outstanding O-ref, or
917                                  * b) the object has already been destroyed.
918                                  */
919                         }
920                         ao2_unlink(class_container, class); /* unlink C-ref from container (reference handled implicitly) */
921                         /* At this point, either
922                          * a) there's an outstanding O-ref, which holds an outstanding C-ref, or
923                          * b) the last remaining C-ref is held by the iterator, which will be
924                          * destroyed in the next step.
925                          */
926                 }
927                 ao2_ref(class, -1); /* C-ref-- (by iterator) */
928         }
929
930         /* Empty the cache; it will get rebuilt the next time the tables are needed. */
931         AST_RWLIST_WRLOCK(&odbc_tables);
932         while ((table = AST_RWLIST_REMOVE_HEAD(&odbc_tables, list))) {
933                 destroy_table_cache(table);
934         }
935         AST_RWLIST_UNLOCK(&odbc_tables);
936
937         return 0;
938 }
939
940 static int unload_module(void)
941 {
942         /* Prohibit unloading */
943         return -1;
944 }
945
946 static int load_module(void)
947 {
948         if (!(class_container = ao2_container_alloc(1, null_hash_fn, ao2_match_by_addr)))
949                 return AST_MODULE_LOAD_DECLINE;
950         if (load_odbc_config() == -1)
951                 return AST_MODULE_LOAD_DECLINE;
952         ast_cli_register_multiple(cli_odbc, ARRAY_LEN(cli_odbc));
953         ast_log(LOG_NOTICE, "res_odbc loaded.\n");
954         return 0;
955 }
956
957 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "ODBC resource",
958                 .load = load_module,
959                 .unload = unload_module,
960                 .reload = reload,
961                );