res_odbc.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2012, 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. /*! \file
  22. *
  23. * \brief ODBC resource manager
  24. *
  25. * \author Mark Spencer <markster@digium.com>
  26. * \author Anthony Minessale II <anthmct@yahoo.com>
  27. * \author Tilghman Lesher <tilghman@digium.com>
  28. *
  29. * \arg See also: \ref cdr_odbc.c
  30. */
  31. /*! \li \ref res_odbc.c uses the configuration file \ref res_odbc.conf
  32. * \addtogroup configuration_file Configuration Files
  33. */
  34. /*!
  35. * \page res_odbc.conf res_odbc.conf
  36. * \verbinclude res_odbc.conf.sample
  37. */
  38. /*** MODULEINFO
  39. <depend>generic_odbc</depend>
  40. <depend>res_odbc_transaction</depend>
  41. <support_level>core</support_level>
  42. ***/
  43. #include "asterisk.h"
  44. #include "asterisk/file.h"
  45. #include "asterisk/channel.h"
  46. #include "asterisk/config.h"
  47. #include "asterisk/pbx.h"
  48. #include "asterisk/module.h"
  49. #include "asterisk/cli.h"
  50. #include "asterisk/lock.h"
  51. #include "asterisk/res_odbc.h"
  52. #include "asterisk/time.h"
  53. #include "asterisk/astobj2.h"
  54. #include "asterisk/app.h"
  55. #include "asterisk/strings.h"
  56. #include "asterisk/threadstorage.h"
  57. struct odbc_class
  58. {
  59. AST_LIST_ENTRY(odbc_class) list;
  60. char name[80];
  61. char dsn[80];
  62. char *username;
  63. char *password;
  64. char *sanitysql;
  65. SQLHENV env;
  66. unsigned int delme:1; /*!< Purge the class */
  67. unsigned int backslash_is_escape:1; /*!< On this database, the backslash is a native escape sequence */
  68. unsigned int forcecommit:1; /*!< Should uncommitted transactions be auto-committed on handle release? */
  69. unsigned int isolation; /*!< Flags for how the DB should deal with data in other, uncommitted transactions */
  70. unsigned int conntimeout; /*!< Maximum time the connection process should take */
  71. unsigned int maxconnections; /*!< Maximum number of allowed connections */
  72. /*! When a connection fails, cache that failure for how long? */
  73. struct timeval negative_connection_cache;
  74. /*! When a connection fails, when did that last occur? */
  75. struct timeval last_negative_connect;
  76. /*! A pool of available connections */
  77. AST_LIST_HEAD_NOLOCK(, odbc_obj) connections;
  78. /*! Lock to protect the connections */
  79. ast_mutex_t lock;
  80. /*! Condition to notify any pending connection requesters */
  81. ast_cond_t cond;
  82. /*! The total number of current connections */
  83. size_t connection_cnt;
  84. /*! Whether logging is enabled on this class or not */
  85. unsigned int logging;
  86. /*! The number of prepares executed on this class (total from all connections */
  87. int prepares_executed;
  88. /*! The number of queries executed on this class (total from all connections) */
  89. int queries_executed;
  90. /*! The longest execution time for a query executed on this class */
  91. long longest_query_execution_time;
  92. /*! The SQL query that took the longest to execute */
  93. char *sql_text;
  94. /*! Slow query limit (in milliseconds) */
  95. unsigned int slowquerylimit;
  96. };
  97. static struct ao2_container *class_container;
  98. static AST_RWLIST_HEAD_STATIC(odbc_tables, odbc_cache_tables);
  99. static odbc_status odbc_obj_connect(struct odbc_obj *obj);
  100. static odbc_status odbc_obj_disconnect(struct odbc_obj *obj);
  101. static void odbc_register_class(struct odbc_class *class, int connect);
  102. AST_THREADSTORAGE(errors_buf);
  103. struct odbc_txn_frame {
  104. AST_LIST_ENTRY(odbc_txn_frame) list;
  105. struct ast_channel *owner;
  106. struct odbc_obj *obj; /*!< Database handle within which transacted statements are run */
  107. /*!\brief Is this record the current active transaction within the channel?
  108. * Note that the active flag is really only necessary for statements which
  109. * are triggered from the dialplan, as there isn't a direct correlation
  110. * between multiple statements. Applications wishing to use transactions
  111. * may simply perform each statement on the same odbc_obj, which keeps the
  112. * transaction persistent.
  113. */
  114. unsigned int active:1;
  115. unsigned int forcecommit:1; /*!< Should uncommitted transactions be auto-committed on handle release? */
  116. unsigned int isolation; /*!< Flags for how the DB should deal with data in other, uncommitted transactions */
  117. char name[0]; /*!< Name of this transaction ID */
  118. };
  119. const char *ast_odbc_isolation2text(int iso)
  120. {
  121. if (iso == SQL_TXN_READ_COMMITTED) {
  122. return "read_committed";
  123. } else if (iso == SQL_TXN_READ_UNCOMMITTED) {
  124. return "read_uncommitted";
  125. } else if (iso == SQL_TXN_SERIALIZABLE) {
  126. return "serializable";
  127. } else if (iso == SQL_TXN_REPEATABLE_READ) {
  128. return "repeatable_read";
  129. } else {
  130. return "unknown";
  131. }
  132. }
  133. int ast_odbc_text2isolation(const char *txt)
  134. {
  135. if (strncasecmp(txt, "read_", 5) == 0) {
  136. if (strncasecmp(txt + 5, "c", 1) == 0) {
  137. return SQL_TXN_READ_COMMITTED;
  138. } else if (strncasecmp(txt + 5, "u", 1) == 0) {
  139. return SQL_TXN_READ_UNCOMMITTED;
  140. } else {
  141. return 0;
  142. }
  143. } else if (strncasecmp(txt, "ser", 3) == 0) {
  144. return SQL_TXN_SERIALIZABLE;
  145. } else if (strncasecmp(txt, "rep", 3) == 0) {
  146. return SQL_TXN_REPEATABLE_READ;
  147. } else {
  148. return 0;
  149. }
  150. }
  151. static void odbc_class_destructor(void *data)
  152. {
  153. struct odbc_class *class = data;
  154. struct odbc_obj *obj;
  155. /* Due to refcounts, we can safely assume that any objects with a reference
  156. * to us will prevent our destruction, so we don't need to worry about them.
  157. */
  158. if (class->username) {
  159. ast_free(class->username);
  160. }
  161. if (class->password) {
  162. ast_free(class->password);
  163. }
  164. if (class->sanitysql) {
  165. ast_free(class->sanitysql);
  166. }
  167. while ((obj = AST_LIST_REMOVE_HEAD(&class->connections, list))) {
  168. ao2_ref(obj, -1);
  169. }
  170. SQLFreeHandle(SQL_HANDLE_ENV, class->env);
  171. ast_mutex_destroy(&class->lock);
  172. ast_cond_destroy(&class->cond);
  173. ast_free(class->sql_text);
  174. }
  175. static void odbc_obj_destructor(void *data)
  176. {
  177. struct odbc_obj *obj = data;
  178. odbc_obj_disconnect(obj);
  179. }
  180. static void destroy_table_cache(struct odbc_cache_tables *table)
  181. {
  182. struct odbc_cache_columns *col;
  183. ast_debug(1, "Destroying table cache for %s\n", table->table);
  184. AST_RWLIST_WRLOCK(&table->columns);
  185. while ((col = AST_RWLIST_REMOVE_HEAD(&table->columns, list))) {
  186. ast_free(col);
  187. }
  188. AST_RWLIST_UNLOCK(&table->columns);
  189. AST_RWLIST_HEAD_DESTROY(&table->columns);
  190. ast_free(table);
  191. }
  192. /*!
  193. * XXX This creates a connection and disconnects it. In some situations, the caller of
  194. * this function has its own connection and could donate it to this function instead of
  195. * needing to create another one.
  196. *
  197. * XXX The automatic readlock of the columns is awkward. It's done because it's possible for
  198. * multiple threads to have references to the table, and the table is not refcounted. Possible
  199. * changes here would be
  200. * * Eliminate the table cache entirely. The use of ast_odbc_find_table() is generally
  201. * questionable. The only real good use right now is from ast_realtime_require_field() in
  202. * order to make sure the DB has the expected columns in it. Since that is only used sparingly,
  203. * the need to cache tables is questionable. Instead, the table structure can be fetched from
  204. * the DB directly each time, resulting in a single owner of the data.
  205. * * Make odbc_cache_tables a refcounted object.
  206. */
  207. struct odbc_cache_tables *ast_odbc_find_table(const char *database, const char *tablename)
  208. {
  209. struct odbc_cache_tables *tableptr;
  210. struct odbc_cache_columns *entry;
  211. char columnname[80];
  212. SQLLEN sqlptr;
  213. SQLHSTMT stmt = NULL;
  214. int res = 0, error = 0;
  215. struct odbc_obj *obj;
  216. AST_RWLIST_RDLOCK(&odbc_tables);
  217. AST_RWLIST_TRAVERSE(&odbc_tables, tableptr, list) {
  218. if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
  219. break;
  220. }
  221. }
  222. if (tableptr) {
  223. AST_RWLIST_RDLOCK(&tableptr->columns);
  224. AST_RWLIST_UNLOCK(&odbc_tables);
  225. return tableptr;
  226. }
  227. if (!(obj = ast_odbc_request_obj(database, 0))) {
  228. ast_log(LOG_WARNING, "Unable to retrieve database handle for table description '%s@%s'\n", tablename, database);
  229. AST_RWLIST_UNLOCK(&odbc_tables);
  230. return NULL;
  231. }
  232. /* Table structure not already cached; build it now. */
  233. do {
  234. res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
  235. if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
  236. ast_log(LOG_WARNING, "SQL Alloc Handle failed on connection '%s'!\n", database);
  237. break;
  238. }
  239. res = SQLColumns(stmt, NULL, 0, NULL, 0, (unsigned char *)tablename, SQL_NTS, (unsigned char *)"%", SQL_NTS);
  240. if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
  241. SQLFreeHandle(SQL_HANDLE_STMT, stmt);
  242. ast_log(LOG_ERROR, "Unable to query database columns on connection '%s'.\n", database);
  243. break;
  244. }
  245. if (!(tableptr = ast_calloc(sizeof(char), sizeof(*tableptr) + strlen(database) + 1 + strlen(tablename) + 1))) {
  246. ast_log(LOG_ERROR, "Out of memory creating entry for table '%s' on connection '%s'\n", tablename, database);
  247. break;
  248. }
  249. tableptr->connection = (char *)tableptr + sizeof(*tableptr);
  250. tableptr->table = (char *)tableptr + sizeof(*tableptr) + strlen(database) + 1;
  251. strcpy(tableptr->connection, database); /* SAFE */
  252. strcpy(tableptr->table, tablename); /* SAFE */
  253. AST_RWLIST_HEAD_INIT(&(tableptr->columns));
  254. while ((res = SQLFetch(stmt)) != SQL_NO_DATA && res != SQL_ERROR) {
  255. SQLGetData(stmt, 4, SQL_C_CHAR, columnname, sizeof(columnname), &sqlptr);
  256. if (!(entry = ast_calloc(sizeof(char), sizeof(*entry) + strlen(columnname) + 1))) {
  257. ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s' on connection '%s'\n", columnname, tablename, database);
  258. error = 1;
  259. break;
  260. }
  261. entry->name = (char *)entry + sizeof(*entry);
  262. strcpy(entry->name, columnname);
  263. SQLGetData(stmt, 5, SQL_C_SHORT, &entry->type, sizeof(entry->type), NULL);
  264. SQLGetData(stmt, 7, SQL_C_LONG, &entry->size, sizeof(entry->size), NULL);
  265. SQLGetData(stmt, 9, SQL_C_SHORT, &entry->decimals, sizeof(entry->decimals), NULL);
  266. SQLGetData(stmt, 10, SQL_C_SHORT, &entry->radix, sizeof(entry->radix), NULL);
  267. SQLGetData(stmt, 11, SQL_C_SHORT, &entry->nullable, sizeof(entry->nullable), NULL);
  268. SQLGetData(stmt, 16, SQL_C_LONG, &entry->octetlen, sizeof(entry->octetlen), NULL);
  269. /* Specification states that the octenlen should be the maximum number of bytes
  270. * returned in a char or binary column, but it seems that some drivers just set
  271. * it to NULL. (Bad Postgres! No biscuit!) */
  272. if (entry->octetlen == 0) {
  273. entry->octetlen = entry->size;
  274. }
  275. ast_debug(3, "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);
  276. /* Insert column info into column list */
  277. AST_LIST_INSERT_TAIL(&(tableptr->columns), entry, list);
  278. }
  279. SQLFreeHandle(SQL_HANDLE_STMT, stmt);
  280. AST_RWLIST_INSERT_TAIL(&odbc_tables, tableptr, list);
  281. AST_RWLIST_RDLOCK(&(tableptr->columns));
  282. break;
  283. } while (1);
  284. AST_RWLIST_UNLOCK(&odbc_tables);
  285. if (error) {
  286. destroy_table_cache(tableptr);
  287. tableptr = NULL;
  288. }
  289. ast_odbc_release_obj(obj);
  290. return tableptr;
  291. }
  292. struct odbc_cache_columns *ast_odbc_find_column(struct odbc_cache_tables *table, const char *colname)
  293. {
  294. struct odbc_cache_columns *col;
  295. AST_RWLIST_TRAVERSE(&table->columns, col, list) {
  296. if (strcasecmp(col->name, colname) == 0) {
  297. return col;
  298. }
  299. }
  300. return NULL;
  301. }
  302. int ast_odbc_clear_cache(const char *database, const char *tablename)
  303. {
  304. struct odbc_cache_tables *tableptr;
  305. AST_RWLIST_WRLOCK(&odbc_tables);
  306. AST_RWLIST_TRAVERSE_SAFE_BEGIN(&odbc_tables, tableptr, list) {
  307. if (strcmp(tableptr->connection, database) == 0 && strcmp(tableptr->table, tablename) == 0) {
  308. AST_LIST_REMOVE_CURRENT(list);
  309. destroy_table_cache(tableptr);
  310. break;
  311. }
  312. }
  313. AST_RWLIST_TRAVERSE_SAFE_END
  314. AST_RWLIST_UNLOCK(&odbc_tables);
  315. return tableptr ? 0 : -1;
  316. }
  317. SQLHSTMT ast_odbc_direct_execute(struct odbc_obj *obj, SQLHSTMT (*exec_cb)(struct odbc_obj *obj, void *data), void *data)
  318. {
  319. struct timeval start;
  320. SQLHSTMT stmt;
  321. if (obj->parent->logging) {
  322. start = ast_tvnow();
  323. }
  324. stmt = exec_cb(obj, data);
  325. if (obj->parent->logging) {
  326. long execution_time = ast_tvdiff_ms(ast_tvnow(), start);
  327. if (obj->parent->slowquerylimit && execution_time > obj->parent->slowquerylimit) {
  328. ast_log(LOG_WARNING, "SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
  329. obj->sql_text, execution_time, obj->parent->name);
  330. }
  331. ast_mutex_lock(&obj->parent->lock);
  332. if (execution_time > obj->parent->longest_query_execution_time || !obj->parent->sql_text) {
  333. obj->parent->longest_query_execution_time = execution_time;
  334. /* Due to the callback nature of the res_odbc API it's not possible to ensure that
  335. * the SQL text is removed from the connection in all cases, so only if it becomes the
  336. * new longest executing query do we steal the SQL text. In other cases what will happen
  337. * is that the SQL text will be freed if the connection is released back to the class or
  338. * if a new query is done on the connection.
  339. */
  340. ast_free(obj->parent->sql_text);
  341. obj->parent->sql_text = obj->sql_text;
  342. obj->sql_text = NULL;
  343. }
  344. ast_mutex_unlock(&obj->parent->lock);
  345. }
  346. return stmt;
  347. }
  348. SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT (*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
  349. {
  350. struct timeval start;
  351. int res = 0;
  352. SQLHSTMT stmt;
  353. if (obj->parent->logging) {
  354. start = ast_tvnow();
  355. }
  356. /* This prepare callback may do more than just prepare -- it may also
  357. * bind parameters, bind results, etc. The real key, here, is that
  358. * when we disconnect, all handles become invalid for most databases.
  359. * We must therefore redo everything when we establish a new
  360. * connection. */
  361. stmt = prepare_cb(obj, data);
  362. if (!stmt) {
  363. return NULL;
  364. }
  365. res = SQLExecute(stmt);
  366. if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
  367. if (res == SQL_ERROR) {
  368. ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute");
  369. }
  370. ast_log(LOG_WARNING, "SQL Execute error %d!\n", res);
  371. SQLFreeHandle(SQL_HANDLE_STMT, stmt);
  372. stmt = NULL;
  373. } else if (obj->parent->logging) {
  374. long execution_time = ast_tvdiff_ms(ast_tvnow(), start);
  375. if (obj->parent->slowquerylimit && execution_time > obj->parent->slowquerylimit) {
  376. ast_log(LOG_WARNING, "SQL query '%s' took %ld milliseconds to execute on class '%s', this may indicate a database problem\n",
  377. obj->sql_text, execution_time, obj->parent->name);
  378. }
  379. ast_mutex_lock(&obj->parent->lock);
  380. /* If this takes the record on longest query execution time, update the parent class
  381. * with the information.
  382. */
  383. if (execution_time > obj->parent->longest_query_execution_time || !obj->parent->sql_text) {
  384. obj->parent->longest_query_execution_time = execution_time;
  385. ast_free(obj->parent->sql_text);
  386. obj->parent->sql_text = obj->sql_text;
  387. obj->sql_text = NULL;
  388. }
  389. ast_mutex_unlock(&obj->parent->lock);
  390. ast_atomic_fetchadd_int(&obj->parent->queries_executed, +1);
  391. }
  392. return stmt;
  393. }
  394. int ast_odbc_prepare(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
  395. {
  396. if (obj->parent->logging) {
  397. /* It is possible for this connection to be reused without being
  398. * released back to the class, so we free what may already exist
  399. * and place the new SQL in.
  400. */
  401. ast_free(obj->sql_text);
  402. obj->sql_text = ast_strdup(sql);
  403. ast_atomic_fetchadd_int(&obj->parent->prepares_executed, +1);
  404. }
  405. return SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
  406. }
  407. SQLRETURN ast_odbc_execute_sql(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
  408. {
  409. if (obj->parent->logging) {
  410. ast_free(obj->sql_text);
  411. obj->sql_text = ast_strdup(sql);
  412. ast_atomic_fetchadd_int(&obj->parent->queries_executed, +1);
  413. }
  414. return SQLExecDirect(stmt, (unsigned char *)sql, SQL_NTS);
  415. }
  416. int ast_odbc_smart_execute(struct odbc_obj *obj, SQLHSTMT stmt)
  417. {
  418. int res = 0;
  419. res = SQLExecute(stmt);
  420. if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
  421. if (res == SQL_ERROR) {
  422. ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute");
  423. }
  424. }
  425. if (obj->parent->logging) {
  426. ast_atomic_fetchadd_int(&obj->parent->queries_executed, +1);
  427. }
  428. return res;
  429. }
  430. SQLRETURN ast_odbc_ast_str_SQLGetData(struct ast_str **buf, int pmaxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind)
  431. {
  432. SQLRETURN res;
  433. if (pmaxlen == 0) {
  434. if (SQLGetData(StatementHandle, ColumnNumber, TargetType, ast_str_buffer(*buf), 0, StrLen_or_Ind) == SQL_SUCCESS_WITH_INFO) {
  435. ast_str_make_space(buf, *StrLen_or_Ind + 1);
  436. }
  437. } else if (pmaxlen > 0) {
  438. ast_str_make_space(buf, pmaxlen);
  439. }
  440. res = SQLGetData(StatementHandle, ColumnNumber, TargetType, ast_str_buffer(*buf), ast_str_size(*buf), StrLen_or_Ind);
  441. ast_str_update(*buf);
  442. return res;
  443. }
  444. struct ast_str *ast_odbc_print_errors(SQLSMALLINT handle_type, SQLHANDLE handle, const char *operation)
  445. {
  446. struct ast_str *errors = ast_str_thread_get(&errors_buf, 16);
  447. SQLINTEGER nativeerror = 0;
  448. SQLSMALLINT diagbytes = 0;
  449. SQLSMALLINT i;
  450. unsigned char state[10];
  451. unsigned char diagnostic[256];
  452. ast_str_reset(errors);
  453. i = 0;
  454. while (SQLGetDiagRec(handle_type, handle, ++i, state, &nativeerror,
  455. diagnostic, sizeof(diagnostic), &diagbytes) == SQL_SUCCESS) {
  456. ast_str_append(&errors, 0, "%s%s", ast_str_strlen(errors) ? "," : "", state);
  457. ast_log(LOG_WARNING, "%s returned an error: %s: %s\n", operation, state, diagnostic);
  458. /* XXX Why is this here? */
  459. if (i > 10) {
  460. ast_log(LOG_WARNING, "There are more than 10 diagnostic records! Ignore the rest.\n");
  461. break;
  462. }
  463. }
  464. return errors;
  465. }
  466. unsigned int ast_odbc_class_get_isolation(struct odbc_class *class)
  467. {
  468. return class->isolation;
  469. }
  470. unsigned int ast_odbc_class_get_forcecommit(struct odbc_class *class)
  471. {
  472. return class->forcecommit;
  473. }
  474. const char *ast_odbc_class_get_name(struct odbc_class *class)
  475. {
  476. return class->name;
  477. }
  478. static int load_odbc_config(void)
  479. {
  480. static char *cfg = "res_odbc.conf";
  481. struct ast_config *config;
  482. struct ast_variable *v;
  483. char *cat;
  484. const char *dsn, *username, *password, *sanitysql;
  485. int enabled, bse, conntimeout, forcecommit, isolation, maxconnections, logging, slowquerylimit;
  486. struct timeval ncache = { 0, 0 };
  487. int preconnect = 0, res = 0;
  488. struct ast_flags config_flags = { 0 };
  489. struct odbc_class *new;
  490. config = ast_config_load(cfg, config_flags);
  491. if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
  492. ast_log(LOG_WARNING, "Unable to load config file res_odbc.conf\n");
  493. return -1;
  494. }
  495. for (cat = ast_category_browse(config, NULL); cat; cat=ast_category_browse(config, cat)) {
  496. if (!strcasecmp(cat, "ENV")) {
  497. for (v = ast_variable_browse(config, cat); v; v = v->next) {
  498. setenv(v->name, v->value, 1);
  499. ast_log(LOG_NOTICE, "Adding ENV var: %s=%s\n", v->name, v->value);
  500. }
  501. } else {
  502. /* Reset all to defaults for each class of odbc connections */
  503. dsn = username = password = sanitysql = NULL;
  504. enabled = 1;
  505. preconnect = 0;
  506. bse = 1;
  507. conntimeout = 10;
  508. forcecommit = 0;
  509. isolation = SQL_TXN_READ_COMMITTED;
  510. maxconnections = 1;
  511. logging = 0;
  512. slowquerylimit = 5000;
  513. for (v = ast_variable_browse(config, cat); v; v = v->next) {
  514. if (!strcasecmp(v->name, "pooling") ||
  515. !strncasecmp(v->name, "share", 5) ||
  516. !strcasecmp(v->name, "limit") ||
  517. !strcasecmp(v->name, "idlecheck")) {
  518. ast_log(LOG_WARNING, "The 'pooling', 'shared_connections', 'limit', and 'idlecheck' options were replaced by 'max_connections'. See res_odbc.conf.sample.\n");
  519. } else if (!strcasecmp(v->name, "enabled")) {
  520. enabled = ast_true(v->value);
  521. } else if (!strcasecmp(v->name, "pre-connect")) {
  522. preconnect = ast_true(v->value);
  523. } else if (!strcasecmp(v->name, "dsn")) {
  524. dsn = v->value;
  525. } else if (!strcasecmp(v->name, "username")) {
  526. username = v->value;
  527. } else if (!strcasecmp(v->name, "password")) {
  528. password = v->value;
  529. } else if (!strcasecmp(v->name, "sanitysql")) {
  530. sanitysql = v->value;
  531. } else if (!strcasecmp(v->name, "backslash_is_escape")) {
  532. bse = ast_true(v->value);
  533. } else if (!strcasecmp(v->name, "connect_timeout")) {
  534. if (sscanf(v->value, "%d", &conntimeout) != 1 || conntimeout < 1) {
  535. ast_log(LOG_WARNING, "connect_timeout must be a positive integer\n");
  536. conntimeout = 10;
  537. }
  538. } else if (!strcasecmp(v->name, "negative_connection_cache")) {
  539. double dncache;
  540. if (sscanf(v->value, "%lf", &dncache) != 1 || dncache < 0) {
  541. ast_log(LOG_WARNING, "negative_connection_cache must be a non-negative integer\n");
  542. /* 5 minutes sounds like a reasonable default */
  543. ncache.tv_sec = 300;
  544. ncache.tv_usec = 0;
  545. } else {
  546. ncache.tv_sec = (int)dncache;
  547. ncache.tv_usec = (dncache - ncache.tv_sec) * 1000000;
  548. }
  549. } else if (!strcasecmp(v->name, "forcecommit")) {
  550. forcecommit = ast_true(v->value);
  551. } else if (!strcasecmp(v->name, "isolation")) {
  552. if ((isolation = ast_odbc_text2isolation(v->value)) == 0) {
  553. ast_log(LOG_ERROR, "Unrecognized value for 'isolation': '%s' in section '%s'\n", v->value, cat);
  554. isolation = SQL_TXN_READ_COMMITTED;
  555. }
  556. } else if (!strcasecmp(v->name, "max_connections")) {
  557. if (sscanf(v->value, "%30d", &maxconnections) != 1 || maxconnections < 1) {
  558. ast_log(LOG_WARNING, "max_connections must be a positive integer\n");
  559. maxconnections = 1;
  560. }
  561. } else if (!strcasecmp(v->name, "logging")) {
  562. logging = ast_true(v->value);
  563. } else if (!strcasecmp(v->name, "slow_query_limit")) {
  564. if (sscanf(v->value, "%30d", &slowquerylimit) != 1) {
  565. ast_log(LOG_WARNING, "slow_query_limit must be a positive integer\n");
  566. slowquerylimit = 5000;
  567. }
  568. }
  569. }
  570. if (enabled && !ast_strlen_zero(dsn)) {
  571. new = ao2_alloc(sizeof(*new), odbc_class_destructor);
  572. if (!new) {
  573. res = -1;
  574. break;
  575. }
  576. SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &new->env);
  577. res = SQLSetEnvAttr(new->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
  578. if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
  579. ast_log(LOG_WARNING, "res_odbc: Error SetEnv\n");
  580. ao2_ref(new, -1);
  581. return res;
  582. }
  583. new->backslash_is_escape = bse ? 1 : 0;
  584. new->forcecommit = forcecommit ? 1 : 0;
  585. new->isolation = isolation;
  586. new->conntimeout = conntimeout;
  587. new->negative_connection_cache = ncache;
  588. new->maxconnections = maxconnections;
  589. new->logging = logging;
  590. new->slowquerylimit = slowquerylimit;
  591. if (cat)
  592. ast_copy_string(new->name, cat, sizeof(new->name));
  593. if (dsn)
  594. ast_copy_string(new->dsn, dsn, sizeof(new->dsn));
  595. if (username && !(new->username = ast_strdup(username))) {
  596. ao2_ref(new, -1);
  597. break;
  598. }
  599. if (password && !(new->password = ast_strdup(password))) {
  600. ao2_ref(new, -1);
  601. break;
  602. }
  603. if (sanitysql && !(new->sanitysql = ast_strdup(sanitysql))) {
  604. ao2_ref(new, -1);
  605. break;
  606. }
  607. ast_mutex_init(&new->lock);
  608. ast_cond_init(&new->cond, NULL);
  609. odbc_register_class(new, preconnect);
  610. ast_log(LOG_NOTICE, "Registered ODBC class '%s' dsn->[%s]\n", cat, dsn);
  611. ao2_ref(new, -1);
  612. new = NULL;
  613. }
  614. }
  615. }
  616. ast_config_destroy(config);
  617. return res;
  618. }
  619. static char *handle_cli_odbc_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
  620. {
  621. struct ao2_iterator aoi;
  622. struct odbc_class *class;
  623. int length = 0;
  624. int which = 0;
  625. char *ret = NULL;
  626. switch (cmd) {
  627. case CLI_INIT:
  628. e->command = "odbc show";
  629. e->usage =
  630. "Usage: odbc show [class]\n"
  631. " List settings of a particular ODBC class or,\n"
  632. " if not specified, all classes.\n";
  633. return NULL;
  634. case CLI_GENERATE:
  635. if (a->pos != 2)
  636. return NULL;
  637. length = strlen(a->word);
  638. aoi = ao2_iterator_init(class_container, 0);
  639. while ((class = ao2_iterator_next(&aoi))) {
  640. if (!strncasecmp(a->word, class->name, length) && ++which > a->n) {
  641. ret = ast_strdup(class->name);
  642. }
  643. ao2_ref(class, -1);
  644. if (ret) {
  645. break;
  646. }
  647. }
  648. ao2_iterator_destroy(&aoi);
  649. if (!ret && !strncasecmp(a->word, "all", length) && ++which > a->n) {
  650. ret = ast_strdup("all");
  651. }
  652. return ret;
  653. }
  654. ast_cli(a->fd, "\nODBC DSN Settings\n");
  655. ast_cli(a->fd, "-----------------\n\n");
  656. aoi = ao2_iterator_init(class_container, 0);
  657. while ((class = ao2_iterator_next(&aoi))) {
  658. if ((a->argc == 2) || (a->argc == 3 && !strcmp(a->argv[2], "all")) || (!strcmp(a->argv[2], class->name))) {
  659. char timestr[80];
  660. struct ast_tm tm;
  661. ast_cli(a->fd, " Name: %s\n DSN: %s\n", class->name, class->dsn);
  662. if (class->last_negative_connect.tv_sec > 0) {
  663. ast_localtime(&class->last_negative_connect, &tm, NULL);
  664. ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %T", &tm);
  665. ast_cli(a->fd, " Last fail connection attempt: %s\n", timestr);
  666. }
  667. ast_cli(a->fd, " Number of active connections: %zd (out of %d)\n", class->connection_cnt, class->maxconnections);
  668. ast_cli(a->fd, " Logging: %s\n", class->logging ? "Enabled" : "Disabled");
  669. if (class->logging) {
  670. ast_cli(a->fd, " Number of prepares executed: %d\n", class->prepares_executed);
  671. ast_cli(a->fd, " Number of queries executed: %d\n", class->queries_executed);
  672. ast_mutex_lock(&class->lock);
  673. if (class->sql_text) {
  674. ast_cli(a->fd, " Longest running SQL query: %s (%ld milliseconds)\n", class->sql_text, class->longest_query_execution_time);
  675. }
  676. ast_mutex_unlock(&class->lock);
  677. }
  678. ast_cli(a->fd, "\n");
  679. }
  680. ao2_ref(class, -1);
  681. }
  682. ao2_iterator_destroy(&aoi);
  683. return CLI_SUCCESS;
  684. }
  685. static struct ast_cli_entry cli_odbc[] = {
  686. AST_CLI_DEFINE(handle_cli_odbc_show, "List ODBC DSN(s)")
  687. };
  688. static void odbc_register_class(struct odbc_class *class, int preconnect)
  689. {
  690. struct odbc_obj *obj;
  691. ao2_link(class_container, class);
  692. /* I still have a reference in the caller, so a deref is NOT missing here. */
  693. if (!preconnect) {
  694. return;
  695. }
  696. /* Request and release builds a connection */
  697. obj = ast_odbc_request_obj(class->name, 0);
  698. if (obj) {
  699. ast_odbc_release_obj(obj);
  700. }
  701. return;
  702. }
  703. void ast_odbc_release_obj(struct odbc_obj *obj)
  704. {
  705. struct odbc_class *class = obj->parent;
  706. ast_debug(2, "Releasing ODBC handle %p into pool\n", obj);
  707. /* The odbc_obj only holds a reference to the class when it is
  708. * actively being used. This guarantees no circular reference
  709. * between odbc_class and odbc_obj. Since it is being released
  710. * we also release our class reference. If a reload occurred before
  711. * the class will go away automatically once all odbc_obj are
  712. * released back.
  713. */
  714. obj->parent = NULL;
  715. /* Free the SQL text so that the next user of this connection has
  716. * a fresh start.
  717. */
  718. ast_free(obj->sql_text);
  719. obj->sql_text = NULL;
  720. ast_mutex_lock(&class->lock);
  721. AST_LIST_INSERT_HEAD(&class->connections, obj, list);
  722. ast_cond_signal(&class->cond);
  723. ast_mutex_unlock(&class->lock);
  724. ao2_ref(class, -1);
  725. }
  726. int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
  727. {
  728. return obj->parent->backslash_is_escape;
  729. }
  730. static int aoro2_class_cb(void *obj, void *arg, int flags)
  731. {
  732. struct odbc_class *class = obj;
  733. char *name = arg;
  734. if (!strcmp(class->name, name) && !class->delme) {
  735. return CMP_MATCH | CMP_STOP;
  736. }
  737. return 0;
  738. }
  739. unsigned int ast_odbc_get_max_connections(const char *name)
  740. {
  741. struct odbc_class *class;
  742. unsigned int max_connections;
  743. class = ao2_callback(class_container, 0, aoro2_class_cb, (char *) name);
  744. if (!class) {
  745. return 0;
  746. }
  747. max_connections = class->maxconnections;
  748. ao2_ref(class, -1);
  749. return max_connections;
  750. }
  751. /*!
  752. * \brief Determine if the connection has died.
  753. *
  754. * \param connection The connection to check
  755. * \param class The ODBC class
  756. * \retval 1 Yep, it's dead
  757. * \retval 0 It's alive and well
  758. */
  759. static int connection_dead(struct odbc_obj *connection, struct odbc_class *class)
  760. {
  761. char *test_sql = "select 1";
  762. SQLINTEGER dead;
  763. SQLRETURN res;
  764. SQLHSTMT stmt;
  765. res = SQLGetConnectAttr(connection->con, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
  766. if (SQL_SUCCEEDED(res)) {
  767. return dead == SQL_CD_TRUE ? 1 : 0;
  768. }
  769. /* If the Driver doesn't support SQL_ATTR_CONNECTION_DEAD do a
  770. * probing query instead
  771. */
  772. res = SQLAllocHandle(SQL_HANDLE_STMT, connection->con, &stmt);
  773. if (!SQL_SUCCEEDED(res)) {
  774. return 1;
  775. }
  776. if (!ast_strlen_zero(class->sanitysql)) {
  777. test_sql = class->sanitysql;
  778. }
  779. res = SQLPrepare(stmt, (unsigned char *)test_sql, SQL_NTS);
  780. if (!SQL_SUCCEEDED(res)) {
  781. SQLFreeHandle(SQL_HANDLE_STMT, stmt);
  782. return 1;
  783. }
  784. res = SQLExecute(stmt);
  785. SQLFreeHandle(SQL_HANDLE_STMT, stmt);
  786. return SQL_SUCCEEDED(res) ? 0 : 1;
  787. }
  788. struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags, const char *file, const char *function, int lineno)
  789. {
  790. struct odbc_obj *obj = NULL;
  791. struct odbc_class *class;
  792. if (!(class = ao2_callback(class_container, 0, aoro2_class_cb, (char *) name))) {
  793. ast_debug(1, "Class '%s' not found!\n", name);
  794. return NULL;
  795. }
  796. while (!obj) {
  797. ast_mutex_lock(&class->lock);
  798. obj = AST_LIST_REMOVE_HEAD(&class->connections, list);
  799. ast_mutex_unlock(&class->lock);
  800. if (!obj) {
  801. ast_mutex_lock(&class->lock);
  802. if (class->connection_cnt < class->maxconnections) {
  803. /* If no connection is immediately available establish a new
  804. * one if allowed. If we try and fail we give up completely as
  805. * we could go into an infinite loop otherwise.
  806. */
  807. obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
  808. if (!obj) {
  809. ast_mutex_unlock(&class->lock);
  810. break;
  811. }
  812. obj->parent = ao2_bump(class);
  813. class->connection_cnt++;
  814. ast_mutex_unlock(&class->lock);
  815. if (odbc_obj_connect(obj) == ODBC_FAIL) {
  816. ast_mutex_lock(&class->lock);
  817. class->connection_cnt--;
  818. ast_mutex_unlock(&class->lock);
  819. ao2_ref(obj->parent, -1);
  820. ao2_ref(obj, -1);
  821. obj = NULL;
  822. break;
  823. }
  824. ast_mutex_lock(&class->lock);
  825. ast_debug(2, "Created ODBC handle %p on class '%s', new count is %zd\n", obj,
  826. name, class->connection_cnt);
  827. } else {
  828. /* Otherwise if we're not allowed to create a new one we
  829. * wait for another thread to give up the connection they
  830. * own.
  831. */
  832. ast_cond_wait(&class->cond, &class->lock);
  833. }
  834. ast_mutex_unlock(&class->lock);
  835. } else if (connection_dead(obj, class)) {
  836. /* If the connection is dead try to grab another functional one from the
  837. * pool instead of trying to resurrect this one.
  838. */
  839. ao2_ref(obj, -1);
  840. obj = NULL;
  841. ast_mutex_lock(&class->lock);
  842. class->connection_cnt--;
  843. ast_debug(2, "ODBC handle %p dead - removing from class '%s', new count is %zd\n",
  844. obj, name, class->connection_cnt);
  845. ast_mutex_unlock(&class->lock);
  846. } else {
  847. /* We successfully grabbed a connection from the pool and all is well!
  848. */
  849. obj->parent = ao2_bump(class);
  850. ast_debug(2, "Reusing ODBC handle %p from class '%s'\n", obj, name);
  851. }
  852. }
  853. ao2_ref(class, -1);
  854. return obj;
  855. }
  856. struct odbc_obj *_ast_odbc_request_obj(const char *name, int check, const char *file, const char *function, int lineno)
  857. {
  858. struct ast_flags flags = { check ? RES_ODBC_SANITY_CHECK : 0 };
  859. /* XXX New flow means that the "check" parameter doesn't do anything. We're requesting
  860. * a connection from ODBC. We'll either get a new one, which obviously is already connected, or
  861. * we'll get one from the ODBC connection pool. In that case, it will ensure to only give us a
  862. * live connection
  863. */
  864. return _ast_odbc_request_obj2(name, flags, file, function, lineno);
  865. }
  866. static odbc_status odbc_obj_disconnect(struct odbc_obj *obj)
  867. {
  868. int res;
  869. SQLINTEGER err;
  870. short int mlen;
  871. unsigned char msg[200], state[10];
  872. SQLHDBC con;
  873. /* Nothing to disconnect */
  874. if (!obj->con) {
  875. return ODBC_SUCCESS;
  876. }
  877. con = obj->con;
  878. obj->con = NULL;
  879. res = SQLDisconnect(con);
  880. if ((res = SQLFreeHandle(SQL_HANDLE_DBC, con)) == SQL_SUCCESS) {
  881. ast_debug(3, "Database handle %p (connection %p) deallocated\n", obj, con);
  882. } else {
  883. SQLGetDiagRec(SQL_HANDLE_DBC, con, 1, state, &err, msg, 100, &mlen);
  884. ast_log(LOG_WARNING, "Unable to deallocate database handle %p? %d errno=%d %s\n", con, res, (int)err, msg);
  885. }
  886. return ODBC_SUCCESS;
  887. }
  888. static odbc_status odbc_obj_connect(struct odbc_obj *obj)
  889. {
  890. int res;
  891. SQLINTEGER err;
  892. short int mlen;
  893. unsigned char msg[200], state[10];
  894. #ifdef NEEDTRACE
  895. SQLINTEGER enable = 1;
  896. char *tracefile = "/tmp/odbc.trace";
  897. #endif
  898. SQLHDBC con;
  899. long int negative_cache_expiration;
  900. ast_assert(obj->con == NULL);
  901. ast_debug(3, "Connecting %s(%p)\n", obj->parent->name, obj);
  902. /* Dont connect while server is marked as unreachable via negative_connection_cache */
  903. negative_cache_expiration = obj->parent->last_negative_connect.tv_sec + obj->parent->negative_connection_cache.tv_sec;
  904. if (time(NULL) < negative_cache_expiration) {
  905. char secs[AST_TIME_T_LEN];
  906. ast_time_t_to_string(negative_cache_expiration - time(NULL), secs, sizeof(secs));
  907. ast_log(LOG_WARNING, "Not connecting to %s. Negative connection cache for %s seconds\n", obj->parent->name, secs);
  908. return ODBC_FAIL;
  909. }
  910. res = SQLAllocHandle(SQL_HANDLE_DBC, obj->parent->env, &con);
  911. if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
  912. ast_log(LOG_WARNING, "res_odbc: Error AllocHDB %d\n", res);
  913. obj->parent->last_negative_connect = ast_tvnow();
  914. return ODBC_FAIL;
  915. }
  916. SQLSetConnectAttr(con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)(long) obj->parent->conntimeout, 0);
  917. SQLSetConnectAttr(con, SQL_ATTR_CONNECTION_TIMEOUT, (SQLPOINTER *)(long) obj->parent->conntimeout, 0);
  918. #ifdef NEEDTRACE
  919. SQLSetConnectAttr(con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER);
  920. SQLSetConnectAttr(con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile));
  921. #endif
  922. res = SQLConnect(con,
  923. (SQLCHAR *) obj->parent->dsn, SQL_NTS,
  924. (SQLCHAR *) obj->parent->username, SQL_NTS,
  925. (SQLCHAR *) obj->parent->password, SQL_NTS);
  926. if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
  927. SQLGetDiagRec(SQL_HANDLE_DBC, con, 1, state, &err, msg, 100, &mlen);
  928. obj->parent->last_negative_connect = ast_tvnow();
  929. ast_log(LOG_WARNING, "res_odbc: Error SQLConnect=%d errno=%d %s\n", res, (int)err, msg);
  930. if ((res = SQLFreeHandle(SQL_HANDLE_DBC, con)) != SQL_SUCCESS) {
  931. SQLGetDiagRec(SQL_HANDLE_DBC, con, 1, state, &err, msg, 100, &mlen);
  932. ast_log(LOG_WARNING, "Unable to deallocate database handle %p? %d errno=%d %s\n", con, res, (int)err, msg);
  933. }
  934. return ODBC_FAIL;
  935. } else {
  936. ast_debug(3, "res_odbc: Connected to %s [%s (%p)]\n", obj->parent->name, obj->parent->dsn, obj);
  937. }
  938. obj->con = con;
  939. return ODBC_SUCCESS;
  940. }
  941. static int reload(void)
  942. {
  943. struct odbc_cache_tables *table;
  944. struct odbc_class *class;
  945. struct ao2_iterator aoi = ao2_iterator_init(class_container, 0);
  946. /* First, mark all to be purged */
  947. while ((class = ao2_iterator_next(&aoi))) {
  948. class->delme = 1;
  949. ao2_ref(class, -1);
  950. }
  951. ao2_iterator_destroy(&aoi);
  952. load_odbc_config();
  953. aoi = ao2_iterator_init(class_container, 0);
  954. while ((class = ao2_iterator_next(&aoi))) {
  955. if (class->delme) {
  956. ao2_unlink(class_container, class);
  957. }
  958. ao2_ref(class, -1);
  959. }
  960. ao2_iterator_destroy(&aoi);
  961. /* Empty the cache; it will get rebuilt the next time the tables are needed. */
  962. AST_RWLIST_WRLOCK(&odbc_tables);
  963. while ((table = AST_RWLIST_REMOVE_HEAD(&odbc_tables, list))) {
  964. destroy_table_cache(table);
  965. }
  966. AST_RWLIST_UNLOCK(&odbc_tables);
  967. return 0;
  968. }
  969. static int unload_module(void)
  970. {
  971. ao2_cleanup(class_container);
  972. ast_cli_unregister_multiple(cli_odbc, ARRAY_LEN(cli_odbc));
  973. return 0;
  974. }
  975. static int load_module(void)
  976. {
  977. class_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, ao2_match_by_addr);
  978. if (!class_container) {
  979. return AST_MODULE_LOAD_DECLINE;
  980. }
  981. if (load_odbc_config() == -1) {
  982. return AST_MODULE_LOAD_DECLINE;
  983. }
  984. ast_module_shutdown_ref(ast_module_info->self);
  985. ast_cli_register_multiple(cli_odbc, ARRAY_LEN(cli_odbc));
  986. return AST_MODULE_LOAD_SUCCESS;
  987. }
  988. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "ODBC resource",
  989. .support_level = AST_MODULE_SUPPORT_CORE,
  990. .load = load_module,
  991. .unload = unload_module,
  992. .reload = reload,
  993. .load_pri = AST_MODPRI_REALTIME_DEPEND,
  994. .requires = "res_odbc_transaction",
  995. );