Index: apps/app_queue.c =================================================================== --- apps/app_queue.c (revision 368404) +++ apps/app_queue.c (working copy) @@ -1114,7 +1114,29 @@ struct ast_aoc_decoded *aoc_s_rate_list; }; +/*! \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[MAX_MUSICCLASS]; /*!< Name of musiconhold to be used */ @@ -1163,6 +1185,7 @@ unsigned int delme:1; /*!< Flag to delete entry on reload */ char rt_uniqueid[80]; /*!< Unique id of realtime member entry */ unsigned int ringinuse:1; /*!< Flag to ring queue members even if their status is 'inuse' */ + struct queue_ifc_use *lastattempt; /*!< Last time member was tried */ }; enum empty_conditions { @@ -1311,6 +1334,83 @@ 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 struct member *interface_exists(struct call_queue *q, const char *interface); static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused); @@ -3272,6 +3372,16 @@ const char *macrocontext, *macroexten; enum ast_device_state newstate; + if (recent_queue_ifc_use(tmp->member, tmp->member->interface)) { + if (ast_channel_cdr(qe->chan)) { + ast_cdr_busy(ast_channel_cdr(qe->chan)); + } + 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->member->paused) { ast_debug(1, "%s paused, can't receive call\n", tmp->interface);