[asterisk-commits] tilghman: branch tilghman/odbc_tx_support r131302 - in /team/tilghman/odbc_tx...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 16 14:01:18 CDT 2008


Author: tilghman
Date: Wed Jul 16 14:01:17 2008
New Revision: 131302

URL: http://svn.digium.com/view/asterisk?view=rev&rev=131302
Log:
Start working with transactions within func_odbc

Modified:
    team/tilghman/odbc_tx_support/   (props changed)
    team/tilghman/odbc_tx_support/funcs/func_odbc.c
    team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h
    team/tilghman/odbc_tx_support/res/res_odbc.c

Propchange: team/tilghman/odbc_tx_support/
------------------------------------------------------------------------------
    automerge = *

Modified: team/tilghman/odbc_tx_support/funcs/func_odbc.c
URL: http://svn.digium.com/view/asterisk/team/tilghman/odbc_tx_support/funcs/func_odbc.c?view=diff&rev=131302&r1=131301&r2=131302
==============================================================================
--- team/tilghman/odbc_tx_support/funcs/func_odbc.c (original)
+++ team/tilghman/odbc_tx_support/funcs/func_odbc.c Wed Jul 16 14:01:17 2008
@@ -131,6 +131,7 @@
 	struct acf_odbc_query *query;
 	char *t, buf[2048], varname[15];
 	int i, dsn, bogus_chan = 0;
+	int transactional = 0;
 	AST_DECLARE_APP_ARGS(values,
 		AST_APP_ARG(field)[100];
 	);
@@ -204,17 +205,36 @@
 	}
 	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 (!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, buf))) {
+				break;
+			}
+		}
+
+		if (obj && !transactional) {
+			ast_odbc_release_obj(obj);
+		}
+	}
+
 	AST_LIST_UNLOCK(&queries);
-
-	for (dsn = 0; dsn < 5; dsn++) {
-		if (!ast_strlen_zero(query->writehandle[dsn])) {
-			obj = ast_odbc_request_obj(query->writehandle[dsn], 0);
-			if (obj)
-				stmt = ast_odbc_direct_execute(obj, generic_execute, buf);
-		}
-		if (stmt)
-			break;
-	}
 
 	if (stmt) {
 		/* Rows affected */
@@ -232,7 +252,7 @@
 		SQLCloseCursor(stmt);
 		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 	}
-	if (obj)
+	if (obj && !transactional)
 		ast_odbc_release_obj(obj);
 
 	if (chan)

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=131302&r1=131301&r2=131302
==============================================================================
--- team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h (original)
+++ team/tilghman/odbc_tx_support/include/asterisk/res_odbc.h Wed Jul 16 14:01:17 2008
@@ -119,7 +119,14 @@
 struct odbc_obj *ast_odbc_request_obj2(const char *name, struct ast_flags flags);
 #endif
 
+#ifdef DEBUG_THREADS
+struct odbc_obj *_ast_odbc_request_obj(const char *name, int check, const char *file, const char *function, int lineno);
+#define ast_odbc_request_obj(a, b)	_ast_odbc_request_obj(a, b, __FILE__, __PRETTY_FUNCTION__, __LINE__)
+#else
 struct odbc_obj *ast_odbc_request_obj(const char *name, int check);
+#endif
+
+struct odbc_obj *ast_odbc_retrieve_transaction_obj(struct ast_channel *chan, const char *objname);
 
 /*! 
  * \brief Releases an ODBC object previously allocated by odbc_request_obj()

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=131302&r1=131301&r2=131302
==============================================================================
--- team/tilghman/odbc_tx_support/res/res_odbc.c (original)
+++ team/tilghman/odbc_tx_support/res/res_odbc.c Wed Jul 16 14:01:17 2008
@@ -65,7 +65,7 @@
 	unsigned int forcecommit:1;          /*!< Should uncommitted transactions be auto-committed on handle release? */
 	unsigned int isolation:2;            /*!< Flags for how the DB should deal with data in other, uncommitted transactions */
 	unsigned int limit;                  /*!< 1023 wasn't enough for some people */
-	unsigned int count;                  /*!< Running count of pooled connections */
+	int count;                           /*!< Running count of pooled connections */
 	unsigned int idlecheck;              /*!< Recheck the connection if it is idle for this long */
 	struct ao2_container *obj_container;
 };
@@ -149,7 +149,7 @@
 
 	if (!chan && obj && obj->txf && obj->txf->owner) {
 		chan = obj->txf->owner;
-	} else {
+	} else if (!chan) {
 		/* No channel == no transaction */
 		return NULL;
 	}
@@ -955,7 +955,6 @@
 		}
 
 		if (!obj && (class->count < class->limit)) {
-			class->count++;
 			obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
 			if (!obj) {
 				ao2_ref(class, -1);
@@ -968,10 +967,10 @@
 				ast_log(LOG_WARNING, "Failed to connect to %s\n", name);
 				ao2_ref(obj, -1);
 				obj = NULL;
-				class->count--;
 			} else {
 				obj->used = 1;
 				ao2_link(class->obj_container, obj);
+				ast_atomic_fetchadd_int(&class->count, +1);
 			}
 		}
 	} else if (ast_test_flag(&flags, RES_ODBC_INDEPENDENT_CONNECTION)) {
@@ -987,7 +986,6 @@
 		}
 
 		if (!obj) {
-			class->count++;
 			obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
 			if (!obj) {
 				ao2_ref(class, -1);
@@ -1000,10 +998,10 @@
 				ast_log(LOG_WARNING, "Failed to connect to %s\n", name);
 				ao2_ref(obj, -1);
 				obj = NULL;
-				class->count--;
 			} else {
 				obj->used = 1;
 				ao2_link(class->obj_container, obj);
+				ast_atomic_fetchadd_int(&class->count, +1);
 			}
 		}
 	} else {
@@ -1055,10 +1053,46 @@
 	return obj;
 }
 
+#ifdef DEBUG_THREADS
+struct odbc_obj *_ast_odbc_request_obj(const char *name, int check, const char *file, const char *function, int lineno)
+#else
 struct odbc_obj *ast_odbc_request_obj(const char *name, int check)
+#endif
 {
 	struct ast_flags flags = { check ? RES_ODBC_SANITY_CHECK : 0 };
+#ifdef DEBUG_THREADS
+	return _ast_odbc_request_obj2(name, flags, file, function, lineno);
+#else
 	return ast_odbc_request_obj2(name, flags);
+#endif
+}
+
+struct odbc_obj *ast_odbc_retrieve_transaction_obj(struct ast_channel *chan, const char *objname)
+{
+	struct ast_datastore *txn_store;
+	AST_LIST_HEAD(, odbc_txn_frame) *oldlist;
+	struct odbc_txn_frame *txn = NULL;
+
+	if (!chan) {
+		/* No channel == no transaction */
+		return NULL;
+	}
+
+	if ((txn_store = ast_channel_datastore_find(chan, &txn_info, NULL))) {
+		oldlist = txn_store->data;
+	} else {
+		return NULL;
+	}
+
+	AST_LIST_LOCK(oldlist);
+	AST_LIST_TRAVERSE(oldlist, txn, list) {
+		if (txn->obj && txn->obj->parent && !strcmp(txn->obj->parent->name, objname)) {
+			AST_LIST_UNLOCK(oldlist);
+			return txn->obj;
+		}
+	}
+	AST_LIST_UNLOCK(oldlist);
+	return NULL;
 }
 
 static odbc_status odbc_obj_disconnect(struct odbc_obj *obj)




More information about the asterisk-commits mailing list