[asterisk-commits] murf: branch murf/bug11210 r103829 - in /team/murf/bug11210: channels/ main/ ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Feb 19 16:15:12 CST 2008


Author: murf
Date: Tue Feb 19 16:15:12 2008
New Revision: 103829

URL: http://svn.digium.com/view/asterisk?view=rev&rev=103829
Log:
A reorganization of the changes to astobj2.c; all funcs (debug & normal) will be present at all times. Common code to both is gathered into __ao2_xxx funcs, which reduces duplicated code, which is a better way to go. Made a mistake and spent a couple hours tracking it down. Tested. Looks good.

Modified:
    team/murf/bug11210/channels/chan_iax2.c
    team/murf/bug11210/main/astobj2.c
    team/murf/bug11210/utils/refcounter.c

Modified: team/murf/bug11210/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_iax2.c?view=diff&rev=103829&r1=103828&r2=103829
==============================================================================
--- team/murf/bug11210/channels/chan_iax2.c (original)
+++ team/murf/bug11210/channels/chan_iax2.c Tue Feb 19 16:15:12 2008
@@ -92,7 +92,7 @@
   might be crashes during the destruction of astobj2 objects, which could
   be a symptom of the object being destroyed multiple times.
 */
-/* #define  REF_DEBUG 1 */
+#define  REF_DEBUG 1
 #include "asterisk/astobj2.h"
 
 #include "iax2.h"

Modified: team/murf/bug11210/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/main/astobj2.c?view=diff&rev=103829&r1=103828&r2=103829
==============================================================================
--- team/murf/bug11210/main/astobj2.c (original)
+++ team/murf/bug11210/main/astobj2.c Tue Feb 19 16:15:12 2008
@@ -22,6 +22,9 @@
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/_private.h"
+/* make ALL functions available so if any file needs to use
+   the refcount debug tracing, it will be available. Turn
+   it off you want to save a little space */
 #define  REF_DEBUG 1
 #include "asterisk/astobj2.h"
 #include "asterisk/utils.h"
@@ -128,6 +131,18 @@
  */
 #define EXTERNAL_OBJ(_p)	((_p) == NULL ? NULL : (_p)->user_data)
 
+/* the underlying functions common to debug and non-debug versions */
+
+static int __ao2_ref(void *user_data, const int delta);
+static void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn);
+static struct ao2_container *__ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn,
+											ao2_callback_fn *cmp_fn);
+static struct bucket_list *__ao2_link(struct ao2_container *c, void *user_data);
+static void *__ao2_callback(struct ao2_container *c,
+	const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg,
+					 char *tag, char *file, int line, const char *funcname);
+static void * __ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q);
+
 int ao2_lock(void *user_data)
 {
 	struct astobj2 *p = INTERNAL_OBJ(user_data);
@@ -160,25 +175,39 @@
  * The argument is a pointer to the user portion.
  */
 
-#ifdef REF_DEBUG
-#define REF_FILE "/tmp/refs"
 
 int ao2_ref_debug(void *user_data, const int delta, char *tag, char *file, int line, const char *funcname)
 {
-	int current_value;
-	int ret;
 	struct astobj2 *obj = INTERNAL_OBJ(user_data);
 	
 	if (obj == NULL)
 		return -1;
 
 	if (delta != 0) {
-		
 		FILE *refo = fopen(REF_FILE,"a");
 		fprintf(refo, "%p %s%d   %s:%d:%s (%s) [@%d]\n", user_data, (delta<0? "":"+"), delta, file, line, funcname, tag, obj->priv_data.ref_counter);
 		fclose(refo);
 	}
-	
+	return __ao2_ref(user_data, delta);
+	
+}
+
+int ao2_ref(void *user_data, const int delta)
+{
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
+
+	if (obj == NULL)
+		return -1;
+
+	return __ao2_ref(user_data, delta);
+}
+
+static int __ao2_ref(void *user_data, const int delta)
+{
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
+	int current_value;
+	int ret;
+
 	/* if delta is 0, just return the refcount */
 	if (delta == 0)
 		return (obj->priv_data.ref_counter);
@@ -193,15 +222,12 @@
 
 	/* this case must never happen */
 	if (current_value < 0)
-		ast_log(LOG_ERROR, "refcount %d on object %p -- fix your code!\n", current_value, user_data);
-
-	if (current_value == 0) { /* last reference, destroy the object */
-		if (obj->priv_data.destructor_fn != NULL) {
-			FILE *refo = fopen(REF_FILE,"a");
-			fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);
-			fclose(refo);
+		ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
+
+	if (current_value <= 0) { /* last reference, destroy the object */
+		if (obj->priv_data.destructor_fn != NULL) 
 			obj->priv_data.destructor_fn(user_data);
-		}
+
 		ast_mutex_destroy(&obj->priv_data.lock);
 #ifdef AO2_DEBUG
 		ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
@@ -212,55 +238,6 @@
 		 * allocated. */
 		bzero(obj, sizeof(struct astobj2 *) + sizeof(void *) );
 		free(obj);
-	} else if (current_value < 0) {
-		FILE *refo = fopen(REF_FILE,"a");
-		fprintf(refo, "%p **Refcount 0 or less** [%d]  %s:%d:%s (%s)\n", user_data, current_value, file, line, funcname, tag);
-		fclose(refo);
-	}
-	return ret;
-}
-
-#endif
-
-int ao2_ref(void *user_data, const int delta)
-{
-	int current_value;
-	int ret;
-	struct astobj2 *obj = INTERNAL_OBJ(user_data);
-
-	if (obj == NULL)
-		return -1;
-
-	/* if delta is 0, just return the refcount */
-	if (delta == 0)
-		return (obj->priv_data.ref_counter);
-
-	/* we modify with an atomic operation the reference counter */
-	ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
-	current_value = ret + delta;
-
-#ifdef AO2_DEBUG	
-	ast_atomic_fetchadd_int(&ao2.total_refs, delta);
-#endif
-
-	/* this case must never happen */
-	if (current_value < 0)
-		ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
-
-	if (current_value <= 0) { /* last reference, destroy the object */
-		if (obj->priv_data.destructor_fn != NULL) 
-			obj->priv_data.destructor_fn(user_data);
-
-		ast_mutex_destroy(&obj->priv_data.lock);
-#ifdef AO2_DEBUG
-		ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
-		ast_atomic_fetchadd_int(&ao2.total_objects, -1);
-#endif
-		/* for safety, zero-out the astobj2 header and also the
-		 * first word of the user-data, which we make sure is always
-		 * allocated. */
-		bzero(obj, sizeof(struct astobj2 *) + sizeof(void *) );
-		free(obj);
 	}
 
 	return ret;
@@ -270,12 +247,10 @@
  * We always alloc at least the size of a void *,
  * for debugging purposes.
  */
-#ifdef REF_DEBUG
-void *ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, char *tag, char *file, int line, const char *funcname)
+static void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
 {
 	/* allocation */
 	struct astobj2 *obj;
-	FILE *refo = fopen(REF_FILE,"a");
 
 	if (data_size < sizeof(void *))
 		data_size = sizeof(void *);
@@ -284,9 +259,6 @@
 
 	if (obj == NULL)
 		return NULL;
-
-	fprintf(refo, "%p =1   %s:%d:%s (%s)\n", EXTERNAL_OBJ(obj), file, line, funcname, tag);
-	fclose(refo);
 
 	ast_mutex_init(&obj->priv_data.lock);
 	obj->priv_data.magic = AO2_MAGIC;
@@ -303,36 +275,32 @@
 	/* return a pointer to the user data */
 	return EXTERNAL_OBJ(obj);
 }
-#endif
+
+void *ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, char *tag, char *file, int line, const char *funcname)
+{
+	/* allocation */
+	void *obj;
+	FILE *refo = fopen(REF_FILE,"a");
+
+	obj = __ao2_alloc(data_size, destructor_fn);
+
+	if (obj == NULL)
+		return NULL;
+	
+	if (refo) {
+		fprintf(refo, "%p =1   %s:%d:%s (%s)\n", obj, file, line, funcname, tag);
+		fclose(refo);
+	}
+
+	/* return a pointer to the user data */
+	return obj;
+}
 
 void *ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn)
 {
-	/* allocation */
-	struct astobj2 *obj;
-
-	if (data_size < sizeof(void *))
-		data_size = sizeof(void *);
-
-	obj = ast_calloc(1, sizeof(*obj) + data_size);
-
-	if (obj == NULL)
-		return NULL;
-
-	ast_mutex_init(&obj->priv_data.lock);
-	obj->priv_data.magic = AO2_MAGIC;
-	obj->priv_data.data_size = data_size;
-	obj->priv_data.ref_counter = 1;
-	obj->priv_data.destructor_fn = destructor_fn;	/* can be NULL */
-
-#ifdef AO2_DEBUG
-	ast_atomic_fetchadd_int(&ao2.total_objects, 1);
-	ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
-	ast_atomic_fetchadd_int(&ao2.total_refs, 1);
-#endif
-
-	/* return a pointer to the user data */
-	return EXTERNAL_OBJ(obj);
-}
+	return __ao2_alloc(data_size, destructor_fn);
+}
+
 
 /* internal callback to destroy a container. */
 static void container_destruct(void *c);
@@ -394,30 +362,37 @@
 /*
  * A container is just an object, after all!
  */
-#ifdef REF_DEBUG
-struct ao2_container *
-ao2_container_alloc_debug(const uint n_buckets, ao2_hash_fn *hash_fn,
+static struct ao2_container *__ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn,
+											ao2_callback_fn *cmp_fn)
+{
+	/* XXX maybe consistency check on arguments ? */
+	/* compute the container size */
+
+	if (!c)
+		return NULL;
+	
+	c->version = 1;	/* 0 is a reserved value here */
+	c->n_buckets = n_buckets;
+	c->hash_fn = hash_fn ? hash_fn : hash_zero;
+	c->cmp_fn = cmp_fn;
+
+#ifdef AO2_DEBUG
+	ast_atomic_fetchadd_int(&ao2.total_containers, 1);
+#endif
+
+	return c;
+}
+
+struct ao2_container *ao2_container_alloc_debug(const uint n_buckets, ao2_hash_fn *hash_fn,
 		ao2_callback_fn *cmp_fn, char *tag, char *file, int line, const char *funcname)
 {
 	/* XXX maybe consistency check on arguments ? */
 	/* compute the container size */
 	size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
 	struct ao2_container *c = ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname);
-	if (!c)
-		return NULL;
-	
-	c->version = 1;	/* 0 is a reserved value here */
-	c->n_buckets = n_buckets;
-	c->hash_fn = hash_fn ? hash_fn : hash_zero;
-	c->cmp_fn = cmp_fn;
-
-#ifdef AO2_DEBUG
-	ast_atomic_fetchadd_int(&ao2.total_containers, 1);
-#endif
-
-	return c;
-}
-#endif
+
+	return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
+}
 
 struct ao2_container *
 ao2_container_alloc(const uint n_buckets, ao2_hash_fn *hash_fn,
@@ -425,21 +400,11 @@
 {
 	/* XXX maybe consistency check on arguments ? */
 	/* compute the container size */
+
 	size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket);
 	struct ao2_container *c = ao2_alloc(container_size, container_destruct);
-	if (!c)
-		return NULL;
-	
-	c->version = 1;	/* 0 is a reserved value here */
-	c->n_buckets = n_buckets;
-	c->hash_fn = hash_fn ? hash_fn : hash_zero;
-	c->cmp_fn = cmp_fn;
-
-#ifdef AO2_DEBUG
-	ast_atomic_fetchadd_int(&ao2.total_containers, 1);
-#endif
-
-	return c;
+
+	return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn);
 }
 
 /*!
@@ -461,11 +426,11 @@
 	struct astobj2 *astobj;		/* pointer to internal data */
 }; 
 
-#ifdef REF_DEBUG
 /*
  * link an object to a container
  */
-void *ao2_link_debug(struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
+
+static struct bucket_list *__ao2_link(struct ao2_container *c, void *user_data)
 {
 	int i;
 	/* create a new list entry */
@@ -490,44 +455,30 @@
 	p->version = ast_atomic_fetchadd_int(&c->version, 1);
 	AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
 	ast_atomic_fetchadd_int(&c->elements, 1);
-	ao2_ref_debug(user_data, +1, tag, file, line, funcname);
-	ao2_unlock(c);
-	
+
+	/* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
 	return p;
 }
-#endif
-
-/*
- * link an object to a container
- */
+
+void *ao2_link_debug(struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
+{
+	struct bucket_list *p = __ao2_link(c, user_data);
+	
+	if (p) {
+		ao2_ref_debug(user_data, +1, tag, file, line, funcname);
+		ao2_unlock(c);
+	}
+	return p;
+}
+
 void *ao2_link(struct ao2_container *c, void *user_data)
 {
-	int i;
-	/* create a new list entry */
-	struct bucket_list *p;
-	struct astobj2 *obj = INTERNAL_OBJ(user_data);
-	
-	if (!obj)
-		return NULL;
-
-	if (INTERNAL_OBJ(c) == NULL)
-		return NULL;
-
-	p = ast_calloc(1, sizeof(*p));
-	if (!p)
-		return NULL;
-
-	i = c->hash_fn(user_data, OBJ_POINTER);
-
-	ao2_lock(c);
-	i %= c->n_buckets;
-	p->astobj = obj;
-	p->version = ast_atomic_fetchadd_int(&c->version, 1);
-	AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
-	ast_atomic_fetchadd_int(&c->elements, 1);
-	ao2_ref(user_data, +1);
-	ao2_unlock(c);
-	
+	struct bucket_list *p = __ao2_link(c, user_data);
+	
+	if (p) {
+		ao2_ref(user_data, +1);
+		ao2_unlock(c);
+	}
 	return p;
 }
 
@@ -543,7 +494,6 @@
  * Unlink an object from the container
  * and destroy the associated * ao2_bucket_list structure.
  */
-#ifdef REF_DEBUG
 void *ao2_unlink_debug(struct ao2_container *c, void *user_data, char *tag,
 					   char *file, int line, const char *funcname)
 {
@@ -554,7 +504,6 @@
 
 	return NULL;
 }
-#endif
 
 void *ao2_unlink(struct ao2_container *c, void *user_data)
 {
@@ -579,12 +528,13 @@
  * Browse the container using different stategies accoding the flags.
  * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is 
  * specified.
- */
-#ifdef REF_DEBUG
-void *ao2_callback_debug(struct ao2_container *c,
-						 const enum search_flags flags,
-						 ao2_callback_fn *cb_fn, void *arg, 
-						 char *tag, char *file, int line, const char *funcname)
+ * Luckily, for debug purposes, the added args (tag, file, line, funcname)
+ * aren't an excessive load to the system, as the callback should not be
+ * called as often as, say, the ao2_ref func is called.
+ */
+static void *__ao2_callback(struct ao2_container *c,
+	const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg,
+	char *tag, char *file, int line, const char *funcname)
 {
 	int i, last;	/* search boundaries */
 	void *ret = NULL;
@@ -639,7 +589,10 @@
 			if (!(flags & OBJ_NODATA)) {	/* if must return the object, record the value */
 				/* it is important to handle this case before the unlink */
 				ret = EXTERNAL_OBJ(cur->astobj);
-				ao2_ref_debug(ret, 1, tag, file, line, funcname);
+				if (tag)
+					ao2_ref_debug(ret, 1, tag, file, line, funcname);
+				else
+					ao2_ref(ret, 1);
 			}
 
 			if (flags & OBJ_UNLINK) {	/* must unlink */
@@ -650,7 +603,10 @@
 				AST_LIST_REMOVE_CURRENT(entry);
 				/* update number of elements and version */
 				ast_atomic_fetchadd_int(&c->elements, -1);
-				ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
+				if (tag)
+					ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
+				else
+					ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
 				free(x);	/* free the link record */
 			}
 
@@ -673,109 +629,29 @@
 	ao2_unlock(c);
 	return ret;
 }
-#endif
+
+void *ao2_callback_debug(struct ao2_container *c,
+						 const enum search_flags flags,
+						 ao2_callback_fn *cb_fn, void *arg, 
+						 char *tag, char *file, int line, const char *funcname)
+{
+	return __ao2_callback(c,flags, cb_fn, arg, tag, file, line, funcname);
+}
 
 void *ao2_callback(struct ao2_container *c,
 	const enum search_flags flags,
 	ao2_callback_fn *cb_fn, void *arg)
 {
-	int i, last;	/* search boundaries */
-	void *ret = NULL;
-
-	if (INTERNAL_OBJ(c) == NULL)	/* safety check on the argument */
-		return NULL;
-
-	if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
-		ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags);
-		return NULL;
-	}
-
-	/* override the match function if necessary */
-	if (cb_fn == NULL)	/* if NULL, match everything */
-		cb_fn = cb_true;
-	/*
-	 * XXX this can be optimized.
-	 * If we have a hash function and lookup by pointer,
-	 * run the hash function. Otherwise, scan the whole container
-	 * (this only for the time being. We need to optimize this.)
-	 */
-	if ((flags & OBJ_POINTER))	/* we know hash can handle this case */
-		i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
-	else			/* don't know, let's scan all buckets */
-		i = -1;		/* XXX this must be fixed later. */
-
-	/* determine the search boundaries: i..last-1 */
-	if (i < 0) {
-		i = 0;
-		last = c->n_buckets;
-	} else {
-		last = i + 1;
-	}
-
-	ao2_lock(c);	/* avoid modifications to the content */
-
-	for (; i < last ; i++) {
-		/* scan the list with prev-cur pointers */
-		struct bucket_list *cur;
-
-		AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
-			int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP);
-
-			/* we found the object, performing operations according flags */
-			if (match == 0) {	/* no match, no stop, continue */
-				continue;
-			} else if (match == CMP_STOP) {	/* no match but stop, we are done */
-				i = last;
-				break;
-			}
-			/* we have a match (CMP_MATCH) here */
-			if (!(flags & OBJ_NODATA)) {	/* if must return the object, record the value */
-				/* it is important to handle this case before the unlink */
-				ret = EXTERNAL_OBJ(cur->astobj);
-				ao2_ref(ret, 1);
-			}
-
-			if (flags & OBJ_UNLINK) {	/* must unlink */
-				struct bucket_list *x = cur;
-
-				/* we are going to modify the container, so update version */
-				ast_atomic_fetchadd_int(&c->version, 1);
-				AST_LIST_REMOVE_CURRENT(entry);
-				/* update number of elements and version */
-				ast_atomic_fetchadd_int(&c->elements, -1);
-				ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
-				free(x);	/* free the link record */
-			}
-
-			if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) {
-				/* We found the only match we need */
-				i = last;	/* force exit from outer loop */
-				break;
-			}
-			if (!(flags & OBJ_NODATA)) {
-#if 0	/* XXX to be completed */
-				/*
-				 * This is the multiple-return case. We need to link
-				 * the object in a list. The refcount is already increased.
-				 */
-#endif
-			}
-		}
-		AST_LIST_TRAVERSE_SAFE_END;
-	}
-	ao2_unlock(c);
-	return ret;
+	return __ao2_callback(c,flags, cb_fn, arg, NULL, NULL, 0, NULL);
 }
 
 /*!
  * the find function just invokes the default callback with some reasonable flags.
  */
-#ifdef REF_DEBUG
 void *ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
 {
 	return ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
 }
-#endif
 
 void *ao2_find(struct ao2_container *c, void *arg, enum search_flags flags)
 {
@@ -798,13 +674,14 @@
 /*
  * move to the next element in the container.
  */
-#ifdef REF_DEBUG
-void * ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
+static void * __ao2_iterator_next(struct ao2_iterator *a, struct bucket_list **q)
 {
 	int lim;
 	struct bucket_list *p = NULL;
 	void *ret = NULL;
 
+	*q = NULL;
+	
 	if (INTERNAL_OBJ(a->c) == NULL)
 		return NULL;
 
@@ -846,6 +723,21 @@
 		a->c_version = a->c->version;
 		ret = EXTERNAL_OBJ(p->astobj);
 		/* inc refcount of returned object */
+		*q = p;
+	}
+
+	return ret;
+}
+
+void * ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
+{
+	struct bucket_list *p;
+	void *ret = NULL;
+
+	ret = __ao2_iterator_next(a, &p);
+	
+	if (p) {
+		/* inc refcount of returned object */
 		ao2_ref_debug(ret, 1, tag, file, line, funcname);
 	}
 
@@ -854,54 +746,15 @@
 
 	return ret;
 }
-#endif
 
 void * ao2_iterator_next(struct ao2_iterator *a)
 {
-	int lim;
 	struct bucket_list *p = NULL;
 	void *ret = NULL;
 
-	if (INTERNAL_OBJ(a->c) == NULL)
-		return NULL;
-
-	if (!(a->flags & F_AO2I_DONTLOCK))
-		ao2_lock(a->c);
-
-	/* optimization. If the container is unchanged and
-	 * we have a pointer, try follow it
-	 */
-	if (a->c->version == a->c_version && (p = a->obj) ) {
-		if ( (p = AST_LIST_NEXT(p, entry)) )
-			goto found;
-		/* nope, start from the next bucket */
-		a->bucket++;
-		a->version = 0;
-		a->obj = NULL;
-	}
-
-	lim = a->c->n_buckets;
-
-	/* Browse the buckets array, moving to the next
-	 * buckets if we don't find the entry in the current one.
-	 * Stop when we find an element with version number greater
-	 * than the current one (we reset the version to 0 when we
-	 * switch buckets).
-	 */
-	for (; a->bucket < lim; a->bucket++, a->version = 0) {
-		/* scan the current bucket */
-		AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
-			if (p->version > a->version)
-				goto found;
-		}
-	}
-
-found:
+	ret = __ao2_iterator_next(a, &p);
+	
 	if (p) {
-		a->version = p->version;
-		a->obj = p;
-		a->c_version = a->c->version;
-		ret = EXTERNAL_OBJ(p->astobj);
 		/* inc refcount of returned object */
 		ao2_ref(ret, 1);
 	}

Modified: team/murf/bug11210/utils/refcounter.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/utils/refcounter.c?view=diff&rev=103829&r1=103828&r2=103829
==============================================================================
--- team/murf/bug11210/utils/refcounter.c (original)
+++ team/murf/bug11210/utils/refcounter.c Tue Feb 19 16:15:12 2008
@@ -229,6 +229,13 @@
 
 }
 
+#undef ast_mark
+
+int64_t ast_mark(int x, int start1_stop0)
+{
+	return 0;
+}
+
 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
 {
 	va_list vars;




More information about the asterisk-commits mailing list