[asterisk-commits] mmichelson: branch mmichelson/queue_refcount r81457 - /team/mmichelson/queue_...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 4 17:11:05 CDT 2007


Author: mmichelson
Date: Tue Sep  4 17:11:05 2007
New Revision: 81457

URL: http://svn.digium.com/view/asterisk?view=rev&rev=81457
Log:
More changes. Consider this the first draft of refcounted members.

**NOTE: COMPLETELY UNTESTED! PROBABLY BROKEN!**


Modified:
    team/mmichelson/queue_refcount/apps/app_queue.c

Modified: team/mmichelson/queue_refcount/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/mmichelson/queue_refcount/apps/app_queue.c?view=diff&rev=81457&r1=81456&r2=81457
==============================================================================
--- team/mmichelson/queue_refcount/apps/app_queue.c (original)
+++ team/mmichelson/queue_refcount/apps/app_queue.c Tue Sep  4 17:11:05 2007
@@ -535,7 +535,7 @@
 			break;
 		default:
 			ast_mutex_unlock(&q->lock);
-			ao2_unref(member);
+			ao2_ref(member, -1);
 			return QUEUE_NORMAL;
 		}
 	}
@@ -1131,6 +1131,7 @@
 	while ((m = ao2_iterator_next(&mem_iter))) {
 		if (m->realtime)
 			m->dead = 1;
+		ao2_ref(m, -1);
 	}
 
 	while ((interface = ast_category_browse(member_config, interface))) {
@@ -1144,11 +1145,6 @@
 	mem_iter = ao2_iterator_init(q->members, 0);
 	while ((m = ao2_iterator_next(&mem_iter))) {	
 		if (m->dead) {
-			if (prev_m) {
-				prev_m->next = next_m;
-			} else {
-				q->members = next_m;
-			}
 			ao2_unlink(m);
 			ast_mutex_unlock(&q->lock);
 			remove_from_interfaces(m->interface);
@@ -1205,6 +1201,7 @@
 	while ((m = ao2_iterator_next(&mem_iter))) { 
 		if (m->realtime)
 			m->dead = 1;
+		ao2_ref(m, -1);
 	}
 
 	while ((interface = ast_category_browse(member_config, interface))) {
@@ -1561,6 +1558,7 @@
 			ast_hangup(outgoing->chan);
 		oo = outgoing;
 		outgoing = outgoing->q_next;
+		ao2_ref(oo->member, -1);
 		free(oo);
 	}
 }
@@ -2428,6 +2426,7 @@
 	char vars[2048];
 	int forwardsallowed = 1;
 	int callcompletedinsl;
+	struct ao2_iterator mem_iter;
 
 	memset(&bridge_config, 0, sizeof(bridge_config));
 	time(&now);
@@ -2481,13 +2480,15 @@
 	if (!ast_strlen_zero(announceoverride))
 		announce = announceoverride;
 
-	for (; cur; cur = cur->next) {
+	mem_iter = ao2_iterator_init(qe->parent->members);
+	while ((cur = ao2_iterator_next(&mem_iter))) {
 		struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
 
 		if (!tmp) {
 			ast_mutex_unlock(&qe->parent->lock);
 			if (use_weight)
 				ao2_unlock(queues);
+			ao2_ref(cur, -1);
 			goto out;
 		}
 		tmp->stillgoing = -1;
@@ -2507,8 +2508,12 @@
 			if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
 				break;
 		} else {
+			ao2_ref(cur, -1);
 			free(tmp);
 		}
+		/*Note: We do NOT decrease the reference count of the members here as we typically would while iterating
+		 * We want these references to persist until we have finished using the call_attempts
+		 */
 	}
 	if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
 		to = (qe->expire - now) * 1000;
@@ -2552,6 +2557,7 @@
 		callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
 		ast_mutex_unlock(&qe->parent->lock);
 		member = lpeer->member;
+		ao2_ref(member, 1);
 		hangupcalls(outgoing, peer);
 		outgoing = NULL;
 		if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
@@ -2606,6 +2612,7 @@
 				ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long)time(NULL) - qe->start);
 				record_abandoned(qe);
 				ast_hangup(peer);
+				ao2_ref(member, -1);
 				return -1;
 			}
 		}
@@ -2621,6 +2628,7 @@
 			ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", qe->chan->name, peer->name);
 			record_abandoned(qe);
 			ast_hangup(peer);
+			ao2_ref(member, -1);
 			return -1;
 		}
 		/* Begin Monitoring */
@@ -2820,17 +2828,14 @@
 
 static struct member *interface_exists(struct call_queue *q, const char *interface)
 {
-	struct member *mem;
+	struct member tmpmem;
 
 	if (!q)
 		return NULL;
 
-	for (mem = q->members; mem; mem = mem->next) {
-		if (!strcasecmp(interface, mem->interface))
-			return mem;
-	}
-
-	return NULL;
+	ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
+	/*XXX This is probably not what I want, but I need to double check*/
+	return ao2_find(q->members, &tmpmem, OBJ_NODATA);
 }
 
 
@@ -2845,13 +2850,15 @@
 	char value[PM_MAX_LEN];
 	int value_len = 0;
 	int res;
+	struct ao2_iterator mem_iter;
 
 	memset(value, 0, sizeof(value));
 
 	if (!pm_queue)
 		return;
 
-	for (cur_member = pm_queue->members; cur_member; cur_member = cur_member->next) {
+	mem_iter = ao2_iterator_init(pm_queue->members, 0);
+	while ((cur_member = ao2_iterator_next(&mem_iter))) {
 		if (!cur_member->dynamic)
 			continue;
 
@@ -2860,9 +2867,11 @@
 			cur_member->next ? "|" : "");
 		if (res != strlen(value + value_len)) {
 			ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
+			ao2_ref(cur_member, -1);
 			break;
 		}
 		value_len += res;
+		ao2_ref(cur_member, -1);
 	}
 	
 	if (value_len && !cur_member) {
@@ -2885,6 +2894,7 @@
 	q = ao2_find(queues, &tmpq, OBJ_POINTER);
 	ast_mutex_lock(&q->lock);
 
+	/*XXX WTF? This is so weird...Come back later*/
 	if ((last_member = interface_exists(q, interface))) {
 		if ((look = q->members) == last_member) {
 			q->members = last_member->next;
@@ -3717,6 +3727,7 @@
 	struct call_queue *q;
 	struct call_queue tmpq;
 	struct member *m;
+	struct ao2_iterator mem_iter;
 
 	/* Ensure an otherwise empty list doesn't return garbage */
 	buf[0] = '\0';
@@ -3729,12 +3740,11 @@
 	ast_copy_string(tmpq.name, data, sizeof(tmpq.name));
 	u = ast_module_user_add(chan);
 
-	q = ao2_find(queues, &tmpq, OBJ_POINTER);
-
-	if (q) {
+	if((q = ao2_find(queues, &tmpq, OBJ_POINTER))) {
 		int buflen = 0, count = 0;
 
-		for (m = q->members; m; m = m->next) {
+		mem_iter = ao2_iterator_init(q->members, 0);
+		while ((m = ao2_iterator_next(&mem_iter))) {
 			/* strcat() is always faster than printf() */
 			if (count++) {
 				strncat(buf + buflen, ",", len - buflen - 1);
@@ -3745,8 +3755,10 @@
 			/* Safeguard against overflow (negative length) */
 			if (buflen >= len - 2) {
 				ast_log(LOG_WARNING, "Truncating list\n");
+				ao2_ref(m, -1);
 				break;
 			}
+			ao2_ref(m, -1);
 		}
 		ast_mutex_unlock(&q->lock);
 		queue_unref(q);
@@ -3804,14 +3816,14 @@
 	struct ast_config *cfg;
 	char *cat, *tmp;
 	struct ast_variable *var;
-	struct member *prev, *cur, *newm, *next;
+	struct member *prev, *cur, *newm, *next, tmpmem;
 	int new;
 	const char *general_val = NULL;
 	char parse[80];
 	char *interface;
 	char *membername;
 	int penalty;
-	struct ao2_iterator i;
+	struct ao2_iterator queue_iter, mem_iter;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(interface);
 		AST_APP_ARG(penalty);
@@ -3823,9 +3835,9 @@
 		return 0;
 	}
 	use_weight=0;
-	i = ao2_iterator_init(queues, 0);
+	queue_iter = ao2_iterator_init(queues, 0);
 	/*Mark all non-realtime queues dead for now*/
-	while((q = ao2_iterator_next(&i))) {
+	while((q = ao2_iterator_next(&queue_iter))) {
 		if(!q->realtime)
 			q->dead = 1;
 		queue_unref(q);
@@ -3864,10 +3876,12 @@
 				/* Re-initialize the queue, and clear statistics */
 				init_queue(q);
 				clear_queue(q);
-				for (cur = q->members; cur; cur = cur->next) {
+				mem_iter = ao2_iterator_init(q->members, 0);
+				while ((cur = ao2_iterator_next(&mem_iter))) {
 					if (!cur->dynamic) {
 						cur->delme = 1;
 					}
+					ao2_ref(cur, -1);
 				}
 				for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
 					if (!strcasecmp(var->name, "member")) {
@@ -3894,28 +3908,19 @@
 							membername = interface;
 
 						/* Find the old position in the list */
-						for (prev = NULL, cur = q->members; cur; prev = cur, cur = cur->next) {
-							if (!strcmp(cur->interface, interface)) {
-								break;
-							}
-						}
+						ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
+						cur = ao2_find(q->members, &tmpmem, OBJ_POINTER);
 
 						newm = create_queue_member(interface, membername, penalty, cur ? cur->paused : 0);
 
 						if (cur) {
-							/* Delete it now */
-							newm->next = cur->next;
-							if (prev) {
-								prev->next = newm;
-							} else {
-								q->members = newm;
-							}
-							free(cur);
+							ao2_unlink(q->members, cur);
+							ao2_link(q->members, newm);
+							ao2_ref(cur, -1);
 						} else {
 							/* Add them to the master int list if necessary */
 							add_to_interfaces(interface);
-							newm->next = q->members;
-							q->members = newm;
+							ao2_link(q->members, newm);
 						}
 						q->membercount++;
 					} else {
@@ -3924,23 +3929,18 @@
 				}
 
 				/* Free remaining members marked as delme */
-				for (prev = NULL, cur = q->members;
-				     cur;
-				     cur = next) {
-					next = cur->next;
-
+				mem_iter = ao2_iterator_init(q->members, 0);
+				while ((cur = ao2_iterator_next(&mem_iter))) {
 					if (!cur->delme) {
 						prev = cur;
 						continue;
 					}
-
-					if (prev)
-						prev->next = next;
-					else
-						q->members = next;
+					ao2_unlink(q->members, cur);
 					remove_from_interfaces(cur->interface);
 					q->membercount--;
-					free(cur);
+					/*We decrease count by 2 since we are removing the iterator's reference
+					 * plus the container's reference*/
+					ao2_ref(cur, -2);
 				}
 
 				if (q->strategy == QUEUE_STRATEGY_ROUNDROBIN)
@@ -3956,16 +3956,18 @@
 		}
 	}
 	ast_config_destroy(cfg);
-	i = ao2_iterator_init(queues,0);
-	while ((q = ao2_iterator_next(&i))) {
+	queue_iter = ao2_iterator_init(queues,0);
+	while ((q = ao2_iterator_next(&queue_iter))) {
 		if (q->dead) {
 			ao2_unlink(queues, q);
 		} else {
 			ast_mutex_lock(&q->lock);
-			for (cur = q->members; cur; cur = cur->next) {
+			mem_iter = ao2_iterator_init(q->members, 0);
+			while ((cur = ao2_iterator_next(&mem_iter))) {
 				if(cur->dynamic)
 					q->membercount++;
 				cur->status = ast_device_state(cur->interface);
+				ao2_ref(cur, -1);
 			}
 			ast_mutex_unlock(&q->lock);
 		}
@@ -3983,6 +3985,7 @@
 	time_t now;
 	struct queue_ent *qe;
 	struct member *mem;
+	struct ao2_iterator mem_iter;
 	int pos;
 
 	max_buf[0] = '\0';
@@ -4007,7 +4010,8 @@
 			astman_append(s, "   Members: %s", term);
 		else
 			ast_cli(fd, "   Members: %s", term);
-		for (mem = q->members; mem; mem = mem->next) {
+		mem_iter = ao2_iterator_init(q->members, 0);
+		while ((mem = ao2_iterator_next(&mem_iter))) {
 			max_buf[0] = '\0';
 			max = max_buf;
 			max_left = sizeof(max_buf);
@@ -4027,6 +4031,7 @@
 				astman_append(s, "      %s%s%s", mem->interface, max_buf, term);
 			else
 				ast_cli(fd, "      %s%s%s", mem->interface, max_buf, term);
+			ao2_ref(mem, -1);
 		}
 	} else if (s)
 		astman_append(s, "   No Members%s", term);
@@ -4168,15 +4173,15 @@
 	struct queue_ent *qe;
 	float sl = 0;
 	struct member *mem;
-	struct ao2_iterator i;
+	struct ao2_iterator queue_iter, mem_iter;
 
 	astman_send_ack(s, m, "Queue status will follow");
 	time(&now);
 	if (!ast_strlen_zero(id))
 		snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
 
-	i = ao2_iterator_init(queues,0);
-	while((q = ao2_iterator_next(&i))) {
+	queue_iter = ao2_iterator_init(queues,0);
+	while((q = ao2_iterator_next(&queue_iter))) {
 		ast_mutex_lock(&q->lock);
 
 		/* List queue properties */
@@ -4197,7 +4202,9 @@
 				q->name, q->maxlen, q->count, q->holdtime, q->callscompleted,
 				q->callsabandoned, q->servicelevel, sl, q->weight, idText);
 			/* List Queue Members */
-			for (mem = q->members; mem; mem = mem->next) {
+
+			mem_iter = ao2_iterator_init(q->members, 0);
+			while((mem = ao2_iterator_next(&mem_iter))) {
 				if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) {
 					astman_append(s, "Event: QueueMember\r\n"
 						"Queue: %s\r\n"
@@ -4213,6 +4220,7 @@
 						q->name, mem->interface, mem->dynamic ? "dynamic" : "static",
 						mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
 				}
+				ao2_ref(mem, -1);
 			}
 			/* List Queue Entries */
 			pos = 1;




More information about the asterisk-commits mailing list