[asterisk-commits] murf: branch murf/bug11210 r91889 - in /team/murf/bug11210: apps/ channels/ f...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Dec 7 17:00:44 CST 2007


Author: murf
Date: Fri Dec  7 17:00:43 2007
New Revision: 91889

URL: http://svn.digium.com/view/asterisk?view=rev&rev=91889
Log:
OK, a good checkpoint. Every object that is created, gets destroyed. (plus a few get mult. destroys now). The ast_sched_ stuff is the secret.

Modified:
    team/murf/bug11210/apps/app_queue.c
    team/murf/bug11210/channels/chan_iax2.c
    team/murf/bug11210/channels/chan_sip.c
    team/murf/bug11210/funcs/func_dialgroup.c
    team/murf/bug11210/include/asterisk/astobj2.h
    team/murf/bug11210/main/astobj2.c
    team/murf/bug11210/main/config.c
    team/murf/bug11210/main/manager.c
    team/murf/bug11210/utils/hashtest2.c

Modified: team/murf/bug11210/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/apps/app_queue.c?view=diff&rev=91889&r1=91888&r2=91889
==============================================================================
--- team/murf/bug11210/apps/app_queue.c (original)
+++ team/murf/bug11210/apps/app_queue.c Fri Dec  7 17:00:43 2007
@@ -107,6 +107,8 @@
                                                  char *file, int line, const char *funcname);
 #define ao2_find(arg1,arg2,arg3) ao2_find_debug((arg1), (arg2), (arg3), "app_queue",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 void *ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname);
+#define ao2_iterator_next(arg1) ao2_iterator_next_debug((arg1), "app_queue",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+void *ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
 
 enum {
 	QUEUE_STRATEGY_RINGALL = 0,

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=91889&r1=91888&r2=91889
==============================================================================
--- team/murf/bug11210/channels/chan_iax2.c (original)
+++ team/murf/bug11210/channels/chan_iax2.c Fri Dec  7 17:00:43 2007
@@ -97,8 +97,11 @@
 void *ao2_alloc_debug(const size_t data_size, ao2_destructor_fn destructor_fn, char *tag, char *file, int line, const char *funcname);
 #define ao2_container_alloc(arg1,arg2,arg3) ao2_container_alloc_debug((arg1), (arg2), (arg3), "IAX",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 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);
+												ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
+												char *tag, char *file, int line, const char *funcname);
+#define ao2_iterator_next(arg1) ao2_iterator_next_debug((arg1), "IAX",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+void *ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
+
 #define ao2_callback(arg1,arg2,arg3,arg4) ao2_callback_debug((arg1), (arg2), (arg3), (arg4), "IAX",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 void *ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
                                                  ao2_callback_fn *cb_fn, void *arg, char *tag,

Modified: team/murf/bug11210/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_sip.c?view=diff&rev=91889&r1=91888&r2=91889
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Fri Dec  7 17:00:43 2007
@@ -1203,6 +1203,25 @@
  * functions so we keep track of the refcounts.
  * To simplify the code, we allow a NULL to be passed to dialog_unref().
  */
+#ifdef REF_DEBUG
+#define dialog_ref(arg1,arg2) dialog_ref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define dialog_unref(arg1,arg2) dialog_unref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+static struct sip_pvt *dialog_ref_debug(struct sip_pvt *p, char *tag, char *file, int line, const char *func)
+{
+	if (p)
+		ao2_ref_debug(p,1,tag,file,line,func);
+	else
+		ast_log(LOG_ERROR,"Attempt to Ref a null pointer\n");
+	return p;
+}
+
+static struct sip_pvt *dialog_unref_debug(struct sip_pvt *p, char *tag, char *file, int line, const char *func)
+{
+	if (p)
+		ao2_ref_debug(p,-1, tag, file, line, func);
+	return NULL;
+}
+#else
 static struct sip_pvt *dialog_ref(struct sip_pvt *p, char *tag)
 {
 	if (p)
@@ -1218,6 +1237,7 @@
 		ao2_ref(p,-1, tag);
 	return NULL;
 }
+#endif
 
 /*! \brief sip packet - raw format for outbound packets that are sent or scheduled for transmission
  * Packets are linked in a list, whose head is in the struct sip_pvt they belong to.
@@ -1453,6 +1473,8 @@
 {
 	struct sip_peer *peer = obj, *peer2 = arg;
 
+	ast_log(LOG_NOTICE,"peer %s == peer %s ? %d\n", peer->name, peer2->name, !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0);
+	
 	return !strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0;
 }
 
@@ -1475,6 +1497,11 @@
 static int peer_ipcmp_cb(void *obj, void *arg, int flags)
 {
 	struct sip_peer *peer = obj, *peer2 = arg;
+
+	ast_log(LOG_NOTICE,"peerip %d/%d (ins:%d) == peerip %d/%d (ins:%d) ? %d\n", 
+			peer->addr.sin_addr.s_addr, peer->addr.sin_port, ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT),
+			peer2->addr.sin_addr.s_addr, peer2->addr.sin_port, ast_test_flag(&peer2->flags[0], SIP_INSECURE_PORT),
+			!strcasecmp(peer->name, peer2->name) ? CMP_MATCH : 0);
 	
 	if (peer->addr.sin_addr.s_addr != peer2->addr.sin_addr.s_addr)
 		return 0;
@@ -1505,6 +1532,7 @@
 {
 	struct sip_user *user = obj, *user2 = arg;
 
+	ast_log(LOG_NOTICE,"user %s == user %s ? %d\n", user->name, user2->name, !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0);
 	return !strcasecmp(user->name, user2->name) ? CMP_MATCH : 0;
 }
 
@@ -1524,7 +1552,7 @@
 static int dialog_cmp_cb(void *obj, void *arg, int flags)
 {
 	struct sip_pvt *pvt = obj, *pvt2 = arg;
-	ast_log(LOG_NOTICE,"obj %s == obj %s ? %d\n", pvt->callid, pvt2->callid, !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH : 0);
+	ast_log(LOG_NOTICE,"dialog %s == obj %s ? %d\n", pvt->callid, pvt2->callid, !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH : 0);
 	return !strcasecmp(pvt->callid, pvt2->callid) ? CMP_MATCH : 0;
 }
 
@@ -2044,6 +2072,14 @@
 	return NULL;
 }
 
+static struct sip_peer *ref_peer(struct sip_peer *peer, char *tag)
+{
+	int rc = ao2_ref(peer,1,tag);
+	ast_log(LOG_NOTICE,"Ref peer %s prev refcount=%d\n", peer->name, rc);
+	return peer;
+}
+
+
 static void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglist)
 {
 	int rc = ao2_ref(dialog,0, "");
@@ -2055,10 +2091,10 @@
 	ast_log(LOG_NOTICE,"Unlink dialog %s prev refcount=%d\n", dialog->callid, rc);
 	if (dialog->registry) {
 		if (dialog->registry->call == dialog)
-			dialog->registry->call = NULL;
+			dialog->registry->call = dialog_unref(dialog->registry->call,"nulling out the registry's call dialog field in unlink_all");
 		dialog->registry = registry_unref(dialog->registry, "delete dialog->registry");
 	}
-	/* Unlink us from the owner if we have one */
+	/* Unlink us from the owner (channel) if we have one */
 	if (dialog->owner) {
 		if (lockowner)
 			ast_channel_lock(dialog->owner);
@@ -2076,6 +2112,19 @@
 	else
 	dialog_unref(x,"remove result of ao2_find");
 	*/
+
+	if (dialog->initid > -1) {
+		ast_sched_del(sched, dialog->initid);
+		dialog_unref(dialog,"when you delete the initid sched, you should dec the refcount for the stored dialog ptr");
+		dialog->initid = -1;
+	}
+	
+	if (dialog->autokillid > -1) {
+		ast_sched_del(sched, dialog->autokillid);
+		dialog_unref(dialog,"when you delete the autokillid sched, you should dec the refcount for the stored dialog ptr");
+		dialog->autokillid = -1;
+	}
+
 	rc = ao2_ref(dialog,0,"");
 	ast_log(LOG_NOTICE,"Unlink dialog %s prev refcount=%d\n", dialog->callid, rc);
 	return NULL;
@@ -3753,7 +3802,7 @@
 		}
 	}
 	sip_pvt_unlock(p);
-	dialog_unref(p,"unreffing arg passed into auto_conget -- is this right?");
+	dialog_unref(p,"unreffing arg passed into auto_congest callback");
 	return 0;
 }
 
@@ -3841,7 +3890,7 @@
 	
 		/* Initialize auto-congest time */
 		p->initid = ast_sched_replace(p->initid, sched, SIP_TRANS_TIMEOUT, 
-									  auto_congest, dialog_ref(p, "sip_call: bumping refcount as calling ast_sched_replace"));
+									  auto_congest, dialog_ref(p,"this is a pointer for the autocongest callback to use"));
 	}
 
 	return res;
@@ -3898,10 +3947,6 @@
 
 	if (p->stateid > -1)
 		ast_extension_state_del(p->stateid, NULL);
-	if (p->initid > -1)
-		ast_sched_del(sched, p->initid);
-	if (p->autokillid > -1)
-		ast_sched_del(sched, p->autokillid);
 
 	if (p->rtp)
 		ast_rtp_destroy(p->rtp);
@@ -3934,7 +3979,7 @@
 		p->packets = p->packets->next;
 		if (cp->retransid > -1)
 			ast_sched_del(sched, cp->retransid);
-		dialog_unref(cp->owner,"free cp->owner dialog before freeing the pkt");
+		cp->owner = dialog_unref(cp->owner,"free cp->owner dialog before freeing the pkt");
 		ast_free(cp);
 	}
 	if (p->chanvars) {
@@ -5239,7 +5284,7 @@
 		return NULL;
 
 	if (ast_string_field_init(p, 512)) {
-		ast_free(p);
+		ao2_ref(p,-1,"failed to string_field_init, drop p");
 		return NULL;
 	}
 
@@ -5291,7 +5336,7 @@
 				ast_variables_destroy(p->chanvars);
 				p->chanvars = NULL;
 			}
-			ast_free(p);
+			ao2_ref(p,-1,"failed to create RTP audio session, drop p");
 			return NULL;
 		}
 		ast_rtp_setqos(p->rtp, global_tos_audio, global_cos_audio);
@@ -5507,7 +5552,7 @@
 	if (intended_method == SIP_RESPONSE)
 		ast_debug(2, "That's odd...  Got a response on a call we dont know about. Callid %s\n", callid ? callid : "<unknown>");
 
-	return p;
+	return p; /* most likely null if returning here */
 }
 
 /*! \brief Parse register=> line in sip.conf and add to registry */
@@ -7754,7 +7799,8 @@
 static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version)
 {
 	struct sip_request req;
-
+	int res;
+	
 	reqprep(&req, p, ast_test_flag(&p->flags[0], SIP_REINVITE_UPDATE) ?  SIP_UPDATE : SIP_INVITE, 0, 1);
 	
 	add_header(&req, "Allow", ALLOWED_METHODS);
@@ -7771,7 +7817,8 @@
 	initialize_initreq(p, &req);
 	p->lastinvite = p->ocseq;
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);		/* Change direction of this dialog */
-	return send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+	res = send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+	return res;
 }
 
 /* \brief Remove URI parameters at end of URI, not in username part though */
@@ -8035,6 +8082,7 @@
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
 {
 	struct sip_request req;
+	int res;
 	
 	req.method = sipmethod;
 	if (init) {/* Bump branch even on initial requests */
@@ -8123,7 +8171,8 @@
 	if (!p->initreq.headers)
 		initialize_initreq(p, &req);
 	p->lastinvite = p->ocseq;
-	return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq);
+	return res;
 }
 
 /*! \brief Used in the SUBSCRIBE notification subsystem */
@@ -8139,7 +8188,8 @@
 	enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN;
 	char *pidfstate = "--";
 	char *pidfnote= "Ready";
-
+	int res;
+	
 	memset(from, 0, sizeof(from));
 	memset(to, 0, sizeof(to));
 
@@ -8304,7 +8354,8 @@
 	add_header_contentLength(&req, tmp->used);
 	add_line(&req, tmp->str);
 
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	return res;
 }
 
 /*! \brief Notify user of messages waiting in voicemail
@@ -8317,7 +8368,8 @@
 {
 	struct sip_request req;
 	struct ast_str *out = ast_str_alloca(500);
-
+	int res;
+	
 	initreqprep(&req, p, SIP_NOTIFY);
 	add_header(&req, "Event", "message-summary");
 	add_header(&req, "Content-Type", default_notifymime);
@@ -8343,15 +8395,18 @@
 
 	if (!p->initreq.headers) 
 		initialize_initreq(p, &req);
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	return res;
 }
 
 /*! \brief Transmit SIP request unreliably (only used in sip_notify subsystem) */
 static int transmit_sip_request(struct sip_pvt *p, struct sip_request *req)
 {
+	int res;
 	if (!p->initreq.headers) 	/* Initialize first request before sending */
 		initialize_initreq(p, req);
-	return send_request(p, req, XMIT_UNRELIABLE, p->ocseq);
+	res = send_request(p, req, XMIT_UNRELIABLE, p->ocseq);
+	return res;
 }
 
 /*! \brief Notify a transferring party of the status of transfer */
@@ -8359,7 +8414,8 @@
 {
 	struct sip_request req;
 	char tmp[BUFSIZ/2];
-
+	int res;
+	
 	reqprep(&req, p, SIP_NOTIFY, 0, 1);
 	snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq);
 	add_header(&req, "Event", tmp);
@@ -8377,7 +8433,8 @@
 
 	p->lastnoninvite = p->ocseq;
 
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	return res;
 }
 
 static const struct _map_x_s regstatestrings[] = {
@@ -8500,6 +8557,7 @@
 	char tmp[80];
 	char addr[80];
 	struct sip_pvt *p;
+	int res;
 
 	/* exit if we are already in process with this registrar ?*/
 	if ( r == NULL || ((auth==NULL) && (r->regstate==REG_STATE_REGSENT || r->regstate==REG_STATE_AUTHSENT))) {
@@ -8512,7 +8570,7 @@
 			ast_log(LOG_WARNING, "Already have a REGISTER going on to %s@%s?? \n", r->username, r->hostname);
 			return 0;
 		} else {
-			p = r->call;
+			p = dialog_ref(r->call,"getting a copy of the r->call dialog in transmit_register");
 			make_our_tag(p->tag, sizeof(p->tag));	/* create a new local tag for every register attempt */
 			ast_string_field_set(p, theirtag, NULL);	/* forget their old tag, so we don't match tags when getting response */
 		}
@@ -8559,7 +8617,7 @@
 		} else 	/* Set registry port to the port set from the peer definition/srv or default */
 			r->portno = ntohs(p->sa.sin_port);
 		ast_set_flag(&p->flags[0], SIP_OUTGOING);	/* Registration is outgoing call */
-		r->call = dialog_ref(p,"transmit_register: setting dialog in registry r->call");		/* Save pointer to SIP dialog */
+		r->call = dialog_ref(p,"copying dialog into registry r->call");		/* Save pointer to SIP dialog */
 		p->registry = registry_addref(r,"transmit_register: addref to p->registry in transmit_register");	/* Add pointer to registry in packet */
 		if (!ast_strlen_zero(r->secret))	/* Secret (password) */
 			ast_string_field_set(p, peersecret, r->secret);
@@ -8687,17 +8745,21 @@
 	r->regattempts++;	/* Another attempt */
 	if (option_debug > 3)
 		ast_verbose("REGISTER attempt %d to %s@%s\n", r->regattempts, r->username, r->hostname);
-	return send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+	res = send_request(p, &req, XMIT_CRITICAL, p->ocseq);
+	dialog_unref(p,"p is finished here at the end of transmit_register");
+	return res;
 }
 
 /*! \brief Transmit text with SIP MESSAGE method */
 static int transmit_message_with_text(struct sip_pvt *p, const char *text)
 {
 	struct sip_request req;
-
+	int res;
+	
 	reqprep(&req, p, SIP_MESSAGE, 0, 1);
 	add_text(&req, text);
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	return res;
 }
 
 /*! \brief Allocate SIP refer structure */
@@ -8723,6 +8785,7 @@
 	char referto[256];
 	char *ttag, *ftag;
 	char *theirtag = ast_strdupa(p->theirtag);
+	int res;
 
 	if (sipdebug)
 		ast_debug(1, "SIP transfer of %s to %s\n", p->callid, dest);
@@ -8770,7 +8833,9 @@
 	if (!ast_strlen_zero(p->our_contact))
 		add_header(&req, "Referred-By", p->our_contact);
 
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	return res;
+
 	/* We should propably wait for a NOTIFY here until we ack the transfer */
 	/* Maybe fork a new thread and wait for a STATUS of REFER_200OK on the refer status before returning to app_transfer */
 
@@ -8786,20 +8851,24 @@
 static int transmit_info_with_digit(struct sip_pvt *p, const char digit, unsigned int duration)
 {
 	struct sip_request req;
-
+	int res;
+	
 	reqprep(&req, p, SIP_INFO, 0, 1);
 	add_digit(&req, digit, duration, (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO));
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	return res;
 }
 
 /*! \brief Send SIP INFO with video update request */
 static int transmit_info_with_vidupdate(struct sip_pvt *p)
 {
 	struct sip_request req;
-
+	int res;
+	
 	reqprep(&req, p, SIP_INFO, 0, 1);
 	add_vidupdate(&req);
-	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	res = send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+	return res;
 }
 
 /*! \brief Transmit generic SIP request 
@@ -8808,7 +8877,8 @@
 static int transmit_request(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
 {
 	struct sip_request resp;
-
+	int res;
+	
 	if (sipmethod == SIP_ACK)
 		p->invitestate = INV_CONFIRMED;
 
@@ -8817,7 +8887,8 @@
 		add_header(&resp, "Reason:", "SIP;cause=200;text=\"Call completed elsewhere\"");
 
 	add_header_contentLength(&resp, 0);
-	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
+	res = send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);
+	return res;
 }
 
 /*! \brief return the request and response heade for a 401 or 407 code */
@@ -8839,7 +8910,8 @@
 static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int seqno, enum xmittype reliable, int newbranch)
 {
 	struct sip_request resp;
-
+	int res;
+	
 	reqprep(&resp, p, sipmethod, seqno, newbranch);
 	if (!ast_strlen_zero(p->realm)) {
 		char digest[1024];
@@ -8864,7 +8936,8 @@
 	}
 
 	add_header_contentLength(&resp, 0);
-	return send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
+	res = send_request(p, &resp, reliable, seqno ? seqno : p->ocseq);	
+	return res;
 }
 
 /*! \brief Remove registration data from realtime database or AST/DB when registration expires */
@@ -10883,7 +10956,7 @@
 	
 	i = ao2_iterator_init(users, 0);
 	
-	while ((user = ao2_iterator_next(&i))) {
+	while ((user = ao2_iterator_next(&i,"iterate thru user table"))) {
 		if (user->call_limit)
 			snprintf(ilimits, sizeof(ilimits), "%d", user->call_limit);
 		else 
@@ -10891,13 +10964,14 @@
 		snprintf(iused, sizeof(iused), "%d", user->inUse);
 		if (showall || user->call_limit)
 			ast_cli(a->fd, FORMAT2, user->name, iused, ilimits);
+		unref_user(user,"toss iterator pointer");
 	}
 
 	ast_cli(a->fd, FORMAT, "* Peer name", "In use", "Limit");
 
 	i = ao2_iterator_init(peers, 0);
 
-	while ((peer = ao2_iterator_next(&i))) {
+	while ((peer = ao2_iterator_next(&i, "iterate thru peer table"))) {
 		if (peer->call_limit)
 			snprintf(ilimits, sizeof(ilimits), "%d", peer->call_limit);
 		else 
@@ -10905,6 +10979,7 @@
 		snprintf(iused, sizeof(iused), "%d/%d/%d", peer->inUse, peer->inRinging, peer->onHold);
 		if (showall || peer->call_limit)
 			ast_cli(a->fd, FORMAT2, peer->name, iused, ilimits);
+		unref_peer(peer,"toss iterator pointer");
 	}
 
 	return CLI_SUCCESS;
@@ -11012,7 +11087,7 @@
 
 	i = ao2_iterator_init(users, 0);
 
-	while ((user = ao2_iterator_next(&i))) {
+	while ((user = ao2_iterator_next(&i, "iterate thru user table"))) {
 
 		if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0)) {
 			ao2_unlock(user);
@@ -11025,6 +11100,7 @@
 			user->context,
 			cli_yesno(user->ha != NULL),
 			nat2str(ast_test_flag(&user->flags[0], SIP_NAT)));
+		unref_user(user,"toss iterator pointer");
 	}
 
 	if (havepattern)
@@ -11185,13 +11261,14 @@
 		ast_cli(fd, FORMAT2, "Name/username", "Host", "Dyn", "Nat", "ACL", "Port", "Status", (realtimepeers ? "Realtime" : ""));
 	
 	i = ao2_iterator_init(peers, 0);
-	while ((peer = ao2_iterator_next(&i))) {	
+	while ((peer = ao2_iterator_next(&i, "iterate thru peers table"))) {	
 		char status[20] = "";
 		char srch[2000];
 		char pstatus;
 		
 		if (havepattern && regexec(&regexbuf, peer->name, 0, NULL, 0)) {
 			ao2_unlock(peer);
+			unref_peer(peer,"toss iterator peer ptr before continue");
 			continue;
 		}
 
@@ -11259,6 +11336,7 @@
 		}
 
 		total_peers++;
+		unref_peer(peer,"toss iterator peer ptr");
 	}
 	
 	if (!s)
@@ -11532,14 +11610,16 @@
 			
 			ao2_lock(peers); /* was WRLOCK */
 			i = ao2_iterator_init(peers, 0);
-			while ((pi = ao2_iterator_next(&i))) {
+			while ((pi = ao2_iterator_next(&i,"iterate thru peers table"))) {
 				if (name && regexec(&regexbuf, pi->name, 0, NULL, 0)) {
+					unref_peer(pi,"toss iterator peer ptr before continue");
 					continue;
 				};
 				if (ast_test_flag(&pi->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
 					pi->theMark = 1;
 					pruned++;
 				}
+				unref_peer(pi,"toss iterator peer ptr");
 			}
 			if (pruned) {
 				ast_log(LOG_NOTICE,"Callback to PRUNE PEERS\n");
@@ -11554,14 +11634,16 @@
 
 			ao2_lock(users); /* was WRLOCK */
 			i = ao2_iterator_init(users, 0);
-			while ((ui = ao2_iterator_next(&i))) {
+			while ((ui = ao2_iterator_next(&i, "iterate thru users table"))) {
 				if (name && regexec(&regexbuf, ui->name, 0, NULL, 0)) {
+					unref_user(ui,"toss iterator user ptr before continue");
 					continue;
 				};
 				if (ast_test_flag(&ui->flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
 					ui->theMark = 1;
 					pruned++;
 				}
+				unref_user(ui,"toss iterator user ptr");
 			}
 			if (pruned) {
 				ast_log(LOG_NOTICE,"Callback to PRUNE USERS\n");
@@ -12421,7 +12503,7 @@
 
 	i = ao2_iterator_init(dialogs, 0);
 	
-	while ((cur = ao2_iterator_next(&i))) {
+	while ((cur = ao2_iterator_next(&i, "iterate thru dialogs"))) {
 		if (!strncasecmp(word, cur->callid, wordlen) && ++which > state) {
 			c = ast_strdup(cur->callid);
 			ao2_ref(cur,-1,"drop ref in iterator loop break");
@@ -12442,14 +12524,17 @@
 	struct ao2_iterator i = ao2_iterator_init(peers,0);
 	struct sip_peer *peer;
 
-	while ((peer = ao2_iterator_next(&i))) {
+	while ((peer = ao2_iterator_next(&i, "iterate thru peers table"))) {
 		/* locking of the object is not required because only the name and flags are being compared */
 		if (!strncasecmp(word, peer->name, wordlen) &&
 				(!flags2 || ast_test_flag(&peer->flags[1], flags2)) &&
 				++which > state)
 			result = ast_strdup(peer->name);
-		if (result)
+		if (result) {
+			unref_peer(peer,"toss iterator peer ptr before break");
 			break;
+		}
+		unref_peer(peer,"toss iterator peer ptr");
 	}
 	return result;
 }
@@ -12464,13 +12549,16 @@
 	   struct sip_peer *peer;
 
 	   i = ao2_iterator_init(peers, 0);
-	   while ((peer = ao2_iterator_next(&i))) {
+	   while ((peer = ao2_iterator_next(&i, "iterate thru peers table"))) {
 		   if (!strncasecmp(word, peer->name, wordlen) &&
 			   (!flags2 || ast_test_flag(&peer->flags[1], flags2)) &&
 			   ++which > state && peer->expire > 0)
 			   result = ast_strdup(peer->name);
-		   if (result)
+		   if (result) {
+			   unref_peer(peer,"toss iterator peer ptr before break");
 			   break;
+		   }
+		   unref_peer(peer,"toss iterator peer ptr");
        }
        return result;
 }
@@ -12513,17 +12601,22 @@
 
 	i = ao2_iterator_init(users, 0);
 
-	while ((user = ao2_iterator_next(&i))) {
+	while ((user = ao2_iterator_next(&i, "iterate thru users table"))) {
 		/* locking of the object is not required because only the name and flags are being compared */
 		if (!strncasecmp(word, user->name, wordlen)) {
-			if (flags2 && !ast_test_flag(&user->flags[1], flags2))
+			if (flags2 && !ast_test_flag(&user->flags[1], flags2)) {
+				unref_user(user,"toss iterator user ptr before continue");
 				continue;
+			}
 			if (++which > state) {
 				result = ast_strdup(user->name);
 			}
 		}
-		if (result)
+		if (result) {
+			unref_user(user,"toss iterator user ptr before break");
 			break;
+		}
+		unref_user(user,"toss iterator user ptr");
 	}
 	return result;
 }
@@ -12593,7 +12686,7 @@
 	
 	i = ao2_iterator_init(dialogs, 0);
 
-	while ((cur = ao2_iterator_next(&i))) {
+	while ((cur = ao2_iterator_next(&i, "iterate thru dialogs"))) {
 		if (!strncasecmp(cur->callid, a->argv[3], len)) {
 			char formatbuf[BUFSIZ/2];
 			ast_cli(a->fd,"\n");
@@ -12645,6 +12738,7 @@
 			ast_cli(a->fd, "\n\n");
 			found++;
 		}
+		ao2_ref(cur,-1,"toss dialog ptr set by iterator_next");
 	}
 	dialoglist_unlock();
 	if (!found) 
@@ -12678,7 +12772,7 @@
 	len = strlen(a->argv[3]);
 	dialoglist_lock();
 	i = ao2_iterator_init(dialogs, 0);
-	while ((cur = ao2_iterator_next(&i))) {
+	while ((cur = ao2_iterator_next(&i,"iterate thru dialogs"))) {
 		if (!strncasecmp(cur->callid, a->argv[3], len)) {
 			struct sip_history *hist;
 			int x = 0;
@@ -12695,6 +12789,7 @@
 				ast_cli(a->fd, "Call '%s' has no history\n", cur->callid);
 			found++;
 		}
+		ao2_ref(cur,-1,"toss dialog ptr from iterator_next");
 	}
 	dialoglist_unlock();
 	if (!found) 
@@ -13077,9 +13172,10 @@
 		build_via(p);
 		build_callid_pvt(p);
 		ast_cli(a->fd, "Sending NOTIFY of type '%s' to '%s'\n", a->argv[2], a->argv[i]);
+		dialog_ref(p,"bump the count of p, which transmit_sip_request will decrement.");
 		transmit_sip_request(p, &req);
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-		dialog_unref(p,"unref pvt at end of for loop");
+		dialog_unref(p,"unref pvt at end of for loop in sip_notify");
 	}
 
 	return CLI_SUCCESS;
@@ -13691,6 +13787,7 @@
 	if (p->initid > -1) {
 		/* Don't auto congest anymore since we've gotten something useful back */
 		ast_sched_del(sched, p->initid);
+		dialog_unref(p,"when you delete the initid sched, you should dec the refcount for the stored dialog ptr");
 		p->initid = -1;
 	}
 
@@ -14041,8 +14138,8 @@
 {
 	int expires, expires_ms;
 	struct sip_registry *r;
-	r=p->registry;
-
+	r=p->registry; /* do I need to ref/unref this during this routine? Doesn't LOOK like it...*/
+	
 	switch (resp) {
 	case 401:	/* Unauthorized */
 		if (p->authtries == MAX_AUTHTRIES || do_register_auth(p, req, resp)) {
@@ -14060,7 +14157,8 @@
 	case 404:	/* Not found */
 		ast_log(LOG_WARNING, "Got 404 Not found on SIP register to service %s@%s, giving up\n", p->registry->username,p->registry->hostname);
 		p->needdestroy = 1;
-		r->call = NULL;
+		if (r->call)
+			r->call = dialog_unref(r->call,"unsetting registry->call pointer-- case 404");
 		r->regstate = REG_STATE_REJECTED;
 		ast_sched_del(sched, r->timeout);
 		r->timeout = -1;
@@ -14075,7 +14173,8 @@
 		if (global_regattempts_max)
 			p->registry->regattempts = global_regattempts_max+1;
 		p->needdestroy = 1;
-		r->call = NULL;
+		if (r->call)
+			r->call = dialog_unref(r->call,"unsetting registry->call pointer-- case 408");
 		ast_sched_del(sched, r->timeout);
 		r->timeout = -1;
 		break;
@@ -14085,7 +14184,7 @@
 		ast_sched_del(sched, r->timeout);
 		r->timeout = -1;
 		if (r->call) {
-			r->call = NULL;
+			r->call = dialog_unref(r->call,"unsetting registry->call pointer-- case 423");
 			p->needdestroy = 1;
 		}
 		if (r->expiry > max_expiry) {
@@ -14101,7 +14200,8 @@
 	case 479:	/* SER: Not able to process the URI - address is wrong in register*/
 		ast_log(LOG_WARNING, "Got error 479 on register to %s@%s, giving up (check config)\n", p->registry->username,p->registry->hostname);
 		p->needdestroy = 1;
-		r->call = NULL;
+		if (r->call)
+			r->call = dialog_unref(r->call,"unsetting registry->call pointer-- case 479");
 		r->regstate = REG_STATE_REJECTED;
 		ast_sched_del(sched, r->timeout);
 		r->timeout = -1;
@@ -14112,7 +14212,7 @@
 			p->needdestroy = 1;
 			return 0;
 		}
-
+		
 		r->regstate = REG_STATE_REGISTERED;
 		r->regtime = ast_tvnow();		/* Reset time of last succesful registration */
 		manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nDomain: %s\r\nStatus: %s\r\n", r->hostname, regstate2str(r->regstate));
@@ -14123,12 +14223,13 @@
 			ast_sched_del(sched, r->timeout);
 		}
 		r->timeout=-1;
-		r->call = NULL;
-		p->registry = registry_unref(p->registry,"unref registry entry p->registry"); /* are we erasing a ref? */
+		if (r->call)
+			r->call = dialog_unref(r->call,"unsetting registry->call pointer-- case 200");
+		p->registry = registry_unref(p->registry,"unref registry entry p->registry");
 		/* Let this one hang around until we have all the responses */
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 		/* p->needdestroy = 1; */
-
+		
 		/* set us up for re-registering */
 		/* figure out how long we got registered for */
 		if (r->expire > -1)
@@ -14136,7 +14237,7 @@
 		/* according to section 6.13 of RFC, contact headers override
 		   expires headers, so check those first */
 		expires = 0;
-
+		
 		/* XXX todo: try to save the extra call */
 		if (!ast_strlen_zero(get_header(req, "Contact"))) {
 			const char *contact = NULL;
@@ -14158,13 +14259,13 @@
 				if (sscanf(tmptmp + 8, "%d;", &expires) != 1)
 					expires = 0;
 			}
-
+			
 		}
 		if (!expires) 
 			expires=atoi(get_header(req, "expires"));
 		if (!expires)
 			expires=default_expiry;
-
+		
 		expires_ms = expires * 1000;
 		if (expires <= EXPIRY_GUARD_LIMIT)
 			expires_ms -= MAX((expires_ms * EXPIRY_GUARD_PCT),EXPIRY_GUARD_MIN);
@@ -14172,12 +14273,16 @@
 			expires_ms -= EXPIRY_GUARD_SECS * 1000;
 		if (sipdebug)
 			ast_log(LOG_NOTICE, "Outbound Registration: Expiry for %s is %d sec (Scheduling reregistration in %d s)\n", r->hostname, expires, expires_ms/1000); 
-
+		
 		r->refresh= (int) expires_ms / 1000;
-
+		
 		/* Schedule re-registration before we expire */
 		r->expire = ast_sched_replace(r->expire, sched, expires_ms, sip_reregister, r); 
-		registry_unref(r,"unref registry ptr r");
+		registry_unref(r,"unref registry ptr r"); /* HUH?  if this gets deleted, p->registry will be a bad pointer! */
+		/* shouldn't this be:
+		   p->registry = registry_unref(r,"unref registry entry at p->registry");
+		   ??????? 
+		*/
 	}
 	return 1;
 }
@@ -14185,7 +14290,7 @@
 /*! \brief Handle qualification responses (OPTIONS) */
 static void handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req)
 {
-	struct sip_peer *peer = p->relatedpeer; /* hope this is already refcounted! */
+	struct sip_peer *peer = ref_peer(p->relatedpeer,"bump refcount on p, as it is being used in this function(handle_response_peerpoke)"); /* hope this is already refcounted! */
 	int statechanged, is_reachable, was_reachable;
 	int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps);
 
@@ -14227,6 +14332,7 @@
 	peer->pokeexpire = ast_sched_replace(peer->pokeexpire, sched,
 		is_reachable ? DEFAULT_FREQ_OK : DEFAULT_FREQ_NOTOK,
 		sip_poke_peer_s, peer);
+	unref_peer(peer,"unref relatedpeer ptr var at end of handle_response_peerpoke");
 }
 
 /*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
@@ -16627,8 +16733,12 @@
 			authpeer->mwipvt = dialog_unref(authpeer->mwipvt,"unref dialog authpeer->mwipvt");
 			/* sip_destroy(authpeer->mwipvt); */
 		}
-		authpeer->mwipvt = p;		/* Link from peer to pvt UH- should this be dialog_ref()? */
-		p->relatedpeer = authpeer;	/* already refcounted...Link from pvt to peer UH- should this be dialog_ref()? */
+		if (authpeer->mwipvt)
+			dialog_unref(authpeer->mwipvt,"Unref previously stored mwipvt dialog pointer");
+		authpeer->mwipvt = dialog_ref(p,"setting peers' mwipvt to p");		/* Link from peer to pvt UH- should this be dialog_ref()? */
+		if (p->relatedpeer)
+			unref_peer(p->relatedpeer,"Unref previously stored relatedpeer ptr");
+		p->relatedpeer = ref_peer(authpeer,"setting dialog's relatedpeer pointer");	/* already refcounted...Link from pvt to peer UH- should this be dialog_ref()? */
 		/* Do not release authpeer here */
 	} else { /* At this point, Asterisk does not understand the specified event */
 		transmit_response(p, "489 Bad Event", req);
@@ -16701,23 +16811,31 @@
 
 			i = ao2_iterator_init(dialogs, 0);
 
-			while ((p_old = ao2_iterator_next(&i))) {
-				if (p_old == p)
+			while ((p_old = ao2_iterator_next(&i,"iterate thru dialogs"))) {
+				if (p_old == p) {
+					ao2_ref(p_old,-1,"toss dialog ptr from iterator_next before continue");
 					continue;
-				if (p_old->initreq.method != SIP_SUBSCRIBE)
+				}
+				if (p_old->initreq.method != SIP_SUBSCRIBE) {
+					ao2_ref(p_old,-1,"toss dialog ptr from iterator_next before continue");
 					continue;
-				if (p_old->subscribed == NONE)
+				}
+				if (p_old->subscribed == NONE) {
+					ao2_ref(p_old,-1,"toss dialog ptr from iterator_next before continue");
 					continue;
+				}
 				sip_pvt_lock(p_old);
 				if (!strcmp(p_old->username, p->username)) {
 					if (!strcmp(p_old->exten, p->exten) &&
 					    !strcmp(p_old->context, p->context)) {
 						p_old->needdestroy = 1;
 						sip_pvt_unlock(p_old);
+						ao2_ref(p_old,-1,"toss dialog ptr from iterator_next before break");
 						break;
 					}
 				}
 				sip_pvt_unlock(p_old);
+				ao2_ref(p_old,-1,"toss dialog ptr from iterator_next");
 			}
 			dialoglist_unlock();
 		}
@@ -17177,8 +17295,8 @@
 
 	/* Send MWI */
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);
+	/* the following will decrement the refcount on p as it finishes */
 	transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten);
-
 	return 0;
 }
 
@@ -17395,8 +17513,9 @@
 		peer->call = dialog_unref(peer->call, "unref dialog peer->call");
 		/* peer->call = sip_destroy(peer->call); */
 	}
-	if (!(p = peer->call = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
+	if (!(p = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
 		return -1;
+	peer->call = dialog_ref(p,"copy sip alloc from p to peer->call");
 	
 	p->sa = peer->addr;
 	p->recv = peer->addr;
@@ -17419,14 +17538,13 @@
 
 	if (peer->pokeexpire > -1)
 		ast_sched_del(sched, peer->pokeexpire);
-	p->relatedpeer = peer;
-	ao2_ref(peer,1,"add one for ->relatedpeer copy"); /* we just added another ref to peer here */
+	p->relatedpeer = ref_peer(peer,"setting the relatedpeer field in the dialog");
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);
 #ifdef VOCAL_DATA_HACK
 	ast_copy_string(p->username, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->username));
-	xmitres = transmit_invite(p, SIP_INVITE, 0, 2);
+	xmitres = transmit_invite(p, SIP_INVITE, 0, 2); /* sinks the p refcount */
 #else
-	xmitres = transmit_invite(p, SIP_OPTIONS, 0, 2);
+	xmitres = transmit_invite(p, SIP_OPTIONS, 0, 2); /* sinks the p refcount */
 #endif
 	peer->ps = ast_tvnow();
 	if (xmitres == XMIT_ERROR)
@@ -17637,10 +17755,9 @@
 	if (!tmpc) {
 		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from call request 3 for %s....\n", p->callid);
 		dialog_unlink_all(p, TRUE, TRUE);
-		dialog_unref(p,"unref dialog before destroy");
 		/* sip_destroy(p); */
 	}
-	
+	dialog_unref(p,"toss pvt ptr at end of sip_request_call");
 	ast_update_use_count();
 	restart_monitor();
 	return tmpc;
@@ -19589,10 +19706,11 @@
 	if (!speerobjs)	/* No peers, just give up */
 		return;
 
-	while ((peer = ao2_iterator_next(&i))) {
+	while ((peer = ao2_iterator_next(&i, "iterate thru peers table"))) {
 		ms += 100;
 		peer->pokeexpire = ast_sched_replace(peer->pokeexpire, 
 			sched, ms, sip_poke_peer_s, peer);
+		unref_peer(peer,"toss iterator peer ptr");
 	}
 }
 
@@ -19814,9 +19932,10 @@
 	dialoglist_lock();
 	/* Hangup all dialogs if they have an owner */
 	i = ao2_iterator_init(dialogs, 0);
-	while ((p = ao2_iterator_next(&i))) {
+	while ((p = ao2_iterator_next(&i, "iterate thru dialogs"))) {
 		if (p->owner)
 			ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
+		ao2_ref(p,-1,"toss dialog ptr from iterator_next");
 	}
 	dialoglist_unlock();
 
@@ -19832,7 +19951,7 @@
 	dialoglist_lock();
 	/* Destroy all the dialogs and free their memory */
 	i = ao2_iterator_init(dialogs, 0);
-	while ((p = ao2_iterator_next(&i))) {
+	while ((p = ao2_iterator_next(&i, "iterate thru dialogs"))) {
 		ao2_unlink(dialogs,p,"unlink from dialogs");
 		ao2_ref(p,-1,"throw away iterator result"); 
 	}

Modified: team/murf/bug11210/funcs/func_dialgroup.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/funcs/func_dialgroup.c?view=diff&rev=91889&r1=91888&r2=91889
==============================================================================
--- team/murf/bug11210/funcs/func_dialgroup.c (original)
+++ team/murf/bug11210/funcs/func_dialgroup.c Fri Dec  7 17:00:43 2007
@@ -55,6 +55,8 @@
                                                  char *file, int line, const char *funcname);
 #define ao2_find(arg1,arg2,arg3) ao2_find_debug((arg1), (arg2), (arg3), "func_dialgroup",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
 void *ao2_find_debug(struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname);
+#define ao2_iterator_next(arg1) ao2_iterator_next_debug((arg1), "func_dialgroup",  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+void *ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
 
 static struct ao2_container *group_container = NULL;
 

Modified: team/murf/bug11210/include/asterisk/astobj2.h
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/include/asterisk/astobj2.h?view=diff&rev=91889&r1=91888&r2=91889
==============================================================================
--- team/murf/bug11210/include/asterisk/astobj2.h (original)
+++ team/murf/bug11210/include/asterisk/astobj2.h Fri Dec  7 17:00:43 2007
@@ -659,8 +659,12 @@
 };
 
 struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags);
-
+#ifdef REF_DEBUG
+#define ao2_iterator_next(arg1, arg2) ao2_iterator_next_debug((arg1), (arg2),  __FILE__, __LINE__, __PRETTY_FUNCTION__)
+void *ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname);
+#else
 void *ao2_iterator_next(struct ao2_iterator *a);
+#endif
 
 /* extra functions */
 void ao2_bt(void);	/* backtrace */

Modified: team/murf/bug11210/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/main/astobj2.c?view=diff&rev=91889&r1=91888&r2=91889
==============================================================================
--- team/murf/bug11210/main/astobj2.c (original)
+++ team/murf/bug11210/main/astobj2.c Fri Dec  7 17:00:43 2007
@@ -790,7 +790,8 @@
 /*
  * move to the next element in the container.
  */
-void * ao2_iterator_next(struct ao2_iterator *a)
+#ifdef REF_DEBUG
+void * ao2_iterator_next_debug(struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
 {
 	int lim;
 	struct bucket_list *p = NULL;
@@ -837,7 +838,7 @@
 		a->c_version = a->c->version;
 		ret = EXTERNAL_OBJ(p->astobj);
 		/* inc refcount of returned object */
-		ao2_ref(ret, 1, "iterator_next bumps the refcount before returning ptr" );
+		ao2_ref_debug(ret, 1, tag, file, line, funcname);
 	}
 
 	if (!(a->flags & F_AO2I_DONTLOCK))
@@ -845,6 +846,63 @@
 
 	return ret;
 }
+#else
+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:
+	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 */

[... 86 lines stripped ...]



More information about the asterisk-commits mailing list