diff --git a/funcs/func_odbc.c b/funcs/func_odbc.c index c8b65eb226b0477959dd66dcd3ed45547b7ff73a..0205f187293a660964816541c370b8e155588103 100644 --- a/funcs/func_odbc.c +++ b/funcs/func_odbc.c @@ -233,17 +233,23 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co if (!query) { ast_log(LOG_ERROR, "No such function '%s'\n", cmd); AST_RWLIST_UNLOCK(&queries); - pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + if (chan) { + pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + } return -1; } if (!chan) { - if ((chan = ast_channel_alloc(0, AST_STATE_DOWN, "", "", "", "", "", "", 0, "Bogus/func_odbc"))) - bogus_chan = 1; + if (!(chan = ast_dummy_channel_alloc())) { + AST_RWLIST_UNLOCK(&queries); + return -1; + } + bogus_chan = 1; } - if (chan) + if (!bogus_chan) { ast_autoservice_start(chan); + } ast_str_make_space(&buf, strlen(query->sql_write) * 2 + 300); ast_str_make_space(&insertbuf, strlen(query->sql_insert) * 2 + 300); @@ -254,12 +260,11 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co if (!s || !t) { ast_log(LOG_ERROR, "Out of memory\n"); AST_RWLIST_UNLOCK(&queries); - if (chan) + if (!bogus_chan) { ast_autoservice_stop(chan); - if (bogus_chan) { - ast_channel_release(chan); - } else { pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + } else { + ast_channel_release(chan); } return -1; } @@ -283,44 +288,48 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co ast_str_substitute_variables(&buf, 0, chan, query->sql_write); ast_str_substitute_variables(&insertbuf, 0, chan, query->sql_insert); - /* Restore prior values */ - for (i = 0; i < args.argc; i++) { - snprintf(varname, sizeof(varname), "ARG%d", i + 1); - pbx_builtin_setvar_helper(chan, varname, NULL); - } - - for (i = 0; i < values.argc; i++) { - snprintf(varname, sizeof(varname), "VAL%d", i + 1); - pbx_builtin_setvar_helper(chan, varname, NULL); - } - pbx_builtin_setvar_helper(chan, "VALUE", NULL); - - /*!\note - * Okay, this part is confusing. Transactions belong to a single database - * handle. Therefore, when working with transactions, we CANNOT failover - * to multiple DSNs. We MUST have a single handle all the way through the - * transaction, or else we CANNOT enforce atomicity. - */ - for (dsn = 0; dsn < 5; dsn++) { - if (transactional) { - /* This can only happen second time through or greater. */ - ast_log(LOG_WARNING, "Transactions do not work well with multiple DSNs for 'writehandle'\n"); + if (bogus_chan) { + chan = ast_channel_release(chan); + } else { + /* Restore prior values */ + for (i = 0; i < args.argc; i++) { + snprintf(varname, sizeof(varname), "ARG%d", i + 1); + pbx_builtin_setvar_helper(chan, varname, NULL); } - if (!ast_strlen_zero(query->writehandle[dsn])) { - if ((obj = ast_odbc_retrieve_transaction_obj(chan, query->writehandle[dsn]))) { - transactional = 1; - } else { - obj = ast_odbc_request_obj(query->writehandle[dsn], 0); - transactional = 0; + for (i = 0; i < values.argc; i++) { + snprintf(varname, sizeof(varname), "VAL%d", i + 1); + pbx_builtin_setvar_helper(chan, varname, NULL); + } + pbx_builtin_setvar_helper(chan, "VALUE", NULL); + + /*!\note + * Okay, this part is confusing. Transactions belong to a single database + * handle. Therefore, when working with transactions, we CANNOT failover + * to multiple DSNs. We MUST have a single handle all the way through the + * transaction, or else we CANNOT enforce atomicity. + */ + for (dsn = 0; dsn < 5; dsn++) { + if (transactional) { + /* This can only happen second time through or greater. */ + ast_log(LOG_WARNING, "Transactions do not work well with multiple DSNs for 'writehandle'\n"); } - if (obj && (stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(buf)))) { - break; + + if (!ast_strlen_zero(query->writehandle[dsn])) { + if ((obj = ast_odbc_retrieve_transaction_obj(chan, query->writehandle[dsn]))) { + transactional = 1; + } else { + obj = ast_odbc_request_obj(query->writehandle[dsn], 0); + transactional = 0; + } + if (obj && (stmt = ast_odbc_direct_execute(obj, generic_execute, ast_str_buffer(buf)))) { + break; + } } - } - if (obj && !transactional) { - ast_odbc_release_obj(obj); + if (obj && !transactional) { + ast_odbc_release_obj(obj); + } } } @@ -351,9 +360,11 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co * flag this as -1 rows. Note that this is different from 0 affected rows * which would be the case if we succeeded in our query, but the values did * not change. */ - snprintf(varname, sizeof(varname), "%d", (int)rows); - pbx_builtin_setvar_helper(chan, "ODBCROWS", varname); - pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + if (!bogus_chan) { + snprintf(varname, sizeof(varname), "%d", (int)rows); + pbx_builtin_setvar_helper(chan, "ODBCROWS", varname); + pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + } if (stmt) { SQLCloseCursor(stmt); @@ -364,10 +375,9 @@ static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, co obj = NULL; } - if (chan) + if (!bogus_chan) { ast_autoservice_stop(chan); - if (bogus_chan) - ast_channel_release(chan); + } return 0; } @@ -392,7 +402,9 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha const char *status = "FAILURE"; if (!sql) { - pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + if (chan) { + pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + } return -1; } @@ -408,18 +420,22 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha if (!query) { ast_log(LOG_ERROR, "No such function '%s'\n", cmd); AST_RWLIST_UNLOCK(&queries); - pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); - pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + if (chan) { + pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); + pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + } return -1; } if (!chan) { - if ((chan = ast_channel_alloc(0, AST_STATE_DOWN, "", "", "", "", "", "", 0, "Bogus/func_odbc"))) { - bogus_chan = 1; + if (!(chan = ast_dummy_channel_alloc())) { + AST_RWLIST_UNLOCK(&queries); + return -1; } + bogus_chan = 1; } - if (chan) { + if (!bogus_chan) { ast_autoservice_start(chan); } @@ -431,15 +447,19 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha ast_str_substitute_variables(&sql, 0, chan, query->sql_read); - /* Restore prior values */ - for (x = 0; x < args.argc; x++) { - snprintf(varname, sizeof(varname), "ARG%d", x + 1); - pbx_builtin_setvar_helper(chan, varname, NULL); + if (bogus_chan) { + chan = ast_channel_release(chan); + } else { + /* Restore prior values */ + for (x = 0; x < args.argc; x++) { + snprintf(varname, sizeof(varname), "ARG%d", x + 1); + pbx_builtin_setvar_helper(chan, varname, NULL); + } } /* Save these flags, so we can release the lock */ escapecommas = ast_test_flag(query, OPT_ESCAPECOMMAS); - if (ast_test_flag(query, OPT_MULTIROW)) { + if (!bogus_chan && ast_test_flag(query, OPT_MULTIROW)) { resultset = ast_calloc(1, sizeof(*resultset)); AST_LIST_HEAD_INIT(resultset); if (query->rowlimit) { @@ -468,13 +488,10 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha ast_odbc_release_obj(obj); obj = NULL; } - pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); - if (chan) { + if (!bogus_chan) { + pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); ast_autoservice_stop(chan); } - if (bogus_chan) { - ast_channel_release(chan); - } return -1; } @@ -485,13 +502,10 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha SQLFreeHandle (SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); obj = NULL; - pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); - if (chan) { + if (!bogus_chan) { + pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); ast_autoservice_stop(chan); } - if (bogus_chan) { - ast_channel_release(chan); - } return -1; } @@ -512,12 +526,11 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha SQLFreeHandle(SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); obj = NULL; - pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); - pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); - if (chan) + if (!bogus_chan) { + pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); + pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); ast_autoservice_stop(chan); - if (bogus_chan) - ast_channel_release(chan); + } return res1; } @@ -558,10 +571,7 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha obj = NULL; pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); pbx_builtin_setvar_helper(chan, "ODBCSTATUS", "MEMERROR"); - if (chan) - ast_autoservice_stop(chan); - if (bogus_chan) - ast_channel_release(chan); + ast_autoservice_stop(chan); return -1; } resultset = tmp; @@ -636,41 +646,39 @@ static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, cha } end_acf_read: - snprintf(rowcount, sizeof(rowcount), "%d", y); - pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); - pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); - pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(colnames)); - if (resultset) { - int uid; - struct ast_datastore *odbc_store; - uid = ast_atomic_fetchadd_int(&resultcount, +1) + 1; - snprintf(buf, len, "%d", uid); - odbc_store = ast_datastore_alloc(&odbc_info, buf); - if (!odbc_store) { - ast_log(LOG_ERROR, "Rows retrieved, but unable to store it in the channel. Results fail.\n"); - pbx_builtin_setvar_helper(chan, "ODBCSTATUS", "MEMERROR"); - odbc_datastore_free(resultset); - SQLCloseCursor(stmt); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - obj = NULL; - if (chan) + if (!bogus_chan) { + snprintf(rowcount, sizeof(rowcount), "%d", y); + pbx_builtin_setvar_helper(chan, "ODBCROWS", rowcount); + pbx_builtin_setvar_helper(chan, "ODBCSTATUS", status); + pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", ast_str_buffer(colnames)); + if (resultset) { + int uid; + struct ast_datastore *odbc_store; + uid = ast_atomic_fetchadd_int(&resultcount, +1) + 1; + snprintf(buf, len, "%d", uid); + odbc_store = ast_datastore_alloc(&odbc_info, buf); + if (!odbc_store) { + ast_log(LOG_ERROR, "Rows retrieved, but unable to store it in the channel. Results fail.\n"); + odbc_datastore_free(resultset); + SQLCloseCursor(stmt); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + ast_odbc_release_obj(obj); + obj = NULL; + pbx_builtin_setvar_helper(chan, "ODBCSTATUS", "MEMERROR"); ast_autoservice_stop(chan); - if (bogus_chan) - ast_channel_release(chan); - return -1; + return -1; + } + odbc_store->data = resultset; + ast_channel_datastore_add(chan, odbc_store); } - odbc_store->data = resultset; - ast_channel_datastore_add(chan, odbc_store); } SQLCloseCursor(stmt); SQLFreeHandle(SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); obj = NULL; - if (chan) + if (!bogus_chan) { ast_autoservice_stop(chan); - if (bogus_chan) - ast_channel_release(chan); + } return 0; }