[asterisk-commits] irroot: branch irroot/distrotech-customers-trunk r342274 - /team/irroot/distr...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Oct 25 10:19:09 CDT 2011


Author: irroot
Date: Tue Oct 25 10:19:05 2011
New Revision: 342274

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=342274
Log:
Commit changes to app_queue code cleanups #RB1538

Modified:
    team/irroot/distrotech-customers-trunk/apps/app_queue.c

Modified: team/irroot/distrotech-customers-trunk/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/distrotech-customers-trunk/apps/app_queue.c?view=diff&rev=342274&r1=342273&r2=342274
==============================================================================
--- team/irroot/distrotech-customers-trunk/apps/app_queue.c (original)
+++ team/irroot/distrotech-customers-trunk/apps/app_queue.c Tue Oct 25 10:19:05 2011
@@ -1012,6 +1012,7 @@
 	unsigned int pending_connected_update:1;
 	/*! TRUE if caller id is not available for connected line */
 	unsigned int dial_callerid_absent:1;
+	unsigned int reserved:1;
 	struct ast_aoc_decoded *aoc_s_rate_list;
 };
 
@@ -1284,40 +1285,35 @@
 static int queue_hash_cb(const void *obj, const int flags)
 {
 	const struct call_queue *q = obj;
-
-	return ast_str_case_hash(q->name);
+	const char *name = (flags & OBJ_KEY) ? obj : q->name;
+
+	return ast_str_case_hash(name);
 }
 
 static int queue_cmp_cb(void *obj, void *arg, int flags)
 {
-	struct call_queue *q = obj;
-
-	if (flags & OBJ_POINTER) {
-		struct call_queue *q2 = arg;
-		return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
-	} else {
-		char *name = arg;
-		return !strcasecmp(q->name, name) ? CMP_MATCH | CMP_STOP : 0;
-	}
+	const struct call_queue *q = obj;
+	const struct call_queue *q2 = arg;
+	const char *name = (flags & OBJ_POINTER) ? q2->name : arg;
+
+	return !strcasecmp(q->name, name) ? CMP_MATCH | CMP_STOP : 0;
 }
 
 static int device_hash_cb(const void *obj, const int flags)
 {
+	const struct mem_state *s = obj;
+	const char *state_interface = (flags & OBJ_KEY) ? obj : s->state_interface;
+
+	return ast_str_case_hash(state_interface);
+}
+
+static int device_cmp_cb(void *obj, void *arg, int flags)
+{
 	const struct mem_state *d = obj;
-
-	return ast_str_case_hash(d->state_interface);
-}
-
-static int device_cmp_cb(void *obj, void *arg, int flags)
-{
-	struct mem_state *d = obj;
-	if (flags & OBJ_POINTER) {
-		struct mem_state *d2 = arg;
-		return !strcasecmp(d->state_interface, d2->state_interface) ? CMP_MATCH | CMP_STOP : 0;
-	} else {
-		char *iface = arg;
-		return !strcasecmp(d->state_interface, iface) ? CMP_MATCH | CMP_STOP : 0;
-	}
+	const struct mem_state *d2 = arg;
+	const char *iface = (flags & OBJ_POINTER) ? d2->state_interface : arg;
+
+	return !strcasecmp(d->state_interface, iface) ? CMP_MATCH | CMP_STOP : 0;
 }
 
 #ifdef REF_DEBUG_ONLY_QUEUES
@@ -1494,7 +1490,7 @@
 		miter = ao2_iterator_init(q->members, 0);
 		while((m = ao2_iterator_next(&miter))) {
 			ao2_lock(m->device);
-			if (strcmp(m->device->state_interface, s->state_interface)) {
+			if (strcasecmp(m->device->state_interface, s->state_interface)) {
 				ao2_unlock(m->device);
 				ao2_ref(m, -1);
 				continue;
@@ -1540,9 +1536,13 @@
 
 	if ((s = ao2_find(devices, (char *)device, 0))) {
 		ao2_lock(s);
-		s->status = state;
-		ao2_unlock(s);
-		update_status(s);
+		if (s->status != state) {
+			s->status = state;
+			ao2_unlock(s);
+			update_status(s);
+		} else {
+			ao2_unlock(s);
+		}
 		ao2_ref(s, -1);
 		ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", device, state, ast_devstate2str(state));
 	} else {
@@ -1595,9 +1595,13 @@
 
 	if ((s = ao2_find(devices, device, 0))) {
 		ao2_lock(s);
-		s->status = status;
-		ao2_unlock(s);
-		update_status(s);
+		if (s->status != status) {
+			s->status = status;
+			ao2_unlock(s);
+			update_status(s);
+		} else {
+			ao2_unlock(s);
+		}
 		ao2_ref(s, -1);
 		ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, status, ast_devstate2str(status));
 	} else {
@@ -1625,38 +1629,55 @@
 
 static struct mem_state *create_member_state(const char *state_interface) {
 	struct mem_state *state;
-	char *dev_int;
-	char *device;
 	char *exten;
 	char *context;
-
-	dev_int = ast_strdupa(state_interface);
+	char *device;
+
 	/* ref will be held for each shared member and one ref for container */
-	if ((state = ao2_find(devices, dev_int, 0))) {
+	if ((state = ao2_find(devices, (char *)state_interface, 0))) {
 		return state;
 	} else  if (!(state = ao2_alloc(sizeof(*state), NULL))) {
 		return NULL;
 	}
 
 	state->reserved = 0;
-	if (!strncmp(dev_int, "hint:", 5)) {
-		context = ast_strdupa(dev_int);
+	if (!strncasecmp(state_interface, "hint:", 5)) {
+		context = ast_strdupa(state_interface);
 		exten = strsep(&context, "@") + 5;
-
 		if (context) {
-			ast_copy_string(state->state_interface, dev_int, sizeof(state->state_interface));
+			ast_copy_string(state->state_interface, state_interface, sizeof(state->state_interface));
 		} else {
-			asprintf(&device, "%s at default", dev_int);
+			asprintf(&device, "%s at default", state_interface);
 			ast_copy_string(state->state_interface, device, sizeof(state->state_interface));
 		}
-		state->status = extensionstate2devicestate(ast_extension_state(NULL, context, exten));
+		state->status = extensionstate2devicestate(ast_extension_state(NULL, S_OR(context, "default"), exten));
 	} else {
-		ast_copy_string(state->state_interface, dev_int, sizeof(state->state_interface));
+		ast_copy_string(state->state_interface, state_interface, sizeof(state->state_interface));
 		state->status = ast_device_state(state->state_interface);
 	}
 	ao2_link(devices, state);
 
 	return state;
+}
+
+/*! \brief Set current state of member if needed*/
+static void set_queue_member_status(struct member *m)
+{
+	int status;
+	struct mem_state *s = m->device;
+
+	if (!strncasecmp(s->state_interface, "hint:", 5)) {
+		char *context = ast_strdupa(s->state_interface);
+		char *exten = strsep(&context, "@") + 5;
+		status = extensionstate2devicestate(ast_extension_state(NULL, S_OR(context, "default"), exten));
+	} else {
+		status = ast_device_state(s->state_interface);
+	}
+
+	if (s->status != status) {
+		s->status = status;
+		update_status(s);
+	}
 }
 
 /*! \brief allocate space for new queue member and set fields based on parameters passed */
@@ -1706,38 +1727,35 @@
 static int member_hash_fn(const void *obj, const int flags)
 {
 	const struct member *mem = obj;
-	const char *chname = strchr(mem->interface, '/');
+	const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
+	const char *chname = strchr(interface, '/');
 	int ret = 0, i;
-	if (!chname)
-		chname = mem->interface;
-	for (i = 0; i < 5 && chname[i]; i++)
+
+	if (!chname) {
+		chname = interface;
+	}
+	for (i = 0; i < 5 && chname[i]; i++) {
 		ret += compress_char(chname[i]) << (i * 6);
+	}
 	return ret;
 }
 
 static int member_cmp_fn(void *obj1, void *obj2, int flags)
 {
-	struct member *mem1 = obj1;
-
-	if (flags & OBJ_POINTER) {
-		struct member *mem2 = obj2;
-		return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH | CMP_STOP;
-	} else {
-		char *arg = obj2;
-		return strcasecmp(mem1->interface, arg) ? 0 : CMP_MATCH | CMP_STOP;
-	}
+	const struct member *mem1 = obj1;
+	const struct member *mem2 = obj2;
+	const char *arg = (flags & OBJ_POINTER) ? mem2->interface : obj2;
+
+	return strcasecmp(mem1->interface, arg) ? 0 : CMP_MATCH | CMP_STOP;
 }
 
 static int member_cmp_uniqueid_fn(void *obj1, void *arg, int flags)
 {
-	struct member *mem1 = obj1;
-	if (flags & OBJ_POINTER) {
-		struct member *mem2 = arg;
-		return strcasecmp(mem1->rt_uniqueid, mem2->rt_uniqueid) ? 0 : CMP_MATCH | CMP_STOP;
-	} else {
-		char *uniqueid = arg;
-		return strcasecmp(mem1->rt_uniqueid, uniqueid) ? 0 : CMP_MATCH | CMP_STOP;
-	}
+	const struct member *mem1 = obj1;
+	const struct member *mem2 = arg;
+	const char *uniqueid = (flags & OBJ_POINTER) ? mem2->rt_uniqueid : arg;
+
+	return strcasecmp(mem1->rt_uniqueid, uniqueid) ? 0 : CMP_MATCH | CMP_STOP;
 }
 
 /*!
@@ -2220,12 +2238,16 @@
 		if (paused_str) {
 			m->paused = paused;
 		}
-		if (strcmp(state_interface, m->device->state_interface)) {
+		ao2_lock(m->device);
+		if (strcasecmp(state_interface, m->device->state_interface)) {
 			/* we may be the last ref [outside container] unlink if so */
+			ao2_unlock(m->device);
 			if (ao2_ref(m->device, -1) == 2) {
 				ao2_unlink(devices, m->device);
 			}
 			m->device = create_member_state(state_interface);
+		} else {
+			ao2_unlock(m->device);
 		}
 		m->penalty = penalty;
 		m->ignorebusy = ignorebusy;
@@ -2315,7 +2337,7 @@
 	char tmpbuf[64];	/* Must be longer than the longest queue param name. */
 
 	/* Static queues override realtime. */
-	if ((q = ao2_t_find(queues, (char *)queuename, 0, "Check if static queue exists"))) {
+	if ((q = ao2_t_find(queues, queuename, OBJ_KEY, "Check if static queue exists"))) {
 		ao2_lock(q);
 		if (!q->realtime) {
 			if (q->dead) {
@@ -2446,7 +2468,7 @@
 	int prev_weight = 0;
 
 	/* Find the queue in the in-core list first. */
-	q = ao2_t_find(queues, (char *)queuename, 0, "Look for queue in memory first");
+	q = ao2_t_find(queues, queuename, OBJ_KEY, "Look for queue in memory first");
 
 	if (!q || q->realtime) {
 		/*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
@@ -2551,6 +2573,25 @@
 	ao2_iterator_destroy(&mem_iter);
 	ao2_unlock(q);
 	ast_config_destroy(member_config);
+}
+
+
+static void load_all_realtime_queues(void) {
+	char *queuename;
+	struct ast_config *cfg;
+	struct call_queue *queue;
+
+	/* load realtime queues. */
+	if (ast_check_realtime("queues") && (cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL))) {
+		for (queuename = ast_category_browse(cfg, NULL);
+				!ast_strlen_zero(queuename);
+				queuename = ast_category_browse(cfg, queuename)) {
+			if ((queue = load_realtime_queue(queuename))) {
+				queue_unref(queue);
+			}
+		}
+		ast_config_destroy(cfg);
+	}
 }
 
 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
@@ -2936,10 +2977,12 @@
  */
 static void callattempt_free(struct callattempt *doomed)
 {
-	ao2_lock(doomed->member->device);
-	doomed->member->device->reserved--;
-	ao2_unlock(doomed->member->device);
 	if (doomed->member) {
+		if (doomed->reserved) {
+			ao2_lock(doomed->member->device);
+			doomed->member->device->reserved--;
+			ao2_unlock(doomed->member->device);
+		}
 		ao2_ref(doomed->member, -1);
 	}
 	ast_party_connected_line_free(&doomed->connected);
@@ -3155,20 +3198,6 @@
 		return 0;
 	}
 
-	if (!qe->parent->ringinuse || !tmp->member->ignorebusy) {
-		ao2_lock(s);
-		if ((s->reserved > 1) || ((s->status != AST_DEVICE_NOT_INUSE) && (s->status != AST_DEVICE_UNKNOWN))) {
-			ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
-			if (qe->chan->cdr) {
-				ast_cdr_busy(qe->chan->cdr);
-			}
-			tmp->stillgoing = 0;
-			ao2_unlock(s);
-			return 0;
-		}
-		ao2_unlock(s);
-	}
-
 	if (use_weight && compare_weight(qe->parent,tmp->member)) {
 		ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
 		if (qe->chan->cdr) {
@@ -3177,6 +3206,39 @@
 		tmp->stillgoing = 0;
 		(*busies)++;
 		return 0;
+	}
+
+	if (!qe->parent->ringinuse || !tmp->member->ignorebusy) {
+		ao2_lock(s);
+		if (!s->reserved && ((s->status != AST_DEVICE_NOT_INUSE) || (s->status == AST_DEVICE_UNKNOWN))) {
+			int oldstate = s->status;
+			set_queue_member_status(tmp->member);
+			if (oldstate != s->status) {
+				ast_log(LOG_WARNING, "Member %s On Queue %s Had Incorect Status Was %s Now %s\n", s->state_interface,
+						qe->parent->name, ast_devstate2str(oldstate), ast_devstate2str(s->status));
+			}
+		}
+		if ((s->reserved) || ((s->status != AST_DEVICE_NOT_INUSE) && (s->status != AST_DEVICE_UNKNOWN))) {
+			if ((s->status != AST_DEVICE_NOT_INUSE) && (s->status != AST_DEVICE_UNKNOWN)) {
+				set_queue_member_status(tmp->member);
+			}
+			ao2_unlock(s);
+			ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
+			if (qe->chan->cdr) {
+				ast_cdr_busy(qe->chan->cdr);
+			}
+			tmp->stillgoing = 0;
+			(*busies)++;
+			return 0;
+		}
+		ao2_unlock(s);
+	}
+
+	if (!tmp->reserved) { 
+		ao2_lock(s);
+		s->reserved++;
+		ao2_unlock(s);
+		tmp->reserved = 1;
 	}
 
 	ast_copy_string(tech, tmp->interface, sizeof(tech));
@@ -3188,6 +3250,11 @@
 	/* Request the peer */
 	tmp->chan = ast_request(tech, qe->chan->nativeformats, qe->chan, location, &status);
 	if (!tmp->chan) {			/* If we can't, just go on to the next call */
+		/* something is wrong here check status*/
+		ao2_lock(s);
+		set_queue_member_status(tmp->member);
+		ao2_unlock(s);
+
 		if (qe->chan->cdr) {
 			ast_cdr_busy(qe->chan->cdr);
 		}
@@ -3270,6 +3337,11 @@
 
 	/* Place the call, but don't wait on the answer */
 	if ((res = ast_call(tmp->chan, location, 0))) {
+		/* something is wrong here check status*/
+		ao2_lock(s);
+		set_queue_member_status(tmp->member);
+		ao2_unlock(s);
+
 		/* Again, keep going even if there's an error */
 		ast_debug(1, "ast call on peer returned %d\n", res);
 		ast_verb(3, "Couldn't call %s\n", tmp->interface);
@@ -3305,6 +3377,7 @@
 			qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
 		ast_verb(3, "Called %s\n", tmp->interface);
 	}
+
 	ast_channel_unlock(tmp->chan);
 	ast_channel_unlock(qe->chan);
 
@@ -4670,12 +4743,7 @@
 		ast_channel_unlock(qe->chan);
 
 		tmp->stillgoing = -1;
-		tmp->member = cur;/* Place the reference for cur into callattempt. */
-		ao2_lock(tmp->member->device);
-		tmp->member->device->reserved++;
-		ao2_unlock(tmp->member->device);
-		tmp->lastcall = cur->lastcall;
-		tmp->lastqueue = cur->lastqueue;
+		tmp->reserved = 0;
 		ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
 		/* Special case: If we ring everyone, go ahead and ring them, otherwise
 		   just calculate their metric for the appropriate strategy */
@@ -4683,12 +4751,18 @@
 			/* Put them in the list of outgoing thingies...  We're ready now.
 			   XXX If we're forcibly removed, these outgoing calls won't get
 			   hung up XXX */
+			tmp->member = cur;/* Place the reference for cur into callattempt. */
+			tmp->lastcall = cur->lastcall;
+			tmp->lastqueue = cur->lastqueue;
+
 			tmp->q_next = outgoing;
-			outgoing = tmp;		
+			outgoing = tmp;
+
 			/* If this line is up, don't try anybody else */
 			if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
 				break;
 		} else {
+			ao2_ref(cur, -1);
 			callattempt_free(tmp);
 		}
 	}
@@ -5291,9 +5365,11 @@
 			continue;
 		}
 
+		ao2_lock(cur_member->device);
 		res = snprintf(value + value_len, sizeof(value) - value_len, "%s%s;%d;%d;%s;%s",
 			value_len ? "|" : "", cur_member->interface, cur_member->penalty, cur_member->paused, cur_member->membername, cur_member->device->state_interface);
 
+		ao2_unlock(cur_member->device);
 		ao2_ref(cur_member, -1);
 
 		if (res != strlen(value + value_len)) {
@@ -5325,7 +5401,7 @@
 	int res = RES_NOSUCHQUEUE;
 
 	ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
-	if ((q = ao2_t_find(queues, (char *)queuename, 0, "Temporary reference for interface removal"))) {
+	if ((q = ao2_t_find(queues, queuename, OBJ_KEY, "Temporary reference for interface removal"))) {
 		ao2_lock(q);
 		if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
 			/* XXX future changes should beware of this assumption!! */
@@ -5425,6 +5501,67 @@
 	return res;
 }
 
+static int do_set_member_penalty_paused(struct call_queue *q, struct member *mem, int pause, int value, const char *reason)
+{
+	if (pause) {
+		if (mem->paused == value) {
+			ast_debug(1, "%spausing already-%spaused member %s queue %s\n", (value ? "" : "un"), (value ? "" : "un"),
+					mem->membername, q->name);
+			return 0;
+		}
+
+		if ((mem->realtime) && (update_realtime_member_field(mem, q->name, "paused", value ? "1" : "0"))) {
+			ast_log(LOG_WARNING, "Failed %spausing realtime member %s queue %s\n", (value ? "" : "un"),
+					mem->membername, q->name);
+			return -1;
+		}
+		mem->paused = (value) ? 1 : 0;
+
+		if (queue_persistent_members) {
+			dump_queue_members(q);
+		}
+
+		ast_queue_log(q->name, "NONE", mem->membername, (value) ? "PAUSE" : "UNPAUSE", "%s", S_OR(reason, ""));
+
+		if (!ast_strlen_zero(reason)) {
+			manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
+				"Queue: %s\r\n"
+				"Location: %s\r\n"
+				"MemberName: %s\r\n"
+				"Paused: %d\r\n"
+				"Reason: %s\r\n",
+					q->name, mem->interface, mem->membername, mem->paused, reason);
+		} else {
+			manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
+				"Queue: %s\r\n"
+				"Location: %s\r\n"
+				"MemberName: %s\r\n"
+				"Paused: %d\r\n",
+					q->name, mem->interface, mem->membername, mem->paused);
+		}
+	} else {
+		if (mem->realtime) {
+			char *rtpenalty;
+			asprintf(&rtpenalty,"%i", value);
+			if (update_realtime_member_field(mem, q->name, "penalty", rtpenalty)) {
+				ast_log(LOG_WARNING, "Failed setting penalty %d on member %s queue %s\n", value,
+					mem->membername, q->name);
+				return -1;
+			}
+		}
+		mem->penalty = value;
+
+		ast_queue_log(q->name, "NONE", mem->interface, "PENALTY", "%d", mem->penalty);
+		manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
+					"Queue: %s\r\n"
+					"Location: %s\r\n"
+					"Penalty: %d\r\n",
+			q->name, mem->interface, mem->penalty);
+	}
+	return 0;
+}
+
+
 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
 {
 	int found = 0;
@@ -5432,60 +5569,42 @@
 	struct member *mem;
 	struct ao2_iterator queue_iter;
 
+	if (!ast_strlen_zero(queuename)) {
+		if ((q = load_realtime_queue(queuename))) {
+			ao2_lock(q);
+			if ((mem = interface_exists(q, interface))) {
+				found = do_set_member_penalty_paused(q, mem, 1, paused, reason);
+				ao2_ref(mem, -1);
+				ao2_unlock(q);
+				ao2_ref(q, -1);
+				return (found) ? RESULT_FAILURE : RESULT_SUCCESS;
+			} else {
+				ao2_unlock(q);
+				ao2_ref(q, -1);
+				return RESULT_FAILURE;
+			}
+		} else {
+			ast_log (LOG_ERROR, "Invalid queuename\n");
+			return RESULT_FAILURE;
+		}
+	}
+
+	load_all_realtime_queues();
+
 	/* 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 */
-	if (ast_strlen_zero(queuename))
-		ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
+	ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
 
 	queue_iter = ao2_iterator_init(queues, 0);
 	while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
 		ao2_lock(q);
-		if ((ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) &&
-		    (mem = interface_exists(q, interface))) {
-			if (mem->paused == paused) {
-				ast_debug(1, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
-			}
-
-			if ((mem->realtime) && (update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0"))) {
-				ast_log(LOG_WARNING, "Failed %spausing realtime queue member %s:%s\n", (paused ? "" : "un"), q->name, interface);
-				ao2_ref(mem, -1);
-				ao2_unlock(q);
-				queue_t_unref(q, "Done with iterator");
-				continue;
-			}
-			found++;
-			mem->paused = paused;
-
-			if (queue_persistent_members)
-				dump_queue_members(q);
-
-			ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, ""));
-
-			if (!ast_strlen_zero(reason)) {
-				manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
-					"Queue: %s\r\n"
-					"Location: %s\r\n"
-					"MemberName: %s\r\n"
-					"Paused: %d\r\n"
-					"Reason: %s\r\n",
-						q->name, mem->interface, mem->membername, paused, reason);
-			} else {
-				manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
-					"Queue: %s\r\n"
-					"Location: %s\r\n"
-					"MemberName: %s\r\n"
-					"Paused: %d\r\n",
-						q->name, mem->interface, mem->membername, paused);
+		mem = interface_exists(q, interface);
+		if (mem) {
+			if (!do_set_member_penalty_paused(q, mem, 1, paused, reason)) {
+				found ++;
 			}
 			ao2_ref(mem, -1);
 		}
-
-		if (!ast_strlen_zero(queuename) && !strcasecmp(queuename, q->name)) {
-			ao2_unlock(q);
-			queue_t_unref(q, "Done with iterator");
-			break;
-		}
-
 		ao2_unlock(q);
 		queue_t_unref(q, "Done with iterator");
 	}
@@ -5497,42 +5616,54 @@
 /* \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues. */
 static int set_member_penalty(const char *queuename, const char *interface, int penalty)
 {
-	int foundinterface = 0, foundqueue = 0;
+	int foundinterface = 0;
 	struct call_queue *q;
 	struct member *mem;
-	char rtpenalty[80];
+	struct ao2_iterator queue_iter;
 
 	if (penalty < 0 && !negative_penalty_invalid) {
 		ast_log(LOG_ERROR, "Invalid penalty (%d)\n", penalty);
 		return RESULT_FAILURE;
 	}
 
-	if ((q = load_realtime_queue(queuename))) {
-		foundqueue++;
+	if (!ast_strlen_zero(queuename)) {
+		if ((q = load_realtime_queue(queuename))) {
+			ao2_lock(q);
+			if ((mem = interface_exists(q, interface))) {
+				do_set_member_penalty_paused(q, mem, 0, penalty, NULL);
+				ao2_ref(mem, -1);
+				ao2_unlock(q);
+				ao2_ref(q, -1);
+				return RESULT_SUCCESS;
+			} else {
+				ao2_unlock(q);
+				ao2_ref(q, -1);
+				return RESULT_FAILURE;
+			}
+		} else {
+			ast_log (LOG_ERROR, "Invalid queuename\n");
+			return RESULT_FAILURE;
+		}
+	}
+
+	load_all_realtime_queues();
+
+	queue_iter = ao2_iterator_init(queues, 0);
+	while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
 		ao2_lock(q);
-		if ((mem = interface_exists(q, interface))) {
-			foundinterface++;
-			if (!mem->realtime) {
-				mem->penalty = penalty;
-			} else {
-				sprintf(rtpenalty,"%i", penalty);
-				update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
-			}
-			ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
-			manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
-				"Queue: %s\r\n"
-				"Location: %s\r\n"
-				"Penalty: %d\r\n",
-				q->name, mem->interface, penalty);
+		mem = interface_exists(q, interface);
+		if (mem) {
+			if (!do_set_member_penalty_paused(q, mem, 0, penalty, NULL)) {
+				foundinterface++;
+			}
 			ao2_ref(mem, -1);
 		}
 		ao2_unlock(q);
+		ao2_ref(q, -1);
 	}
 
 	if (foundinterface) {
 		return RESULT_SUCCESS;
-	} else if (!foundqueue) {
-		ast_log (LOG_ERROR, "Invalid queuename\n"); 
 	} else {
 		ast_log (LOG_ERROR, "Invalid interface\n");
 	}
@@ -5549,7 +5680,7 @@
 	struct call_queue *q;
 	struct member *mem;
 
-	if ((q = ao2_t_find(queues, queuename, 0, "Search for queue"))) {
+	if ((q = ao2_t_find(queues, queuename, OBJ_KEY, "Search for queue"))) {
 		foundqueue = 1;
 		ao2_lock(q);
 		if ((mem = interface_exists(q, interface))) {
@@ -5597,7 +5728,7 @@
 
 		queue_name = entry->key + strlen(pm_family) + 2;
 
-		cur_queue = ao2_t_find(queues, (char *)queue_name, 0, "Reload queue members");
+		cur_queue = ao2_t_find(queues, queue_name, OBJ_KEY, "Reload queue members");
 
 		if (!cur_queue) {
 			cur_queue = load_realtime_queue(queue_name);
@@ -6261,7 +6392,7 @@
 		return -1;
 	}
 
-	if ((q = ao2_t_find(queues, data, 0, "Find for QUEUE() function"))) {
+	if ((q = ao2_t_find(queues, data, OBJ_KEY, "Find for QUEUE() function"))) {
 		ao2_lock(q);
 		if (q->setqueuevar) {
 			sl = 0;
@@ -6446,17 +6577,17 @@
 			ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
 			return -1;
 		}
-	} else if ((q = load_realtime_queue(args.queuename))) {
+	} else if (!strcasecmp(args.option, "paused")) {
+		/* if queuename = NULL then paused will be set for interface in all the queues.*/
+		if (set_member_paused(args.queuename, args.interface, NULL, memvalue)) {
+			ast_log(LOG_ERROR, "Invalid interface or queue\n");
+			return -1;
+		}
+	} else if (!ast_strlen_zero(args.queuename) && (q = load_realtime_queue(args.queuename))) {
 		ao2_lock(q);
 		if ((m = interface_exists(q, args.interface))) {
 			sprintf(rtvalue, "%s",(memvalue <= 0) ? "0" : "1");
-			if (!strcasecmp(args.option, "paused")) {
-				if (m->realtime) {
-					update_realtime_member_field(m, q->name, args.option, rtvalue);
-				} else {
-					m->paused = (memvalue <= 0) ? 0 : 1;
-				}
-			} else if (!strcasecmp(args.option, "ignorebusy")) {
+			if (!strcasecmp(args.option, "ignorebusy")) {
 				if (m->realtime) {
 					update_realtime_member_field(m, q->name, args.option, rtvalue);
 				} else {
@@ -6546,7 +6677,7 @@
 		return -1;
 	}
 
-	if ((q = ao2_t_find(queues, data, 0, "Find for QUEUE_WAITING_COUNT()"))) {
+	if ((q = ao2_t_find(queues, data, OBJ_KEY, "Find for QUEUE_WAITING_COUNT()"))) {
 		ao2_lock(q);
 		count = q->count;
 		ao2_unlock(q);
@@ -6580,7 +6711,7 @@
 		return -1;
 	}
 
-	if ((q = ao2_t_find(queues, data, 0, "Find for QUEUE_MEMBER_LIST()"))) {
+	if ((q = ao2_t_find(queues, data, OBJ_KEY, "Find for QUEUE_MEMBER_LIST()"))) {
 		int buflen = 0, count = 0;
 		struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
 
@@ -6930,7 +7061,7 @@
 	const int member_reload = ast_test_flag(mask, QUEUE_RELOAD_MEMBER);
 	int prev_weight = 0;
 	struct ast_variable *var;
-		if (!(q = ao2_t_find(queues, (char *)queuename, 0, "Find queue for reload"))) {
+		if (!(q = ao2_t_find(queues, queuename, OBJ_KEY, "Find queue for reload"))) {
 		if (queue_reload) {
 			/* Make one then */
 			if (!(q = alloc_queue(queuename))) {
@@ -7183,20 +7314,8 @@
 		if ((q = load_realtime_queue(argv[2]))) {
 			queue_t_unref(q, "Done with temporary pointer");
 		}
-	} else if (ast_check_realtime("queues")) {
-		/* This block is to find any queues which are defined in realtime but
-		 * which have not yet been added to the in-core container
-		 */
-		struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
-		char *queuename;
-		if (cfg) {
-			for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) {
-				if ((q = load_realtime_queue(queuename))) {
-					queue_t_unref(q, "Done with temporary pointer");
-				}
-			}
-			ast_config_destroy(cfg);
-		}
+	} else {
+		load_all_realtime_queues();
 	}
 
 	queue_iter = ao2_iterator_init(queues, AO2_ITERATOR_DONTLOCK);
@@ -7250,9 +7369,11 @@
 				ast_str_set(&out, 0, "      %s", mem->membername);
 				if (strcasecmp(mem->membername, mem->interface)) {
 					ast_str_append(&out, 0, " (%s", mem->interface);
+					ao2_lock(mem->device);
 					if (mem->device->state_interface) {
 						ast_str_append(&out, 0, " from %s", mem->device->state_interface);
 					}
+					ao2_unlock(mem->device);
 					ast_str_append(&out, 0, ")");
 				}
 				if (mem->penalty) {
@@ -8396,6 +8517,14 @@
 
 AST_DATA_STRUCTURE(member, DATA_EXPORT_MEMBER);
 
+/* struct mem_status astdata mapping */
+#define DATA_EXPORT_CALL_DEVICE(MEMBER)					\
+	MEMBER(mem_state, state_interface, AST_DATA_STRING)		\
+	MEMBER(mem_state, status, AST_DATA_INTEGER)			\
+	MEMBER(mem_state, reserved, AST_DATA_INTEGER)
+
+AST_DATA_STRUCTURE(mem_state, DATA_EXPORT_CALL_DEVICE);
+
 #define DATA_EXPORT_QUEUE_ENT(MEMBER)						\
 	MEMBER(queue_ent, moh, AST_DATA_STRING)					\
 	MEMBER(queue_ent, announce, AST_DATA_STRING)				\
@@ -8537,21 +8666,9 @@
 {
 	struct ao2_iterator i;
 	struct call_queue *queue, *queue_realtime = NULL;
-	struct ast_config *cfg;
-	char *queuename;
-
-	/* load realtime queues. */
-	cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
-	if (cfg) {
-		for (queuename = ast_category_browse(cfg, NULL);
-				!ast_strlen_zero(queuename);
-				queuename = ast_category_browse(cfg, queuename)) {
-			if ((queue = load_realtime_queue(queuename))) {
-				queue_unref(queue);
-			}
-		}
-		ast_config_destroy(cfg);
-	}
+
+	/* load all queues from realtime*/
+	load_all_realtime_queues();
 
 	/* static queues. */
 	i = ao2_iterator_init(queues, 0);
@@ -8710,6 +8827,8 @@
 
 	ast_realtime_require_field("queue_members", "paused", RQ_INTEGER1, 1, "uniqueid", RQ_UINTEGER2, 5, SENTINEL);
 
+	load_all_realtime_queues();
+
 	return res ? AST_MODULE_LOAD_DECLINE : 0;
 }
 




More information about the asterisk-commits mailing list