[asterisk-commits] tilghman: branch tilghman/odbc_tx_support r166381 - /team/tilghman/odbc_tx_su...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Dec 22 15:04:53 CST 2008


Author: tilghman
Date: Mon Dec 22 15:04:52 2008
New Revision: 166381

URL: http://svn.digium.com/view/asterisk?view=rev&rev=166381
Log:
Address several of Russell's concerns

Modified:
    team/tilghman/odbc_tx_support/res/res_odbc.c

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=166381&r1=166380&r2=166381
==============================================================================
--- team/tilghman/odbc_tx_support/res/res_odbc.c (original)
+++ team/tilghman/odbc_tx_support/res/res_odbc.c Mon Dec 22 15:04:52 2008
@@ -160,18 +160,21 @@
 		return NULL;
 	}
 
+	ast_channel_lock(chan);
 	if ((txn_store = ast_channel_datastore_find(chan, &txn_info, NULL))) {
 		oldlist = txn_store->data;
 	} else {
 		/* Need to create a new datastore */
 		if (!(txn_store = ast_datastore_alloc(&txn_info, NULL))) {
 			ast_log(LOG_ERROR, "Unable to allocate a new datastore.  Cannot create a new transaction.\n");
+			ast_channel_unlock(chan);
 			return NULL;
 		}
 
 		if (!(oldlist = ast_calloc(1, sizeof(*oldlist)))) {
 			ast_log(LOG_ERROR, "Unable to allocate datastore list head.  Cannot create a new transaction.\n");
 			ast_datastore_free(txn_store);
+			ast_channel_unlock(chan);
 			return NULL;
 		}
 
@@ -181,6 +184,7 @@
 	}
 
 	AST_LIST_LOCK(oldlist);
+	ast_channel_unlock(chan);
 
 	/* Scanning for an object is *fast*.  Scanning for a name is much slower. */
 	if (obj != NULL || active == 1) {
@@ -1027,6 +1031,33 @@
 	return 0;
 }
 
+static int aoro2_class_cb(void *obj, void *arg, int flags)
+{
+	struct odbc_class *class = obj;
+	char *name = arg;
+	if (!strcmp(class->name, name) && !class->delme) {
+		return CMP_MATCH | CMP_STOP;
+	}
+	return 0;
+}
+
+#define USE_TX (void *)(long)1
+#define NO_TX  (void *)(long)2
+#define EOR_TX (void *)(long)3
+
+static int aoro2_obj_cb(void *vobj, void *arg, int flags)
+{
+	struct odbc_obj *obj = vobj;
+	ast_mutex_lock(&obj->lock);
+	if ((arg == NO_TX && !obj->tx) || (arg == EOR_TX && !obj->used) || (arg == USE_TX && obj->tx && !obj->used)) {
+		obj->used = 1;
+		ast_mutex_unlock(&obj->lock);
+		return CMP_MATCH | CMP_STOP;
+	}
+	ast_mutex_unlock(&obj->lock);
+	return 0;
+}
+
 #ifdef DEBUG_THREADS
 struct odbc_obj *_ast_odbc_request_obj2(const char *name, struct ast_flags flags, const char *file, const char *function, int lineno)
 #else
@@ -1035,33 +1066,17 @@
 {
 	struct odbc_obj *obj = NULL;
 	struct odbc_class *class;
-	struct ao2_iterator aoi = ao2_iterator_init(class_container, 0);
 	SQLINTEGER nativeerror=0, numfields=0;
 	SQLSMALLINT diagbytes=0, i;
 	unsigned char state[10], diagnostic[256];
 
-	while ((class = ao2_iterator_next(&aoi))) {
-		if (!strcmp(class->name, name) && !class->delme) {
-			break;
-		}
-		ao2_ref(class, -1);
-	}
-
-	if (!class)
+	if (!(class = ao2_callback(class_container, 0, aoro2_class_cb, (char *) name))) {
 		return NULL;
+	}
 
 	if (class->haspool) {
 		/* Recycle connections before building another */
-		aoi = ao2_iterator_init(class->obj_container, 0);
-		while ((obj = ao2_iterator_next(&aoi))) {
-			if (! obj->used) {
-				ast_mutex_lock(&obj->lock);
-				obj->used = 1;
-				ast_mutex_unlock(&obj->lock);
-				break;
-			}
-			ao2_ref(obj, -1);
-		}
+		obj = ao2_callback(class->obj_container, 0, aoro2_obj_cb, EOR_TX);
 
 		if (!obj && (class->count < class->limit)) {
 			obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
@@ -1104,17 +1119,7 @@
 		}
 	} else if (ast_test_flag(&flags, RES_ODBC_INDEPENDENT_CONNECTION)) {
 		/* Non-pooled connections -- but must use a separate connection handle */
-		aoi = ao2_iterator_init(class->obj_container, 0);
-		while ((obj = ao2_iterator_next(&aoi))) {
-			if (obj->tx && !obj->used) {
-				/* Transactional connection */
-				obj->used++;
-				break;
-			}
-			ao2_ref(obj, -1);
-		}
-
-		if (!obj) {
+		if (!(obj = ao2_callback(class->obj_container, 0, aoro2_obj_cb, USE_TX))) {
 			obj = ao2_alloc(sizeof(*obj), odbc_obj_destructor);
 			if (!obj) {
 				ao2_ref(class, -1);
@@ -1147,18 +1152,7 @@
 		}
 	} else {
 		/* Non-pooled connection: multiple modules can use the same connection. */
-		aoi = ao2_iterator_init(class->obj_container, 0);
-		while ((obj = ao2_iterator_next(&aoi))) {
-			if (obj->tx) {
-				/* Transactional connection; do not return */
-				ao2_ref(obj, -1);
-				continue;
-			}
-			/* Non-pooled connection: if there is an entry, return it */
-			break;
-		}
-
-		if (obj) {
+		if (!(obj = ao2_callback(class->obj_container, 0, aoro2_obj_cb, NO_TX))) {
 			/* Object is not constructed, so delete outstanding reference to class. */
 			ao2_ref(class, -1);
 			class = NULL;
@@ -1250,13 +1244,17 @@
 		return NULL;
 	}
 
+	ast_channel_lock(chan);
 	if ((txn_store = ast_channel_datastore_find(chan, &txn_info, NULL))) {
 		oldlist = txn_store->data;
 	} else {
+		ast_channel_unlock(chan);
 		return NULL;
 	}
 
 	AST_LIST_LOCK(oldlist);
+	ast_channel_unlock(chan);
+
 	AST_LIST_TRAVERSE(oldlist, txn, list) {
 		if (txn->obj && txn->obj->parent && !strcmp(txn->obj->parent->name, objname)) {
 			AST_LIST_UNLOCK(oldlist);




More information about the asterisk-commits mailing list