[svn-commits] irroot: branch irroot/asterisk-trunk-quack-queue r343850 - /team/irroot/aster...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Nov 8 10:00:59 CST 2011


Author: irroot
Date: Tue Nov  8 10:00:55 2011
New Revision: 343850

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=343850
Log:
Log member remove on exit allow reload time for call_queue

Modified:
    team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c

Modified: team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c?view=diff&rev=343850&r1=343849&r2=343850
==============================================================================
--- team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c (original)
+++ team/irroot/asterisk-trunk-quack-queue/apps/app_queue.c Tue Nov  8 10:00:55 2011
@@ -905,6 +905,7 @@
 	QUEUE_RELOAD_MEMBER = (1 << 1),
 	QUEUE_RELOAD_RULES = (1 << 2),
 	QUEUE_RESET_STATS = (1 << 3),
+	QUEUE_RELOAD_REALTIME = (1 << 4),
 };
 
 static const struct strategy {
@@ -1206,17 +1207,16 @@
 	int maxlen;                         /*!< Max number of entries */
 	int wrapuptime;                     /*!< Wrapup Time */
 	int penaltymemberslimit;            /*!< Disregard penalty when queue has fewer than this many members */
-
 	int retry;                          /*!< Retry calling everyone after this amount of time */
 	int timeout;                        /*!< How long to wait for an answer */
 	int weight;                         /*!< Respective weight */
 	int autopause;                      /*!< Auto pause queue members if they fail to answer */
 	int autopausedelay;                 /*!< Delay auto pause for autopausedelay seconds since last call */
 	int timeoutpriority;                /*!< Do we allow a fraction of the timeout to occur for a ring? */
-
 	/* Queue strategy things */
 	int memberdelay;                    /*!< Seconds to delay connecting member to caller */
 	int autofill;                       /*!< Ignore the head call status and ring an available agent */
+	struct timeval reload;              /*!< Time the queue will be reloaded from RT */
 	struct queue_data *data;            /*!< Queue statistics */
 };
 
@@ -1735,36 +1735,14 @@
 }
 
 /*!
- * \brief helper function used in creating the hash
- */
-static int compress_char(const char c)
-{
-	if (c < 32) {
-		return 0;
-	} else if (c > 96) {
-		return c - 64;
-	} else {
-		return c - 32;
-	}
-}
-
-/*!
  * \brief ao2 callback to calculate hash of a member by interface
  */
 static int member_hash_fn(const void *obj, const int flags)
 {
 	const struct member *mem = obj;
 	const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
-	const char *chname = strchr(interface, '/');
-	int ret = 0, i;
-
-	if (!chname) {
-		chname = interface;
-	}
-	for (i = 0; i < 5 && chname[i]; i++) {
-		ret += compress_char(chname[i]) << (i * 6);
-	}
-	return ret;
+
+	return ast_str_case_hash(interface);
 }
 
 /*!
@@ -1838,6 +1816,7 @@
 
 	ao2_lock(mem);
 	mem->calls = 0;
+	mem->lastwrapup = 0;
 	mem->lastcall = ast_tv(0, 0);
 	ao2_unlock(mem);
 
@@ -1930,16 +1909,8 @@
 	const struct callattempt *c = obj;
 	const struct member *mem = c->member;
 	const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
-	const char *chname = strchr(interface, '/');
-	int ret = 0, i;
-
-	if (!chname) {
-		chname = interface;
-	}
-	for (i = 0; i < 5 && chname[i]; i++) {
-		ret += compress_char(chname[i]) << (i * 6);
-	}
-	return ret;
+
+	return ast_str_case_hash(interface);
 }
 
 
@@ -2031,6 +2002,9 @@
 		if (q->sound_periodicannounce[i])
 			ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
 	}
+
+	q->reload = ast_tvnow();
+	q->reload.tv_sec += 86400; 
 }
 
 /*!
@@ -2053,7 +2027,7 @@
 	}
 
 	contentdup = ast_strdupa(content);
-	
+
 	if (!(maxstr = strchr(contentdup, ','))) {
 		ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
 		ao2_ref(rule, -1);
@@ -2489,8 +2463,10 @@
 		} else if ((rt_m = ao2_callback(q->data->members, 0, member_cmp_uniqueid_fn, rt_uniqueid))) {
 			/*make sure there no duplicates this should never happen am i changing interface perhaps ??*/
 			dead = 1;
+			ao2_lock(rt_m);
 			ast_log(AST_LOG_WARNING, "Duplicate uniqueid found while adding %s (%s) found %s (%s) on queue %s : Not adding\n",
 					m->interface, m->membername, rt_m->interface, rt_m->membername, q->name);
+			ao2_unlock(rt_m);
 			ao2_ref(rt_m, -1);
 		} else {
 			ast_string_field_set(m, rt_uniqueid, rt_uniqueid);
@@ -2622,7 +2598,6 @@
 			free(q->sound_periodicannounce[i]);
 	}
 	ao2_ref(q->data, -1);
-	ast_log(AST_LOG_WARNING, "Releasing Queue %s\n", q->name);
 }
 
 /*! \brief create a new call_queue structure */
@@ -2631,18 +2606,15 @@
 	struct call_queue *q;
 
 	if (!(q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
-		ast_log(AST_LOG_ERROR, "Memory allocation error\n");
 		return NULL;
 	}
-	
+
 	if (!(q->data = get_queue_data(queuename))) {
-		ast_log(AST_LOG_ERROR, "Memory allocation error\n");
 		ao2_ref(q, -1);
 		return NULL;
 	}
 
 	if (ast_string_field_init(q, 64)) {
-		ast_log(AST_LOG_ERROR, "Memory allocation error\n");
 		ao2_ref(q->data, -1);
 		ao2_ref(q, -1);
 		return NULL;
@@ -2665,7 +2637,7 @@
  * \retval the queue,
  * \retval NULL if it doesn't exist.
 */
-static struct call_queue *load_realtime_queue(const char *queuename, int rmask)
+static struct call_queue *load_realtime_queue(const char *queuename, struct ast_flags *mask)
 {
 	struct ast_variable *v;
 	const char *tmp_name;
@@ -2675,12 +2647,20 @@
 	struct ast_variable *queue_vars;
 	struct call_queue *q, *oldq;
 	int found;
+	int reload_queue = (mask) ? ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS) : 0;
+	int reload_members = (mask) ? ast_test_flag(mask, QUEUE_RELOAD_MEMBER) : 0;
+	int reload_realtime = (mask) ? ast_test_flag(mask, QUEUE_RELOAD_REALTIME) : 0;
 
 	if ((q = ao2_t_find(queues, queuename, OBJ_KEY, "Look for queue in memory first")) &&
-	    (!q->realtime || !(rmask & QUEUE_RELOAD_PARAMETERS))) {
-		if (rmask & QUEUE_RELOAD_MEMBER) {
+	    (!q->realtime || !reload_queue)) {
+		if (reload_members) {
 			rt_load_member_config(q);
 		}
+		return q;
+	}
+
+	if (!reload_realtime && !ast_tvzero(q->reload) && ast_tvdiff_sec(ast_tvnow(), q->reload)) {
+		ast_log(AST_LOG_WARNING, "Not reloading queue for next %ld Seconds\n", (long)ast_tvdiff_sec(q->reload, ast_tvnow()));
 		return q;
 	}
 
@@ -2717,7 +2697,6 @@
 			ast_variables_destroy(queue_vars);
 			return NULL;
 		}
-		ast_log(AST_LOG_WARNING, "Reconfiguring  Queue\n");
 	}
 
 	init_queue(q);		/* Ensure defaults for all parameters not set explicitly. */
@@ -2763,7 +2742,7 @@
 	}
 
 	/* Load realtime members*/
-	if (rmask & QUEUE_RELOAD_MEMBER) {
+	if (reload_members) {
 		rt_load_member_config(q);
 	}
 
@@ -2794,7 +2773,8 @@
 	return ret;
 }
 
-static void load_all_realtime_queues(int rmask) {
+static void load_all_realtime_queues(struct ast_flags *mask)
+{
 	char *queuename;
 	struct ast_config *cfg;
 	struct call_queue *queue;
@@ -2804,7 +2784,7 @@
 		for (queuename = ast_category_browse(cfg, NULL);
 				!ast_strlen_zero(queuename);
 				queuename = ast_category_browse(cfg, queuename)) {
-			if ((queue = load_realtime_queue(queuename, rmask))) {
+			if ((queue = load_realtime_queue(queuename, mask))) {
 				ao2_ref(queue, -1);
 			}
 		}
@@ -2819,8 +2799,9 @@
 	int res = -1;
 	int pos = 0;
 	int inserted = 0;
-
-	if (!(q = load_realtime_queue(queuename, QUEUE_RELOAD_PARAMETERS))) {
+	struct ast_flags qflags = {QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER};
+
+	if (!(q = load_realtime_queue(queuename, &qflags))) {
 		return res;
 	}
 
@@ -2832,7 +2813,7 @@
 		ao2_t_ref(q, -1, "Done with realtime queue");
 		return res;
 	}
-	
+
 	ao2_lock(q->data);
 	if ((*reason == QUEUE_UNKNOWN && q->maxlen && (q->data->count >= q->maxlen)) ||
 	    (*reason != QUEUE_UNKNOWN)) {
@@ -3612,10 +3593,11 @@
 static int ring_one(struct queue_ent *qe, int *busies)
 {
 	int ret = 0;
-	struct callattempt *cur, *best = NULL;
+	struct callattempt *cur, *best;
 	struct ao2_iterator aiter;
 
 	while (ret == 0) {
+		best = NULL;
 		ao2_callback_data(qe->attempts, OBJ_NODATA | OBJ_MULTIPLE, get_best_metric_cb, NULL, &best);
 		if (!best) {
 			ast_debug(1, "Nobody left to try ringing in queue\n");
@@ -3746,10 +3728,11 @@
 
 	/* Resume Music on Hold if the caller is going to stay in the queue */
 	if (!res) {
-		if (ringing)
+		if (ringing) {
 			ast_indicate(qe->chan, AST_CONTROL_RINGING);
-		else
+		} else {
 			ast_moh_start(qe->chan, qe->parent->moh, NULL);
+		}
 	}
 
 	/* update last_periodic_announce_time */
@@ -3763,7 +3746,7 @@
 	if (!qe->parent->randomperiodicannounce) {
 		qe->last_periodic_announce_sound++;
 	}
-	
+
 	return res;
 }
 
@@ -3826,12 +3809,14 @@
 			}
 		}
 		if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
-			if (!set_member_paused(qe->parent->name, call->member->interface, "Auto-Pause", 1)) {
+			ao2_lock(call->member);
+			if (!(do_set_member_penalty_paused(qe->parent, call->member, 1, 1, "Auto-Pause"))) {
 				ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
 							call->member->interface, qe->parent->name);
 			} else {
 				ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", call->member->interface, qe->parent->name);
 			}
+			ao2_unlock(call->member);
 		} else {
 			/* If queue autopause is mode all, just don't send any queue to stop.
 			* the function will stop in all queues */
@@ -4358,7 +4343,7 @@
 {
 	int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
 	int min_penalty = qe->pr->min_relative ? qe->min_penalty + qe->pr->min_value : qe->pr->min_value;
-	char max_penalty_str[20], min_penalty_str[20]; 
+	char max_penalty_str[20], min_penalty_str[20];
 	int next = qe->pr->time;
 
 	/* a relative change to the penalty could put it below 0 */
@@ -4429,7 +4414,7 @@
 		if (qe->parent->periodicannouncefrequency &&
 			(res = say_periodic_announcement(qe,ringing)))
 			break;
-		
+
 		/* see if we need to move to the next penalty level for this queue */
 		while (qe->pr && (ast_tvdiff_sec(ast_tvnow(), qe->start) >= qe->pr->time)) {
 			update_qe_rule(qe);
@@ -4440,15 +4425,16 @@
 			*reason = QUEUE_TIMEOUT;
 			break;
 		}
-		
+
 		/* Wait a second before checking again */
 		if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
-			if (res > 0 && !valid_exit(qe, res))
+			if (res > 0 && !valid_exit(qe, res)) {
 				res = 0;
-			else
+			} else {
 				break;
-		}
-		
+			}
+		}
+
 		/* If we have timed out, break out */
 		if (!ast_tvzero(qe->expire) && (ast_tvcmp(ast_tvnow(), qe->expire) >= 0)) {
 			*reason = QUEUE_TIMEOUT;
@@ -5050,8 +5036,7 @@
 	if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
 		store_next_rr(qe);
 
-	}
-	if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
+	} else if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
 		store_next_lin(qe);
 	}
 
@@ -5090,10 +5075,12 @@
 		/* Ah ha!  Someone answered within the desired timeframe.  Of course after this
 		   we will always return with -1 so that it is hung up properly after the
 		   conversation.  */
-		if (!strcmp(qe->chan->tech->type, "DAHDI"))
+		if (!strcmp(qe->chan->tech->type, "DAHDI")) {
 			ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
-		if (!strcmp(peer->tech->type, "DAHDI"))
+		}
+		if (!strcmp(peer->tech->type, "DAHDI")) {
 			ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
+		}
 		/* Update parameters for the queue */
 		now = ast_tvnow();
 		recalc_holdtime(qe, ast_tvdiff_sec(now, qe->start));
@@ -5468,7 +5455,7 @@
 		}
 		qe->handled++;
 		ao2_lock(member);
-		ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s|%ld", 
+		ast_queue_log(qe->parent->name, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s|%ld",
 					(long)ast_tvdiff_sec(ast_tvnow(), qe->start), peer->uniqueid,
 					(long)(orig - to > 0 ? (orig - to) / 1000 : 0));
 		ao2_unlock(member);
@@ -5501,6 +5488,8 @@
 				ao2_unlock(member);
 			}
 		}
+
+		callstart = ast_tvnow();
 
 		ao2_lock(member);
 		if (qe->parent->eventwhencalled)
@@ -5515,7 +5504,7 @@
 					"Ringtime: %ld\r\n"
 					"%s",
 					qe->parent->name, qe->chan->uniqueid, peer->name, member->interface, member->membername,
-					(long)ast_tvdiff_sec(ast_tvnow(), qe->start), peer->uniqueid, (long)(orig - to > 0 ? (orig - to) / 1000 : 0),
+					(long)ast_tvdiff_sec(callstart, qe->start), peer->uniqueid, (long)(orig - to > 0 ? (orig - to) / 1000 : 0),
 					qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
 		ao2_unlock(member);
 
@@ -5535,7 +5524,6 @@
 			ao2_t_ref(qe->parent, 1, "For bridge_config reference");
 		}
 
-		callstart = ast_tvnow();
 		transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
 		bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
 
@@ -5689,7 +5677,7 @@
 	struct member *mem;
 	int reload = 0;
 
-	if (!(q = load_realtime_queue(queuename, 0))) {
+	if (!(q = load_realtime_queue(queuename, NULL))) {
 		return RES_NOSUCHQUEUE;
 	}
 	if (!(mem = interface_exists(q, interface))) {
@@ -5800,7 +5788,7 @@
 	struct ao2_iterator queue_iter;
 
 	if (!ast_strlen_zero(queuename)) {
-		if (!(q = load_realtime_queue(queuename, 0))) {
+		if (!(q = load_realtime_queue(queuename, NULL))) {
 			return RESULT_FAILURE;
 		}
 		if (!(mem = interface_exists(q, interface))) {
@@ -5816,7 +5804,7 @@
 		return (!found) ? RESULT_FAILURE : RESULT_SUCCESS;
 	}
 
-	load_all_realtime_queues(0);
+	load_all_realtime_queues(NULL);
 
 	/* Special event for when all queues are paused - individual events still generated */
 	/* XXX In all other cases, we use the membername, but since this affects all queues, we cannot */
@@ -5853,7 +5841,7 @@
 	}
 
 	if (!ast_strlen_zero(queuename)) {
-		if (!(q = load_realtime_queue(queuename, 0))) {
+		if (!(q = load_realtime_queue(queuename, NULL))) {
 			return RESULT_FAILURE;
 		}
 		if (!(mem = interface_exists(q, interface))) {
@@ -5869,7 +5857,7 @@
 		return RESULT_SUCCESS;
 	}
 
-	load_all_realtime_queues(0);
+	load_all_realtime_queues(NULL);
 
 	queue_iter = ao2_iterator_init(queues, 0);
 	while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
@@ -6115,7 +6103,7 @@
 		ast_category_append(mcfg, mcat);
 	}
 
-	if (!(q = load_realtime_queue(args.queuename, 0))) {
+	if (!(q = load_realtime_queue(args.queuename, NULL))) {
 		ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
 		pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
 		return 0;
@@ -6237,7 +6225,7 @@
 		ast_log(LOG_WARNING, "Queue requires an argument: queuename[,options[,URL[,announceoverride[,timeout[,agi[,macro[,gosub[,rule[,position]]]]]]]]]\n");
 		return -1;
 	}
-	
+
 	parse = ast_strdupa(data);
 	AST_STANDARD_APP_ARGS(args, parse);
 
@@ -6363,8 +6351,8 @@
 			record_abandoned(&qe);
 			reason = QUEUE_TIMEOUT;
 			res = 0;
-			ast_queue_log(args.queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
-				qe.pos, qe.opos, (long)ast_tvdiff_sec(ast_tvnow(), qe.start));
+			ast_queue_log(args.queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d||%ld",
+				qe.pos, (long)ast_tvdiff_sec(ast_tvnow(), qe.start));
 			break;
 		}
 
@@ -6386,7 +6374,8 @@
 			record_abandoned(&qe);
 			reason = QUEUE_TIMEOUT;
 			res = 0;
-			ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
+			ast_queue_log(args.queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
+				qe.pos, qe.opos, (long)ast_tvdiff_sec(ast_tvnow(), qe.start));
 			break;
 		}
 
@@ -6415,20 +6404,21 @@
 		/* exit after 'timeout' cycle if 'n' option enabled */
 		if (noption && tries >= ao2_container_count(qe.parent->data->members)) {
 			ast_verb(3, "Exiting on time-out cycle\n");
-			ast_queue_log(args.queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos);
+			ast_queue_log(args.queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
+				qe.pos, qe.opos, (long)ast_tvdiff_sec(ast_tvnow(), qe.start));
 			record_abandoned(&qe);
 			reason = QUEUE_TIMEOUT;
 			res = 0;
 			break;
 		}
 
-		
 		/* Leave if we have exceeded our queuetimeout */
 		if (!ast_tvzero(qe.expire) && (ast_tvcmp(ast_tvnow(), qe.expire) >= 0)) {
 			record_abandoned(&qe);
 			reason = QUEUE_TIMEOUT;
 			res = 0;
-			ast_queue_log(qe.parent->name, qe.chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld", qe.pos, qe.opos, (long)ast_tvdiff_sec(ast_tvnow(), qe.start));
+			ast_queue_log(args.queuename, chan->uniqueid,"NONE", "EXITWITHTIMEOUT", "%d|%d|%ld",
+				qe.pos, qe.opos, (long)ast_tvdiff_sec(ast_tvnow(), qe.start));
 			break;
 		}
 
@@ -6523,7 +6513,7 @@
 		return -1;
 	}
 
-	if ((q = load_realtime_queue(data, 0))) {
+	if ((q = load_realtime_queue(data, NULL))) {
 		if (q->setqueuevar) {
 			sl = 0;
 			res = 0;
@@ -6564,7 +6554,7 @@
 		ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
 		return -1;
 	}
-	q = load_realtime_queue(data, 0);
+	q = load_realtime_queue(data, NULL);
 	snprintf(buf, len, "%d", q != NULL? 1 : 0);
 	if (q) {
 		ao2_t_ref(q, -1, "Done with temporary reference in QUEUE_EXISTS()");
@@ -6602,7 +6592,7 @@
 
 	AST_STANDARD_APP_ARGS(args, data);
 
-	if ((q = load_realtime_queue(args.queuename, QUEUE_RELOAD_MEMBER))) {
+	if ((q = load_realtime_queue(args.queuename, NULL))) {
 		if (!strcasecmp(args.option, "logged")) {
 			mem_iter = ao2_iterator_init(q->data->members, 0);
 			while ((m = ao2_iterator_next(&mem_iter))) {
@@ -6725,7 +6715,7 @@
 			return -1;
 		}
 	} else if (!ast_strlen_zero(args.queuename)) {
-		if (!(q = load_realtime_queue(args.queuename, 0))) {
+		if (!(q = load_realtime_queue(args.queuename, NULL))) {
 			ast_log(LOG_ERROR, "Invalid queue %s\n", args.queuename);
 			return -1;
 		}
@@ -6784,7 +6774,7 @@
 		return -1;
 	}
 
-	if ((q = load_realtime_queue(data, QUEUE_RELOAD_MEMBER))) {
+	if ((q = load_realtime_queue(data, NULL))) {
 		mem_iter = ao2_iterator_init(q->data->members, 0);
 		while ((m = ao2_iterator_next(&mem_iter))) {
 			ao2_lock(m);
@@ -6857,7 +6847,7 @@
 		return -1;
 	}
 
-	if ((q = load_realtime_queue(data, QUEUE_RELOAD_MEMBER))) {
+	if ((q = load_realtime_queue(data, NULL))) {
 		ast_log(LOG_WARNING, "queue %s was not found\n", data);
 		return -1;
 	}
@@ -6912,7 +6902,7 @@
 		return -1;
 	}
 
-	if (!(q = load_realtime_queue(args.queuename, 0))) {
+	if (!(q = load_realtime_queue(args.queuename, NULL))) {
 		ast_log(AST_LOG_WARNING, "Queue %s does not exist\n", args.queuename);
 		return -1;
 	}
@@ -7203,6 +7193,7 @@
 	struct ast_category *mcat;
 	const char *interface = NULL;
 
+
 	if (!(q = ao2_t_find(queues, queuename, OBJ_KEY, "Find queue for reload"))) {
 		/* Make one then */
 		if (!queue_reload || (!(q = alloc_queue(queuename, 0)))) {
@@ -7307,6 +7298,35 @@
 	}
 
 	return 0;
+}
+
+/*!
+ * \brief ao2 callback to delete realtime members marked dead
+ */
+static int remove_all_members_from_queue(void *obj, void *arg, void *data, int flags)
+{
+	struct member *m = obj;
+	const struct call_queue *q = data;
+
+	ao2_lock(m);
+	if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
+		ast_queue_log(q->name, "SHUTDOWN", m->interface, "REMOVEMEMBER", "%s", "");
+	} else {
+		ast_queue_log(q->name, "SHUTDOWN", m->membername, "REMOVEMEMBER", "%s", "");
+	}
+	ao2_unlock(m);
+	return CMP_MATCH;
+}
+
+/*!
+ * \brief ao2 callback to delete realtime members marked dead
+ */
+static int remove_all_members(void *obj, void *arg, int flags)
+{
+	struct call_queue *q = obj;
+
+	ao2_callback_data(q->data->members, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, remove_all_members_from_queue, NULL, q);
+	return CMP_MATCH;
 }
 
 /*! \brief reload the queues.conf file
@@ -7327,40 +7347,53 @@
 	char *cat;
 	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
 	const int queue_reload = ast_test_flag(mask, QUEUE_RELOAD_PARAMETERS);
+	const int reload_members = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
+	struct call_queue *q;
+	int loaded = 0;
 
 	if (!(cfg = ast_config_load("queues.conf", config_flags))) {
 		ast_log(LOG_NOTICE, "No call queueing config file (queues.conf), so no call queues\n");
 		return -1;
-	} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
-		return 0;
 	} else if (cfg == CONFIG_STATUS_FILEINVALID) {
 		ast_log(LOG_ERROR, "Config file queues.conf is in an invalid format.  Aborting.\n");
 		return -1;
 	}
 
-	/* Mark all queues as dead for the moment if we're reloading queues.
-	 * For clarity, we could just be reloading members, in which case we don't want to mess
-	 * with the other queue parameters at all*/
-	if (queue_reload) {
-		ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE, mark_queues_dead, (char *) queuename);
-	}
-
-	/* Chug through config file */
-	cat = NULL;
-	while ((cat = ast_category_browse(cfg, cat)) ) {
-		if (!strcasecmp(cat, "general") && queue_reload) {
-			queue_set_global_params(cfg);
-			continue;
-		}
-		if (ast_strlen_zero(queuename) || !strcasecmp(cat, queuename)) {
-			reload_single_queue(cfg, mask, cat);
-		}
-	}
-
-	ast_config_destroy(cfg);
-	/* Unref all the dead queues if we were reloading queues */
-	if (queue_reload) {
-		ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_queues, (char *) queuename);
+	if (cfg != CONFIG_STATUS_FILEUNCHANGED) {
+		/* Mark all queues as dead for the moment if we're reloading queues.
+		 * For clarity, we could just be reloading members, in which case we don't want to mess
+		 * with the other queue parameters at all*/
+		if (queue_reload) {
+			ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE, mark_queues_dead, (char *) queuename);
+		}
+
+		/* Chug through config file */
+		cat = NULL;
+		while ((cat = ast_category_browse(cfg, cat)) ) {
+			if (!strcasecmp(cat, "general") && queue_reload) {
+				queue_set_global_params(cfg);
+				continue;
+			}
+			if (ast_strlen_zero(queuename) || !strcasecmp(cat, queuename)) {
+				loaded = 1;
+				reload_single_queue(cfg, mask, cat);
+			}
+		}
+
+		ast_config_destroy(cfg);
+		/* Unref all the dead queues if we were reloading queues */
+		if (queue_reload) {
+			ao2_callback(queues, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, kill_dead_queues, (char *) queuename);
+		}
+	}
+
+	/* reload realtime queues*/
+	ast_set_flag(mask, QUEUE_RELOAD_REALTIME);
+	if (ast_strlen_zero(queuename)) {
+		load_all_realtime_queues(mask);
+	} else if ((!loaded || reload_members) &&
+		   (q = load_realtime_queue(queuename, mask))) {
+		ao2_ref(q, -1);
 	}
 	return 0;
 }
@@ -7459,10 +7492,10 @@
 	}
 
 	if ((argc == 3)	&&
-	    (q = load_realtime_queue(argv[2], QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER))) {
+	    (q = load_realtime_queue(argv[2], NULL))) {
 		ao2_ref(q, -1);
 	} else {
-		load_all_realtime_queues(QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER);
+		load_all_realtime_queues(NULL);
 	}
 
 	queue_iter = ao2_iterator_init(queues, 0);
@@ -7685,8 +7718,8 @@
 
 	/* load realtime queue[s] */
 	if (ast_strlen_zero(queuefilter)) {
-		load_all_realtime_queues(QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER);
-	} else if ((q = load_realtime_queue(queuefilter, QUEUE_RELOAD_MEMBER | QUEUE_RELOAD_PARAMETERS))) {
+		load_all_realtime_queues(NULL);
+	} else if ((q = load_realtime_queue(queuefilter, NULL))) {
 		ao2_ref(q, -1);
 	}
 
@@ -7776,8 +7809,8 @@
 
 	/* load realtime queue[s] */
 	if (ast_strlen_zero(queuefilter)) {
-		load_all_realtime_queues(QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER);
-	} else if ((q = load_realtime_queue(queuefilter, QUEUE_RELOAD_PARAMETERS | QUEUE_RELOAD_MEMBER))) {
+		load_all_realtime_queues(NULL);
+	} else if ((q = load_realtime_queue(queuefilter, NULL))) {
 		ao2_ref(q, -1);
 	}
 
@@ -7898,7 +7931,7 @@
 		ast_category_append(mcfg, mcat);
 	}
 
-	if (!(q = load_realtime_queue(queuename, 0))) {
+	if (!(q = load_realtime_queue(queuename, NULL))) {
 		astman_send_error(s, m, "Unable to add interface to queue: No such queue");
 		return 0;
 	}
@@ -7982,7 +8015,7 @@
 		return 0;
 	}
 
-	if (!(q = load_realtime_queue(queuename, 0))) {
+	if (!(q = load_realtime_queue(queuename, NULL))) {
 		astman_send_error(s, m, "Invalid 'Queue'");
 		return 0;
 	}
@@ -8217,7 +8250,7 @@
 		ast_category_append(mcfg, mcat);
 	}
 
-	if (!(q = load_realtime_queue(a->argv[5], 0))) {
+	if (!(q = load_realtime_queue(a->argv[5], NULL))) {
 		ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", a->argv[5]);
 		return CLI_FAILURE;
 	}
@@ -8466,7 +8499,7 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	if (!(q = load_realtime_queue(a->argv[7], 0))) {
+	if (!(q = load_realtime_queue(a->argv[7], NULL))) {
 		return CLI_FAILURE;
 	}
 	if ((m = interface_exists(q, a->argv[5]))) {
@@ -8955,7 +8988,7 @@
 	struct call_queue *queue;
 
 	/* load all queues from realtime*/
-	load_all_realtime_queues(QUEUE_RELOAD_MEMBER | QUEUE_RELOAD_PARAMETERS);
+	load_all_realtime_queues(NULL);
 
 	/* static queues. */
 	i = ao2_iterator_init(queues, 0);
@@ -9019,7 +9052,7 @@
 		ast_context_destroy(con, "app_queue"); /* leave no trace */
 	}
 
-	ao2_callback(queues, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
+	ao2_callback(queues, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, remove_all_members, NULL);
 	ao2_ref(queues, -1);
 
 	ao2_callback(qdata, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);




More information about the svn-commits mailing list