Index: apps/app_queue.c =================================================================== --- apps/app_queue.c (revision 286831) +++ apps/app_queue.c (working copy) @@ -630,7 +630,28 @@ struct member *member; }; +/*! \brief queues can have members which share a device + * this structure allows the device to be distinguished + * so that it can have an always valid lastattempt flag + * under load the queue had let multiple callers ring + * a member even when call_limit is set to 1 added by bms +*/ +struct queue_ifc_use { + /* record last time queue attempted to use an interface */ + char interface[80]; + time_t lastattempttime; + struct queue_ifc_use *next; +}; +static struct queue_ifc_use *queue_ifc_use_head = NULL; +long queue_ifc_use_count = 0; +struct queue_ifc_use *add_queue_ifc_use(char *ifc); +struct queue_ifc_use *find_queue_ifc_use(char *ifc); +void remove_queue_ifc_use( struct queue_ifc_use *tmp ); +int recent_queue_ifc_use(struct member *mem, char *ifc); +void update_queue_ifc_use(struct member *mem, char *ifc); +void destroy_queue_ifc_use(void); + struct queue_ent { struct call_queue *parent; /*!< What queue is our parent */ char moh[80]; /*!< Name of musiconhold to be used */ @@ -675,6 +696,7 @@ unsigned int dead:1; /*!< Used to detect members deleted in realtime */ unsigned int delme:1; /*!< Flag to delete entry on reload */ char rt_uniqueid[80]; /*!< Unique id of realtime member entry */ + struct queue_ifc_use *lastattempt; /*!< Last time member was tried */ }; enum empty_conditions { @@ -817,6 +839,82 @@ static struct ao2_container *queues; +struct queue_ifc_use *add_queue_ifc_use(char *ifc){ + /* add structure to member based on unique interface */ + struct queue_ifc_use *tmp; + + if ((tmp = ast_calloc(1,sizeof(struct queue_ifc_use)))) { + queue_ifc_use_count++; + strncpy(tmp->interface, ifc, sizeof(tmp->interface)-1); + time(&tmp->lastattempttime); + + if (queue_ifc_use_head == NULL) { + queue_ifc_use_head = tmp; + tmp->next = NULL; + ast_debug(3,"%s First queue_ifc_use of: %s\n", __func__, ifc); + } else { + tmp->next = queue_ifc_use_head; + queue_ifc_use_head = tmp; + ast_debug(3,"%s New queue_ifc_use of: %s\n", __func__, ifc); + } + + return tmp; + } + + ast_debug(3,"%s Fail: New use of: %s\n", __func__, ifc); + return NULL; +} + +struct queue_ifc_use *find_queue_ifc_use(char *ifc) { + /* get location of interface use structure for member */ + struct queue_ifc_use *tmp; + + tmp = queue_ifc_use_head; + + while( tmp != NULL ) { + if (strcmp( ifc, tmp->interface ) == 0) { + ast_debug(3, "%s Found use of %s\n", __func__, ifc ); + return tmp; + } + + tmp = tmp->next; + } + + return add_queue_ifc_use(ifc); +} + + +int recent_queue_ifc_use(struct member *mem, char *ifc) { + /* see how long it has been since interface was accessed */ + time_t currenttime; + int delta; + + time(¤ttime); + ast_debug(3, "%s check recent use of %s\n", __func__, ifc ); + + if (mem->lastattempt == NULL) { + mem->lastattempt = find_queue_ifc_use(ifc); + } + + delta = (int)(currenttime - mem->lastattempt->lastattempttime); + ast_debug(3, "%s %s last used: %d\n", __func__, ifc, delta); + + if (delta > 2) + return 0; + else + return 1; +} + + +void update_queue_ifc_use(struct member *mem, char *ifc) { + if(mem->lastattempt == NULL) { + mem->lastattempt = find_queue_ifc_use(ifc); + } + ast_debug(3, "%s updating lastattempttime\n", __func__ ); + mem->lastattempt->lastattempttime = time(NULL); +} + + static void update_realtime_members(struct call_queue *q); static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused); @@ -2473,6 +2571,15 @@ char *location; const char *macrocontext, *macroexten; + if (recent_queue_ifc_use(tmp->member, tmp->member->interface)) { + if (qe->chan->cdr) + ast_cdr_busy(qe->chan->cdr); + tmp->stillgoing = 0; + return 0; + } + + update_queue_ifc_use(tmp->member, tmp->member->interface); + /* on entry here, we know that tmp->chan == NULL */ if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) || (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {