Additional queue optimization (bug #3093, with mods)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4491 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer 2004-12-19 21:30:55 +00:00
parent c85b38383c
commit 0570c6305f
1 changed files with 58 additions and 88 deletions

View File

@ -160,8 +160,7 @@ static int queue_persistent_members = 0;
struct localuser {
struct ast_channel *chan;
char numsubst[256];
char tech[40];
char interface[256];
int stillgoing;
int metric;
int oldstatus;
@ -197,8 +196,7 @@ struct queue_ent {
};
struct member {
char tech[80]; /* Technology */
char loc[256]; /* Location */
char interface[80]; /* Technology/Location */
int penalty; /* Are we a last resort? */
int calls; /* Number of calls serviced by this member */
int dynamic; /* Are we dynamically added? */
@ -348,18 +346,18 @@ static void *changethread(void *data)
ast_mutex_lock(&q->lock);
cur = q->members;
while(cur) {
if (!strcasecmp(sc->dev, cur->tech) && !strcmp(loc, cur->loc)) {
if (!strcasecmp(sc->dev, cur->interface)) {
if (cur->status != sc->state) {
cur->status = sc->state;
manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
"Queue: %s\r\n"
"Location: %s/%s\r\n"
"Location: %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",
q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
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;
manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
"Queue: %s\r\n"
"Location: %s/%s\r\n"
"Location: %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",
q->name, cur->interface, cur->dynamic ? "dynamic" : "static",
cur->penalty, cur->calls, cur->lastcall, cur->status);
break;
}
@ -711,15 +709,25 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
{
int res;
int status;
char tech[256];
char *location;
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)
ast_cdr_busy(qe->chan->cdr);
tmp->stillgoing = 0;
return 0;
}
strncpy(tech, tmp->interface, sizeof(tech) - 1);
if ((location = strchr(tech, '/')))
*location++ = '\0';
else
location = "";
/* 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 0
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 */
tmp->chan->adsicpe = qe->chan->adsicpe;
/* 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) {
/* Again, keep going even if there's an error */
if (option_debug)
ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
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);
tmp->chan = NULL;
tmp->stillgoing = 0;
@ -767,20 +775,20 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
} else {
if (qe->parent->eventwhencalled) {
manager_event(EVENT_FLAG_AGENT, "AgentCalled",
"AgentCalled: %s/%s\r\n"
"AgentCalled: %s\r\n"
"ChannelCalling: %s\r\n"
"CallerID: %s\r\n"
"CallerIDName: %s\r\n"
"Context: %s\r\n"
"Extension: %s\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_name ? tmp->chan->cid.cid_name : "unknown",
qe->chan->context, qe->chan->exten, qe->chan->priority);
}
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;
}
@ -808,7 +816,7 @@ static int ring_one(struct queue_ent *qe, struct localuser *outgoing)
cur = outgoing;
while(cur) {
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);
}
cur = cur->next;
@ -816,8 +824,7 @@ static int ring_one(struct queue_ent *qe, struct localuser *outgoing)
} else {
/* Ring just the best channel */
if (option_debug)
ast_log(LOG_DEBUG, "Trying '%s/%s' with metric %d\n",
best->tech, best->numsubst, best->metric);
ast_log(LOG_DEBUG, "Trying '%s' with metric %d\n", best->interface, best->metric);
ring_entry(qe, best);
}
}
@ -848,7 +855,7 @@ static int store_next(struct queue_ent *qe, struct localuser *outgoing)
}
if (best) {
/* 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;
} else {
/* 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 */
strncpy(tmp->tech, cur->tech, sizeof(tmp->tech)-1);
strncpy(tmp->numsubst, cur->loc, sizeof(tmp->numsubst)-1);
tmp->oldstatus = cur->status;
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 ((newnum = strstr(tmp->numsubst, "BYEXTENSION"))) {
strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
snprintf(newnum, sizeof(tmp->numsubst) - (newnum - tmp->numsubst), "%s%s", qe->chan->exten,restofit);
if ((newnum = strstr(tmp->interface, "/BYEXTENSION"))) {
newnum++;
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)
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
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] */
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;
char buf[500] ;
if( q != NULL )
{
mem = q->members ;
if (q)
for (mem = q->members; mem; mem = mem->next)
if (!strcmp(interface, mem->interface))
return mem;
while( mem != NULL ) {
snprintf( buf, sizeof(buf), "%s/%s", mem->tech, mem->loc);
if( strcmp( buf, interface ) == 0 ) {
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 ;
char * tmp ;
struct member *cur;
/* Add a new member */
@ -1542,18 +1535,13 @@ static struct member * create_queue_node( char * interface, int penalty )
if (cur) {
memset(cur, 0, sizeof(struct member));
cur->penalty = penalty;
strncpy(cur->tech, interface, sizeof(cur->tech) - 1);
if ((tmp = strchr(cur->tech, '/')))
*tmp = '\0';
if ((tmp = strchr(interface, '/'))) {
tmp++;
strncpy(cur->loc, tmp, sizeof(cur->loc) - 1);
} else
strncpy(cur->interface, interface, sizeof(cur->interface) - 1);
if (!strchr(cur->interface, '/'))
ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
cur->status = ast_device_state(interface);
}
return( cur ) ;
return cur;
}
/* 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) {
if (cur_member->dynamic) {
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)) {
ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
break;
@ -1621,8 +1609,8 @@ static int remove_from_queue(char *queuename, char *interface)
}
manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
"Queue: %s\r\n"
"Location: %s/%s\r\n",
q->name, last_member->tech, last_member->loc);
"Location: %s\r\n",
q->name, last_member->interface);
free(last_member);
if (queue_persistent_members)
@ -1660,13 +1648,13 @@ static int add_to_queue(char *queuename, char *interface, int penalty)
q->members = new_member;
manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
"Queue: %s\r\n"
"Location: %s/%s\r\n"
"Location: %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, 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);
if (queue_persistent_members)
@ -2203,22 +2191,15 @@ static void reload_queues(void)
cur = malloc(sizeof(struct member));
if (cur) {
memset(cur, 0, sizeof(struct member));
strncpy(cur->tech, var->value, sizeof(cur->tech) - 1);
if ((tmp = strchr(cur->tech, ','))) {
strncpy(cur->interface, var->value, sizeof(cur->interface) - 1);
if ((tmp = strchr(cur->interface, ','))) {
*tmp = '\0';
tmp++;
cur->penalty = atoi(tmp);
if (cur->penalty < 0)
cur->penalty = 0;
}
if ((tmp = strchr(cur->tech, '/')))
*tmp = '\0';
if ((tmp = strchr(var->value, '/'))) {
tmp++;
strncpy(cur->loc, tmp, sizeof(cur->loc) - 1);
if ((tmp = strchr(cur->loc, ',')))
*tmp = '\0';
} else
if (!strchr(cur->interface, '/'))
ast_log(LOG_WARNING, "No location at line %d of queue.conf\n", var->lineno);
if (prev)
prev->next = cur;
@ -2331,13 +2312,8 @@ static void reload_queues(void)
} else
ast_log(LOG_WARNING, "XXX Leaking a little memory :( XXX\n");
} 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;
}
for (cur = q->members; cur; cur = cur->next)
cur->status = ast_device_state(cur->interface);
ql = q;
}
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));
} else
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
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)
ast_cli(s->fd, "Event: QueueMember\r\n"
"Queue: %s\r\n"
"Location: %s/%s\r\n"
"Location: %s\r\n"
"Membership: %s\r\n"
"Penalty: %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"
"%s"
"\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);
/* 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);
for (m = q->members ; m ; m = m->next) {
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);
return tmp;
return strdup(m->interface);
}
}
ast_mutex_unlock(&q->lock);