[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