[Asterisk-cvs] asterisk/apps app_queue.c,1.93,1.94

markster at lists.digium.com markster at lists.digium.com
Sat Nov 13 17:43:39 CST 2004


Update of /usr/cvsroot/asterisk/apps
In directory mongoose.digium.com:/tmp/cvs-serv18261/apps

Modified Files:
	app_queue.c 
Log Message:
Big agent / queue fixes


Index: app_queue.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_queue.c,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -d -r1.93 -r1.94
--- app_queue.c	9 Nov 2004 05:38:40 -0000	1.93
+++ app_queue.c	13 Nov 2004 22:44:32 -0000	1.94
@@ -303,6 +303,79 @@
 	return empty;
 }
 
+struct statechange {
+	int state;
+	char dev[0];
+};
+
+static void *changethread(void *data)
+{
+	struct ast_call_queue *q;
+	struct statechange *sc = data;
+	struct member *cur;
+	char *loc;
+	loc = strchr(sc->dev, '/');
+	if (loc) {
+		*loc = '\0';
+		loc++;
+	} else {
+		ast_log(LOG_WARNING, "Can't change device with no technology!\n");
+		free(sc);
+		return NULL;
+	}
+	if (option_debug)
+		ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d'\n", sc->dev, loc, sc->state);
+	ast_mutex_lock(&qlock);
+	for (q = queues; q; q = q->next) {
+		ast_mutex_lock(&q->lock);
+		cur = q->members;
+		while(cur) {
+			if (!strcasecmp(sc->dev, cur->tech) && !strcmp(loc, cur->loc)) {
+				if (cur->status != sc->state) {
+					cur->status = sc->state;
+					manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
+						"Queue: %s\r\n"
+						"Location: %s/%s\r\n"
+						"Membership: %s\r\n"
+						"Penalty: %d\r\n"
+						"CallsTaken: %d\r\n"
+						"LastCall: %ld\r\n"
+						"Status: %d\r\n",
+					q->name, cur->tech, cur->loc, cur->dynamic ? "dynamic" : "static",
+					cur->penalty, cur->calls, cur->lastcall, cur->status);
+				}
+			}
+			cur = cur->next;
+		}
+		ast_mutex_unlock(&q->lock);
+	}
+	ast_mutex_unlock(&qlock);
+	ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d'\n", sc->dev, loc, sc->state);
+	free(sc);
+	return NULL;
+}
+
+static int statechange_queue(const char *dev, int state, void *ign)
+{
+	/* Avoid potential for deadlocks by spawning a new thread to handle
+	   the event */
+	struct statechange *sc;
+	pthread_t t;
+	pthread_attr_t attr;
+	sc = malloc(sizeof(struct statechange) + strlen(dev) + 1);
+	if (sc) {
+		sc->state = state;
+		strcpy(sc->dev, dev);
+		pthread_attr_init(&attr);
+		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+		if (ast_pthread_create(&t, &attr, changethread, sc)) {
+			ast_log(LOG_WARNING, "Failed to create update thread!\n");
+			free(sc);
+		}
+	}
+	return 0;
+}
+
 static int join_queue(char *queuename, struct queue_ent *qe)
 {
 	struct ast_call_queue *q;
@@ -316,7 +389,7 @@
 		if (!strcasecmp(q->name, queuename)) {
 			/* This is our one */
 			ast_mutex_lock(&q->lock);
-			if ((!has_no_members(q) || q->joinempty || !q->head) && (!q->maxlen || (q->count < q->maxlen))) {
+			if ((!has_no_members(q) || q->joinempty) && (!q->maxlen || (q->count < q->maxlen))) {
 				/* There's space for us, put us at the right position inside
 				 * the queue. 
 				 * Take into account the priority of the calling user */
@@ -591,8 +664,7 @@
 				"Penalty: %d\r\n"
 				"CallsTaken: %d\r\n"
 				"LastCall: %ld\r\n"
-				"Status: %d\r\n"
-				"\r\n",
+				"Status: %d\r\n",
 					q->name, cur->tech, cur->loc, cur->dynamic ? "dynamic" : "static",
 					cur->penalty, cur->calls, cur->lastcall, cur->status);
 			break;
@@ -604,6 +676,19 @@
 	return 0;
 }
 
+static int update_dial_status(struct ast_call_queue *q, struct member *member, int status)
+{
+	if (status == AST_CAUSE_BUSY)
+		status = AST_DEVICE_BUSY;
+	else if (status == AST_CAUSE_UNREGISTERED)
+		status = AST_DEVICE_UNAVAILABLE;
+	else if (status == AST_CAUSE_NOSUCHDRIVER)
+		status = AST_DEVICE_INVALID;
+	else
+		status = AST_DEVICE_UNKNOWN;
+	return update_status(q, member, status);
+}
+
 static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
 {
 	int res;
@@ -624,10 +709,10 @@
 		if (qe->chan->cdr)
 			ast_cdr_busy(qe->chan->cdr);
 		tmp->stillgoing = 0;
-		update_status(qe->parent, tmp->member, status);
+		update_dial_status(qe->parent, tmp->member, status);
 		return 0;
 	} else if (status != tmp->oldstatus) 
-		update_status(qe->parent, tmp->member, status);
+		update_dial_status(qe->parent, tmp->member, status);
 	
 	tmp->chan->appl = "AppQueue";
 	tmp->chan->data = "(Outgoing Line)";
@@ -855,7 +940,7 @@
 					/* Setup parameters */
 					o->chan = ast_request(tech, in->nativeformats, stuff, &status);
 					if (status != o->oldstatus) 
-						update_status(qe->parent, o->member, status);						
+						update_dial_status(qe->parent, o->member, status);						
 					if (!o->chan) {
 						ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
 						o->stillgoing = 0;
@@ -2095,8 +2180,16 @@
 				free(q);
 			} else
 				ast_log(LOG_WARNING, "XXX Leaking a little memory :( XXX\n");
-		} else
+		} else {
+			char tmp[256];
+			cur = q->members;
+			while(cur) {
+				snprintf(tmp, sizeof(tmp), "%s/%s", cur->tech, cur->loc);
+				cur->status = ast_device_state(tmp);
+				cur = cur->next;
+			}
 			ql = q;
+		}
 		q = qn;
 	}
 	ast_mutex_unlock(&qlock);
@@ -2105,20 +2198,23 @@
 static char *status2str(int status, char *buf, int buflen)
 {
 	switch(status) {
-	case AST_CAUSE_BUSY:
-		strncpy(buf, "busy", buflen - 1);
+	case AST_DEVICE_UNKNOWN:
+		strncpy(buf, "unknown", buflen - 1);
 		break;
-	case AST_CAUSE_CONGESTION:
-		strncpy(buf, "congestion", buflen - 1);
+	case AST_DEVICE_NOT_INUSE:
+		strncpy(buf, "notinuse", buflen - 1);
 		break;
-	case AST_CAUSE_FAILURE:
-		strncpy(buf, "failure", buflen - 1);
+	case AST_DEVICE_INUSE:
+		strncpy(buf, "inuse", buflen - 1);
 		break;
-	case AST_CAUSE_UNREGISTERED:
-		strncpy(buf, "unregistered", buflen - 1);
+	case AST_DEVICE_BUSY:
+		strncpy(buf, "busy", buflen - 1);
 		break;
-	case AST_CAUSE_NOSUCHDRIVER:
-		strncpy(buf, "nosuchdriver", buflen - 1);
+	case AST_DEVICE_INVALID:
+		strncpy(buf, "invalid", buflen - 1);
+		break;
+	case AST_DEVICE_UNAVAILABLE:
+		strncpy(buf, "unavailable", buflen - 1);
 		break;
 	default:
 		snprintf(buf, buflen, "unknown status %d", status);
@@ -2593,6 +2689,7 @@
 	ast_manager_unregister("QueueStatus");
 	ast_manager_unregister("QueueAdd");
 	ast_manager_unregister("QueueRemove");
+	ast_devstate_del(statechange_queue, NULL);
 	ast_unregister_application(app_aqm);
 	ast_unregister_application(app_rqm);
 	return ast_unregister_application(app);
@@ -2607,6 +2704,7 @@
 		ast_cli_register(&cli_show_queues);
 		ast_cli_register(&cli_add_queue_member);
 		ast_cli_register(&cli_remove_queue_member);
+		ast_devstate_add(statechange_queue, NULL);
 		ast_manager_register( "Queues", 0, manager_queues_show, "Queues" );
 		ast_manager_register( "QueueStatus", 0, manager_queues_status, "Queue Status" );
 		ast_manager_register( "QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member, "Add interface to queue." );




More information about the svn-commits mailing list