Additional queue optimization (bug #3093, with mods)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4491 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Mark Spencer 21 years ago
parent c85b38383c
commit 0570c6305f

@ -160,8 +160,7 @@ static int queue_persistent_members = 0;
struct localuser { struct localuser {
struct ast_channel *chan; struct ast_channel *chan;
char numsubst[256]; char interface[256];
char tech[40];
int stillgoing; int stillgoing;
int metric; int metric;
int oldstatus; int oldstatus;
@ -197,8 +196,7 @@ struct queue_ent {
}; };
struct member { struct member {
char tech[80]; /* Technology */ char interface[80]; /* Technology/Location */
char loc[256]; /* Location */
int penalty; /* Are we a last resort? */ int penalty; /* Are we a last resort? */
int calls; /* Number of calls serviced by this member */ int calls; /* Number of calls serviced by this member */
int dynamic; /* Are we dynamically added? */ int dynamic; /* Are we dynamically added? */
@ -348,18 +346,18 @@ static void *changethread(void *data)
ast_mutex_lock(&q->lock); ast_mutex_lock(&q->lock);
cur = q->members; cur = q->members;
while(cur) { while(cur) {
if (!strcasecmp(sc->dev, cur->tech) && !strcmp(loc, cur->loc)) { if (!strcasecmp(sc->dev, cur->interface)) {
if (cur->status != sc->state) { if (cur->status != sc->state) {
cur->status = sc->state; cur->status = sc->state;
manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus", manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
"Queue: %s\r\n" "Queue: %s\r\n"
"Location: %s/%s\r\n" "Location: %s\r\n"
"Membership: %s\r\n" "Membership: %s\r\n"
"Penalty: %d\r\n" "Penalty: %d\r\n"
"CallsTaken: %d\r\n" "CallsTaken: %d\r\n"
"LastCall: %ld\r\n" "LastCall: %ld\r\n"
"Status: %d\r\n", "Status: %d\r\n",
q->name, cur->tech, cur->loc, cur->dynamic ? "dynamic" : "static", q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
cur->penalty, cur->calls, cur->lastcall, cur->status); cur->penalty, cur->calls, cur->lastcall, cur->status);
} }
} }
@ -677,13 +675,13 @@ static int update_status(struct ast_call_queue *q, struct member *member, int st
cur->status = status; cur->status = status;
manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus", manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
"Queue: %s\r\n" "Queue: %s\r\n"
"Location: %s/%s\r\n" "Location: %s\r\n"
"Membership: %s\r\n" "Membership: %s\r\n"
"Penalty: %d\r\n" "Penalty: %d\r\n"
"CallsTaken: %d\r\n" "CallsTaken: %d\r\n"
"LastCall: %ld\r\n" "LastCall: %ld\r\n"
"Status: %d\r\n", "Status: %d\r\n",
q->name, cur->tech, cur->loc, cur->dynamic ? "dynamic" : "static", q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
cur->penalty, cur->calls, cur->lastcall, cur->status); cur->penalty, cur->calls, cur->lastcall, cur->status);
break; break;
} }
@ -711,15 +709,25 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
{ {
int res; int res;
int status; int status;
char tech[256];
char *location;
if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) { if (qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime)) {
ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s/%s\n", tmp->tech, tmp->numsubst); ast_log(LOG_DEBUG, "Wrapuptime not yet expired for %s\n", tmp->interface);
if (qe->chan->cdr) if (qe->chan->cdr)
ast_cdr_busy(qe->chan->cdr); ast_cdr_busy(qe->chan->cdr);
tmp->stillgoing = 0; tmp->stillgoing = 0;
return 0; return 0;
} }
strncpy(tech, tmp->interface, sizeof(tech) - 1);
if ((location = strchr(tech, '/')))
*location++ = '\0';
else
location = "";
/* Request the peer */ /* Request the peer */
tmp->chan = ast_request(tmp->tech, qe->chan->nativeformats, tmp->numsubst, &status); tmp->chan = ast_request(tech, qe->chan->nativeformats, location, &status);
if (!tmp->chan) { /* If we can't, just go on to the next call */ if (!tmp->chan) { /* If we can't, just go on to the next call */
#if 0 #if 0
ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", cur->tech); ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", cur->tech);
@ -753,13 +761,13 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
/* Presense of ADSI CPE on outgoing channel follows ours */ /* Presense of ADSI CPE on outgoing channel follows ours */
tmp->chan->adsicpe = qe->chan->adsicpe; tmp->chan->adsicpe = qe->chan->adsicpe;
/* Place the call, but don't wait on the answer */ /* Place the call, but don't wait on the answer */
res = ast_call(tmp->chan, tmp->numsubst, 0); res = ast_call(tmp->chan, location, 0);
if (res) { if (res) {
/* Again, keep going even if there's an error */ /* Again, keep going even if there's an error */
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res); ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
else if (option_verbose > 2) else if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->numsubst); ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->interface);
ast_hangup(tmp->chan); ast_hangup(tmp->chan);
tmp->chan = NULL; tmp->chan = NULL;
tmp->stillgoing = 0; tmp->stillgoing = 0;
@ -767,20 +775,20 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
} else { } else {
if (qe->parent->eventwhencalled) { if (qe->parent->eventwhencalled) {
manager_event(EVENT_FLAG_AGENT, "AgentCalled", manager_event(EVENT_FLAG_AGENT, "AgentCalled",
"AgentCalled: %s/%s\r\n" "AgentCalled: %s\r\n"
"ChannelCalling: %s\r\n" "ChannelCalling: %s\r\n"
"CallerID: %s\r\n" "CallerID: %s\r\n"
"CallerIDName: %s\r\n" "CallerIDName: %s\r\n"
"Context: %s\r\n" "Context: %s\r\n"
"Extension: %s\r\n" "Extension: %s\r\n"
"Priority: %d\r\n", "Priority: %d\r\n",
tmp->tech, tmp->numsubst, qe->chan->name, tmp->interface, qe->chan->name,
tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown", tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown", tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
qe->chan->context, qe->chan->exten, qe->chan->priority); qe->chan->context, qe->chan->exten, qe->chan->priority);
} }
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Called %s/%s\n", tmp->tech, tmp->numsubst); ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->interface);
} }
return 0; return 0;
} }
@ -808,7 +816,7 @@ static int ring_one(struct queue_ent *qe, struct localuser *outgoing)
cur = outgoing; cur = outgoing;
while(cur) { while(cur) {
if (cur->stillgoing && !cur->chan && (cur->metric == bestmetric)) { if (cur->stillgoing && !cur->chan && (cur->metric == bestmetric)) {
ast_log(LOG_DEBUG, "(Parallel) Trying '%s/%s' with metric %d\n", cur->tech, cur->numsubst, cur->metric); ast_log(LOG_DEBUG, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
ring_entry(qe, cur); ring_entry(qe, cur);
} }
cur = cur->next; cur = cur->next;
@ -816,8 +824,7 @@ static int ring_one(struct queue_ent *qe, struct localuser *outgoing)
} else { } else {
/* Ring just the best channel */ /* Ring just the best channel */
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Trying '%s/%s' with metric %d\n", ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
best->tech, best->numsubst, best->metric);
ring_entry(qe, best); ring_entry(qe, best);
} }
} }
@ -848,7 +855,7 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
} }
if (best) { if (best) {
/* Ring just the best channel */ /* Ring just the best channel */
ast_log(LOG_DEBUG, "Next is '%s/%s' with metric %d\n", best->tech, best->numsubst, best->metric); ast_log(LOG_DEBUG, "Next is '%s' with metric %d\n", best->interface, best->metric);
qe->parent->rrpos = best->metric % 1000; qe->parent->rrpos = best->metric % 1000;
} else { } else {
/* Just increment rrpos */ /* Just increment rrpos */
@ -1320,16 +1327,16 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
} }
tmp->member = cur; /* Never directly dereference! Could change on reload */ tmp->member = cur; /* Never directly dereference! Could change on reload */
strncpy(tmp->tech, cur->tech, sizeof(tmp->tech)-1);
strncpy(tmp->numsubst, cur->loc, sizeof(tmp->numsubst)-1);
tmp->oldstatus = cur->status; tmp->oldstatus = cur->status;
tmp->lastcall = cur->lastcall; tmp->lastcall = cur->lastcall;
strncpy(tmp->interface, cur->interface, sizeof(tmp->interface)-1);
/* If we're dialing by extension, look at the extension to know what to dial */ /* If we're dialing by extension, look at the extension to know what to dial */
if ((newnum = strstr(tmp->numsubst, "BYEXTENSION"))) { if ((newnum = strstr(tmp->interface, "/BYEXTENSION"))) {
strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1); newnum++;
snprintf(newnum, sizeof(tmp->numsubst) - (newnum - tmp->numsubst), "%s%s", qe->chan->exten,restofit); strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit) - 1);
snprintf(newnum, sizeof(tmp->interface) - (newnum - tmp->interface), "%s%s", qe->chan->exten, restofit);
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->numsubst); ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->interface);
} }
/* Special case: If we ring everyone, go ahead and ring them, otherwise /* Special case: If we ring everyone, go ahead and ring them, otherwise
just calculate their metric for the appropriate strategy */ just calculate their metric for the appropriate strategy */
@ -1504,36 +1511,22 @@ static int wait_a_bit(struct queue_ent *qe)
/* [PHM 06/26/03] */ /* [PHM 06/26/03] */
static struct member * interface_exists( struct ast_call_queue * q, char * interface ) static struct member * interface_exists(struct ast_call_queue *q, char *interface)
{ {
struct member * ret = NULL ;
struct member *mem; struct member *mem;
char buf[500] ;
if( q != NULL )
{
mem = q->members ;
while( mem != NULL ) { if (q)
snprintf( buf, sizeof(buf), "%s/%s", mem->tech, mem->loc); for (mem = q->members; mem; mem = mem->next)
if (!strcmp(interface, mem->interface))
if( strcmp( buf, interface ) == 0 ) { return mem;
ret = mem ;
break ;
}
else
mem = mem->next ;
}
}
return( ret ) ; return NULL;
} }
static struct member * create_queue_node( char * interface, int penalty ) static struct member *create_queue_node(char *interface, int penalty)
{ {
struct member * cur ; struct member *cur;
char * tmp ;
/* Add a new member */ /* Add a new member */
@ -1542,18 +1535,13 @@ static struct member * create_queue_node( char * interface, int penalty )
if (cur) { if (cur) {
memset(cur, 0, sizeof(struct member)); memset(cur, 0, sizeof(struct member));
cur->penalty = penalty; cur->penalty = penalty;
strncpy(cur->tech, interface, sizeof(cur->tech) - 1); strncpy(cur->interface, interface, sizeof(cur->interface) - 1);
if ((tmp = strchr(cur->tech, '/'))) if (!strchr(cur->interface, '/'))
*tmp = '\0';
if ((tmp = strchr(interface, '/'))) {
tmp++;
strncpy(cur->loc, tmp, sizeof(cur->loc) - 1);
} else
ast_log(LOG_WARNING, "No location at interface '%s'\n", interface); ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
cur->status = ast_device_state(interface); cur->status = ast_device_state(interface);
} }
return( cur ) ; return cur;
} }
/* Dump all members in a specific queue to the databse /* Dump all members in a specific queue to the databse
@ -1575,7 +1563,7 @@ static void dump_queue_members(struct ast_call_queue *pm_queue)
while (cur_member) { while (cur_member) {
if (cur_member->dynamic) { if (cur_member->dynamic) {
value_len = strlen(value); value_len = strlen(value);
res = snprintf(value+value_len, sizeof(value)-value_len, "%s/%s;%d;", cur_member->tech, cur_member->loc, cur_member->penalty); res = snprintf(value+value_len, sizeof(value)-value_len, "%s;%d;", cur_member->interface, cur_member->penalty);
if (res != strlen(value + value_len)) { if (res != strlen(value + value_len)) {
ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n"); ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
break; break;
@ -1621,8 +1609,8 @@ static int remove_from_queue(char *queuename, char *interface)
} }
manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved", manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
"Queue: %s\r\n" "Queue: %s\r\n"
"Location: %s/%s\r\n", "Location: %s\r\n",
q->name, last_member->tech, last_member->loc); q->name, last_member->interface);
free(last_member); free(last_member);
if (queue_persistent_members) if (queue_persistent_members)
@ -1660,13 +1648,13 @@ static int add_to_queue(char *queuename, char *interface, int penalty)
q->members = new_member; q->members = new_member;
manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded", manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
"Queue: %s\r\n" "Queue: %s\r\n"
"Location: %s/%s\r\n" "Location: %s\r\n"
"Membership: %s\r\n" "Membership: %s\r\n"
"Penalty: %d\r\n" "Penalty: %d\r\n"
"CallsTaken: %d\r\n" "CallsTaken: %d\r\n"
"LastCall: %ld\r\n" "LastCall: %ld\r\n"
"Status: %d\r\n", "Status: %d\r\n",
q->name, new_member->tech, new_member->loc, new_member->dynamic ? "dynamic" : "static", q->name, new_member->interface, new_member->dynamic ? "dynamic" : "static",
new_member->penalty, new_member->calls, new_member->lastcall, new_member->status); new_member->penalty, new_member->calls, new_member->lastcall, new_member->status);
if (queue_persistent_members) if (queue_persistent_members)
@ -2203,22 +2191,15 @@ static void reload_queues(void)
cur = malloc(sizeof(struct member)); cur = malloc(sizeof(struct member));
if (cur) { if (cur) {
memset(cur, 0, sizeof(struct member)); memset(cur, 0, sizeof(struct member));
strncpy(cur->tech, var->value, sizeof(cur->tech) - 1); strncpy(cur->interface, var->value, sizeof(cur->interface) - 1);
if ((tmp = strchr(cur->tech, ','))) { if ((tmp = strchr(cur->interface, ','))) {
*tmp = '\0'; *tmp = '\0';
tmp++; tmp++;
cur->penalty = atoi(tmp); cur->penalty = atoi(tmp);
if (cur->penalty < 0) if (cur->penalty < 0)
cur->penalty = 0; cur->penalty = 0;
} }
if ((tmp = strchr(cur->tech, '/'))) if (!strchr(cur->interface, '/'))
*tmp = '\0';
if ((tmp = strchr(var->value, '/'))) {
tmp++;
strncpy(cur->loc, tmp, sizeof(cur->loc) - 1);
if ((tmp = strchr(cur->loc, ',')))
*tmp = '\0';
} else
ast_log(LOG_WARNING, "No location at line %d of queue.conf\n", var->lineno); ast_log(LOG_WARNING, "No location at line %d of queue.conf\n", var->lineno);
if (prev) if (prev)
prev->next = cur; prev->next = cur;
@ -2331,13 +2312,8 @@ static void reload_queues(void)
} else } else
ast_log(LOG_WARNING, "XXX Leaking a little memory :( XXX\n"); ast_log(LOG_WARNING, "XXX Leaking a little memory :( XXX\n");
} else { } else {
char tmp[256]; for (cur = q->members; cur; cur = cur->next)
cur = q->members; cur->status = ast_device_state(cur->interface);
while(cur) {
snprintf(tmp, sizeof(tmp), "%s/%s", cur->tech, cur->loc);
cur->status = ast_device_state(tmp);
cur = cur->next;
}
ql = q; ql = q;
} }
q = qn; q = qn;
@ -2435,7 +2411,7 @@ static int __queues_show(int fd, int argc, char **argv, int queue_show)
mem->calls, (long)(time(NULL) - mem->lastcall)); mem->calls, (long)(time(NULL) - mem->lastcall));
} else } else
strncpy(calls, " has taken no calls yet", sizeof(calls) - 1); strncpy(calls, " has taken no calls yet", sizeof(calls) - 1);
ast_cli(fd, " %s/%s%s%s\n", mem->tech, mem->loc, max, calls); ast_cli(fd, " %s%s%s\n", mem->interface, max, calls);
} }
} else } else
ast_cli(fd, " No Members\n"); ast_cli(fd, " No Members\n");
@ -2533,7 +2509,7 @@ static int manager_queues_status( struct mansession *s, struct message *m )
for (mem = q->members; mem; mem = mem->next) for (mem = q->members; mem; mem = mem->next)
ast_cli(s->fd, "Event: QueueMember\r\n" ast_cli(s->fd, "Event: QueueMember\r\n"
"Queue: %s\r\n" "Queue: %s\r\n"
"Location: %s/%s\r\n" "Location: %s\r\n"
"Membership: %s\r\n" "Membership: %s\r\n"
"Penalty: %d\r\n" "Penalty: %d\r\n"
"CallsTaken: %d\r\n" "CallsTaken: %d\r\n"
@ -2541,7 +2517,7 @@ static int manager_queues_status( struct mansession *s, struct message *m )
"Status: %d\r\n" "Status: %d\r\n"
"%s" "%s"
"\r\n", "\r\n",
q->name, mem->tech, mem->loc, mem->dynamic ? "dynamic" : "static", q->name, mem->interface, mem->dynamic ? "dynamic" : "static",
mem->penalty, mem->calls, mem->lastcall, mem->status, idText); mem->penalty, mem->calls, mem->lastcall, mem->status, idText);
/* List Queue Entries */ /* List Queue Entries */
@ -2782,14 +2758,8 @@ static char *complete_remove_queue_member(char *line, char *word, int pos, int s
ast_mutex_lock(&q->lock); ast_mutex_lock(&q->lock);
for (m = q->members ; m ; m = m->next) { for (m = q->members ; m ; m = m->next) {
if (++which > state) { if (++which > state) {
char *tmp = malloc(strlen(m->tech) + strlen(m->loc) + 2);
if (tmp) {
sprintf(tmp, "%s/%s", m->tech, m->loc);
} else {
ast_log(LOG_ERROR, "Out of memory\n");
}
ast_mutex_unlock(&q->lock); ast_mutex_unlock(&q->lock);
return tmp; return strdup(m->interface);
} }
} }
ast_mutex_unlock(&q->lock); ast_mutex_unlock(&q->lock);

Loading…
Cancel
Save