[asterisk-commits] tilghman: branch tilghman/odbc_tx_support r166900 - in /team/tilghman/odbc_tx...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Dec 29 18:33:44 CST 2008
Author: tilghman
Date: Mon Dec 29 18:33:44 2008
New Revision: 166900
URL: http://svn.digium.com/view/asterisk?view=rev&rev=166900
Log:
Testing yields improvements
Modified:
team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h
team/tilghman/odbc_tx_support/res/res_odbc.c
Modified: team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h
URL: http://svn.digium.com/view/asterisk/team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h?view=diff&rev=166900&r1=166899&r2=166900
==============================================================================
--- team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h (original)
+++ team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h Mon Dec 29 18:33:44 2008
@@ -58,9 +58,6 @@
AST_LIST_ENTRY(odbc_obj) list;
};
-/*!\brief These aren't used in any API calls, but they are kept in a common
- * location, simply for convenience and to avoid duplication.
- */
struct odbc_cache_columns {
char *name;
SQLSMALLINT type;
Modified: team/tilghman/odbc_tx_support/res/res_odbc.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/odbc_tx_support/res/res_odbc.c?view=diff&rev=166900&r1=166899&r2=166900
==============================================================================
--- team/tilghman/odbc_tx_support/res/res_odbc.c (original)
+++ team/tilghman/odbc_tx_support/res/res_odbc.c Mon Dec 29 18:33:44 2008
@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 1999 - 2005, Digium, Inc.
+ * Copyright (C) 1999 - 2008, Digium, Inc.
*
* Mark Spencer <markster at digium.com>
*
@@ -25,6 +25,7 @@
*
* \author Mark Spencer <markster at digium.com>
* \author Anthony Minessale II <anthmct at yahoo.com>
+ * \author Tilghman Lesher <tilghman at digium.com>
*
* \arg See also: \ref cdr_odbc
*/
@@ -82,6 +83,7 @@
static odbc_status odbc_obj_disconnect(struct odbc_obj *obj);
static int odbc_register_class(struct odbc_class *class, int connect);
static void odbc_txn_free(void *data);
+static void odbc_release_obj2(struct odbc_obj *obj, struct odbc_txn_frame *tx);
AST_THREADSTORAGE(errors_buf);
@@ -92,12 +94,6 @@
struct odbc_txn_frame {
AST_LIST_ENTRY(odbc_txn_frame) list;
- /*!\brief Status of this transaction
- * This is important only when considering what happens when an uncommitted
- * transaction is released without an explicit Commit or Rollback. That
- * action is decided by the forcecommit flag, below.
- */
- enum { ODBC_STATUS_TXCLOSED = 0, ODBC_STATUS_TXOPEN = 1 } status;
struct ast_channel *owner;
struct odbc_obj *obj; /*!< Database handle within which transacted statements are run */
/*!\brief Is this record the current active transaction within the channel?
@@ -213,6 +209,7 @@
txn->obj = obj;
txn->isolation = obj->parent->isolation;
txn->forcecommit = obj->parent->forcecommit;
+ txn->owner = chan;
txn->active = 1;
/* On creation, the txn becomes active, and all others inactive */
@@ -220,51 +217,58 @@
otxn->active = 0;
}
AST_LIST_INSERT_TAIL(oldlist, txn, list);
+
+ obj->txf = txn;
+ obj->tx = 1;
}
AST_LIST_UNLOCK(oldlist);
return txn;
}
-static void release_transaction(struct odbc_txn_frame *tx)
-{
- struct ast_channel *chan;
- struct ast_datastore *txn_store;
- AST_LIST_HEAD(, odbc_txn_frame) *oldlist;
-
- if (tx && tx->owner) {
- chan = tx->owner;
- ast_channel_lock(chan);
- } else {
- /* No channel == no transaction */
- return;
- }
-
- if (!(txn_store = ast_channel_datastore_find(chan, &txn_info, NULL))) {
- ast_channel_unlock(chan);
- return;
- }
-
- oldlist = txn_store->data;
- AST_LIST_LOCK(oldlist);
- AST_LIST_REMOVE(oldlist, tx, list);
- AST_LIST_UNLOCK(oldlist);
+static struct odbc_txn_frame *release_transaction(struct odbc_txn_frame *tx)
+{
+ if (!tx) {
+ return NULL;
+ }
+
+ ast_debug(2, "release_transaction(%p) called (tx->obj = %p, tx->obj->txf = %p)\n", tx, tx->obj, tx->obj ? tx->obj->txf : NULL);
+
+ /* If we have an owner, disassociate */
+ if (tx->owner) {
+ struct ast_datastore *txn_store;
+ AST_LIST_HEAD(, odbc_txn_frame) *oldlist;
+
+ ast_channel_lock(tx->owner);
+ if ((txn_store = ast_channel_datastore_find(tx->owner, &txn_info, NULL))) {
+ oldlist = txn_store->data;
+ AST_LIST_LOCK(oldlist);
+ AST_LIST_REMOVE(oldlist, tx, list);
+ AST_LIST_UNLOCK(oldlist);
+ }
+ ast_channel_unlock(tx->owner);
+ tx->owner = NULL;
+ }
+
if (tx->obj) {
- /* Have to remove this link, first, or the destructors will recursively call each other */
+ /* If we have any uncommitted transactions, they are handled when we release the object */
+ struct odbc_obj *obj = tx->obj;
+ /* Prevent recursion during destruction */
tx->obj->txf = NULL;
- /* If we have any uncommitted transactions, they are handled when we release the object */
- ast_odbc_release_obj(tx->obj);
tx->obj = NULL;
- }
- tx->owner = NULL;
+ odbc_release_obj2(obj, tx);
+ }
ast_free(tx);
- ast_channel_unlock(chan);
+ return NULL;
}
static void odbc_txn_free(void *vdata)
{
struct odbc_txn_frame *tx;
AST_LIST_HEAD(, odbc_txn_frame) *oldlist = vdata;
+
+ ast_debug(2, "odbc_txn_free(%p) called\n", vdata);
+
AST_LIST_LOCK(oldlist);
while ((tx = AST_LIST_REMOVE_HEAD(oldlist, list))) {
release_transaction(tx);
@@ -679,7 +683,8 @@
pooling = 0;
limit = 0;
bse = 1;
- forcecommit = isolation = 0;
+ forcecommit = 0;
+ isolation = SQL_TXN_READ_COMMITTED;
for (v = ast_variable_browse(config, cat); v; v = v->next) {
if (!strcasecmp(v->name, "pooling")) {
if (ast_true(v->value))
@@ -892,15 +897,16 @@
}
}
-void ast_odbc_release_obj(struct odbc_obj *obj)
-{
- struct odbc_txn_frame *tx = find_transaction(NULL, obj, NULL, 0);
+static void odbc_release_obj2(struct odbc_obj *obj, struct odbc_txn_frame *tx)
+{
SQLINTEGER nativeerror=0, numfields=0;
SQLSMALLINT diagbytes=0, i;
unsigned char state[10], diagnostic[256];
+ ast_debug(2, "odbc_release_obj2(%p) called (obj->txf = %p)\n", obj, obj->txf);
if (tx) {
- if (SQLEndTran(SQL_HANDLE_DBC, obj->con, obj->parent->forcecommit ? SQL_COMMIT : SQL_ROLLBACK) == SQL_ERROR) {
+ ast_debug(1, "called on a transactional handle with %s\n", tx->forcecommit ? "COMMIT" : "ROLLBACK");
+ if (SQLEndTran(SQL_HANDLE_DBC, obj->con, tx->forcecommit ? SQL_COMMIT : SQL_ROLLBACK) == SQL_ERROR) {
/* Handle possible transaction commit failure */
SQLGetDiagField(SQL_HANDLE_DBC, obj->con, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
for (i = 0; i < numfields; i++) {
@@ -920,7 +926,7 @@
}
/* Transaction is done, reset autocommit */
- if (obj->parent->haspool && SQLSetConnectAttr(obj->con, SQL_ATTR_AUTOCOMMIT, (void *)SQL_AUTOCOMMIT_ON, 0) == SQL_ERROR) {
+ if (SQLSetConnectAttr(obj->con, SQL_ATTR_AUTOCOMMIT, (void *)SQL_AUTOCOMMIT_ON, 0) == SQL_ERROR) {
SQLGetDiagField(SQL_HANDLE_DBC, obj->con, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
for (i = 0; i < numfields; i++) {
SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
@@ -943,11 +949,17 @@
* reused. For non-pooled connections, it does nothing. */
obj->used = 0;
if (obj->txf) {
- /* We'll get called a second time, with txf set to NULL */
- release_transaction(obj->txf);
- } else {
- ao2_ref(obj, -1);
- }
+ /* Prevent recursion -- transaction is already closed out. */
+ obj->txf->obj = NULL;
+ obj->txf = release_transaction(obj->txf);
+ }
+ ao2_ref(obj, -1);
+}
+
+void ast_odbc_release_obj(struct odbc_obj *obj)
+{
+ struct odbc_txn_frame *tx = find_transaction(NULL, obj, NULL, 0);
+ odbc_release_obj2(obj, tx);
}
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
@@ -988,7 +1000,6 @@
}
pbx_builtin_setvar_helper(chan, "COMMIT_RESULT", ast_str_buffer(errors));
}
- tx->status = ODBC_STATUS_TXCLOSED;
}
return 0;
}
@@ -1026,7 +1037,6 @@
}
pbx_builtin_setvar_helper(chan, "ROLLBACK_RESULT", ast_str_buffer(errors));
}
- tx->status = ODBC_STATUS_TXCLOSED;
}
return 0;
}
@@ -1087,16 +1097,16 @@
ast_mutex_init(&obj->lock);
/* obj inherits the outstanding reference to class */
obj->parent = class;
+ class = NULL;
if (odbc_obj_connect(obj) == ODBC_FAIL) {
ast_log(LOG_WARNING, "Failed to connect to %s\n", name);
ao2_ref(obj, -1);
obj = NULL;
} else {
obj->used = 1;
- ao2_link(class->obj_container, obj);
- ast_atomic_fetchadd_int(&class->count, +1);
- }
- class = NULL;
+ ao2_link(obj->parent->obj_container, obj);
+ ast_atomic_fetchadd_int(&obj->parent->count, +1);
+ }
} else {
/* Object is not constructed, so delete outstanding reference to class. */
ao2_ref(class, -1);
@@ -1128,14 +1138,15 @@
ast_mutex_init(&obj->lock);
/* obj inherits the outstanding reference to class */
obj->parent = class;
+ class = NULL;
if (odbc_obj_connect(obj) == ODBC_FAIL) {
ast_log(LOG_WARNING, "Failed to connect to %s\n", name);
ao2_ref(obj, -1);
obj = NULL;
} else {
obj->used = 1;
- ao2_link(class->obj_container, obj);
- ast_atomic_fetchadd_int(&class->count, +1);
+ ao2_link(obj->parent->obj_container, obj);
+ ast_atomic_fetchadd_int(&obj->parent->count, +1);
}
}
@@ -1158,22 +1169,21 @@
class = NULL;
} else {
/* No entry: build one */
- obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
- if (!obj) {
+ if (!(obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor))) {
ao2_ref(class, -1);
return NULL;
}
ast_mutex_init(&obj->lock);
/* obj inherits the outstanding reference to class */
obj->parent = class;
+ class = NULL;
if (odbc_obj_connect(obj) == ODBC_FAIL) {
ast_log(LOG_WARNING, "Failed to connect to %s\n", name);
ao2_ref(obj, -1);
obj = NULL;
} else {
- ao2_link(class->obj_container, obj);
- }
- class = NULL;
+ ao2_link(obj->parent->obj_container, obj);
+ }
}
if (obj && SQLSetConnectAttr(obj->con, SQL_ATTR_AUTOCOMMIT, (void *)SQL_AUTOCOMMIT_ON, 0) == SQL_ERROR) {
@@ -1190,7 +1200,7 @@
}
/* Set the isolation property */
- if (SQLSetConnectAttr(obj->con, SQL_ATTR_TXN_ISOLATION, (void *)(long)obj->parent->isolation, 0) == SQL_ERROR) {
+ if (obj && SQLSetConnectAttr(obj->con, SQL_ATTR_TXN_ISOLATION, (void *)(long)obj->parent->isolation, 0) == SQL_ERROR) {
SQLGetDiagField(SQL_HANDLE_DBC, obj->con, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
for (i = 0; i < numfields; i++) {
SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes);
@@ -1418,6 +1428,7 @@
if (!(tx = find_transaction(chan, obj, value, 0))) {
return -1;
}
+ obj->tx = 1;
}
return 0;
} else if (strcasecmp(args.property, "forcecommit") == 0) {
More information about the asterisk-commits
mailing list