mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	Fix autofill behavior in app_queue and document it's functionality in queues.conf.sample and UPGRADE.txt
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@24543 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										20
									
								
								UPGRADE.txt
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								UPGRADE.txt
									
									
									
									
									
								
							| @@ -73,6 +73,26 @@ Applications: | ||||
|   queue member channel that is taking the call. This is useful when trying  | ||||
|   to link recording filenames back to a particular call from the queue.   | ||||
|  | ||||
| * The old/current behavior of app_queue has a serial type behavior | ||||
|   in that the queue will make all waiting callers wait in the queue | ||||
|   even if there is more than one available member ready to take | ||||
|   calls until the head caller is connected with the member they | ||||
|   were trying to get to. The next waiting caller in line then | ||||
|   becomes the head caller, and they are then connected with the | ||||
|   next available member and all available members and waiting callers | ||||
|   waits while this happens. This cycle continues until there are | ||||
|   no more available members or waiting callers, whichever comes first. | ||||
|   The new behavior, enabled by setting autofill=yes in queues.conf | ||||
|   either at the [general] level to default for all queues or  | ||||
|   to set on a per-queue level, makes sure that when the waiting  | ||||
|   callers are connecting with available members in a parallel fashion  | ||||
|   until there are no more available members or no more waiting callers, | ||||
|   whichever comes first. This is probably more along the lines of how | ||||
|   one would expect a queue should work and in most cases, you will want  | ||||
|   to enable this new behavior. If you do not specify or comment out this  | ||||
|   option, it will default to "no" to keep backward compatability with the old  | ||||
|   behavior. | ||||
|  | ||||
| Manager: | ||||
|  | ||||
| * After executing the 'status' manager action, the "Status" manager events | ||||
|   | ||||
| @@ -234,6 +234,9 @@ static int queue_persistent_members = 0; | ||||
| /*! \brief queues.conf per-queue weight option */ | ||||
| static int use_weight = 0; | ||||
|  | ||||
| /*! \brief queues.conf [general] option */ | ||||
| static int autofill_default = 0; | ||||
|  | ||||
| enum queue_result { | ||||
| 	QUEUE_UNKNOWN = 0, | ||||
| 	QUEUE_TIMEOUT = 1, | ||||
| @@ -575,6 +578,7 @@ static void init_queue(struct ast_call_queue *q) | ||||
| 	q->roundingseconds = 0; /* Default - don't announce seconds */ | ||||
| 	q->servicelevel = 0; | ||||
| 	q->ringinuse = 1; | ||||
| 	q->autofill = autofill_default; | ||||
| 	q->moh[0] = '\0'; | ||||
| 	q->announce[0] = '\0'; | ||||
| 	q->context[0] = '\0'; | ||||
| @@ -1860,25 +1864,75 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte | ||||
| 	} | ||||
|  | ||||
| 	return peer; | ||||
| 	 | ||||
| } | ||||
|  | ||||
| static int is_our_turn(struct queue_ent *qe) | ||||
| { | ||||
| 	struct queue_ent *ch; | ||||
| 	struct member *cur; | ||||
| 	int avl = 0; | ||||
| 	int idx = 0; | ||||
| 	int res; | ||||
|  | ||||
| 	/* Atomically read the parent head -- does not need a lock */ | ||||
| 	ch = qe->parent->head; | ||||
| 	/* If we are now at the top of the head, break out */ | ||||
| 	if ((ch == qe) || (qe->parent->autofill)) { | ||||
| 		if (option_debug) | ||||
| 			ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name); | ||||
| 		res = 1; | ||||
| 	if (!qe->parent->autofill) { | ||||
|  | ||||
| 		/* Atomically read the parent head -- does not need a lock */ | ||||
| 		ch = qe->parent->head; | ||||
| 		/* If we are now at the top of the head, break out */ | ||||
| 		if ((ch == qe) || (qe->parent->autofill)) { | ||||
| 			if (option_debug) | ||||
| 				ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name); | ||||
| 			res = 1; | ||||
| 		} else { | ||||
| 			if (option_debug) | ||||
| 				ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name); | ||||
| 			res = 0; | ||||
| 		}	 | ||||
|  | ||||
| 	} else { | ||||
|  | ||||
| 		/* This needs a lock. How many members are available to be served? */ | ||||
| 	 | ||||
| 		ast_mutex_lock(&qe->parent->lock); | ||||
| 			 | ||||
| 		ch = qe->parent->head; | ||||
| 		cur = qe->parent->members; | ||||
| 	 | ||||
| 		while (cur) { | ||||
| 			if (cur->status == 1)  | ||||
| 				avl++; | ||||
| 			cur = cur->next; | ||||
| 		} | ||||
|  | ||||
| 		if (option_debug) | ||||
| 			ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name); | ||||
| 		res = 0; | ||||
| 			ast_log(LOG_DEBUG, "There are %d available members.\n", avl); | ||||
| 	 | ||||
| 		if (qe->parent->strategy == 1) { | ||||
| 			if (option_debug) | ||||
| 				ast_log(LOG_DEBUG, "Even though there are %d available members, the strategy is ringall so only the head call is allowed in!\n", avl); | ||||
| 			avl = 1; | ||||
| 		} | ||||
| 	 | ||||
| 		while ((idx < avl) && (ch) && (ch != qe)) { | ||||
| 			idx++; | ||||
| 			ch = ch->next;			 | ||||
| 		} | ||||
| 	 | ||||
| 		/* If the queue entry is within avl [the number of available members] calls from the top ... */ | ||||
| 		if (ch && idx < avl) { | ||||
| 			if (option_debug) | ||||
| 				ast_log(LOG_DEBUG, "It's our turn (%s).\n", qe->chan->name); | ||||
| 			res = 1; | ||||
| 		} else { | ||||
| 			if (option_debug) | ||||
| 				ast_log(LOG_DEBUG, "It's not our turn (%s).\n", qe->chan->name); | ||||
| 			res = 0; | ||||
| 		} | ||||
| 		 | ||||
| 		ast_mutex_unlock(&qe->parent->lock); | ||||
| 	} | ||||
|  | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| @@ -3302,6 +3356,9 @@ static void reload_queues(void) | ||||
| 			queue_persistent_members = 0; | ||||
| 			if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) | ||||
| 				queue_persistent_members = ast_true(general_val); | ||||
| 			autofill_default = 0; | ||||
| 			if ((general_val = ast_variable_retrieve(cfg, "general", "autofill"))) | ||||
| 				autofill_default = ast_true(general_val); | ||||
| 		} else {	/* Define queue */ | ||||
| 			/* Look for an existing one */ | ||||
| 			AST_LIST_TRAVERSE(&queues, q, list) { | ||||
|   | ||||
| @@ -8,6 +8,25 @@ | ||||
| ;    read into their recorded queues. Default is 'yes'. | ||||
| ; | ||||
| persistentmembers = yes | ||||
| ;  | ||||
| ; AutoFill Behavior | ||||
| ;    The old/current behavior of the queue has a serial type behavior  | ||||
| ;    in that the queue will make all waiting callers wait in the queue | ||||
| ;    even if there is more than one available member ready to take | ||||
| ;    calls until the head caller is connected with the member they  | ||||
| ;    were trying to get to. The next waiting caller in line then | ||||
| ;    becomes the head caller, and they are then connected with the | ||||
| ;    next available member and all available members and waiting callers | ||||
| ;    waits while this happens. The new behavior, enabled by setting | ||||
| ;    autofill=yes makes sure that when the waiting callers are connecting | ||||
| ;    with available members in a parallel fashion until there are | ||||
| ;    no more available members or no more waiting callers. This is | ||||
| ;    probably more along the lines of how a queue should work and  | ||||
| ;    in most cases, you will want to enable this behavior. If you  | ||||
| ;    do not specify or comment out this option, it will default to no | ||||
| ;    to keep backward compatability with the old behavior. | ||||
| ; | ||||
| autofill = yes | ||||
| ; | ||||
| ; Note that a timeout to fail out of a queue may be passed as part of | ||||
| ; an application call from extensions.conf: | ||||
| @@ -73,11 +92,9 @@ persistentmembers = yes | ||||
| ;wrapuptime=15 | ||||
| ; | ||||
| ; Autofill will follow queue strategy but push multiple calls through | ||||
| ; at same time. WARNING: By setting this to yes, if you have a number | ||||
| ; of calls waiting in queue, and only a single member becoming available | ||||
| ; at a time, it is more than likely NOT going to be the caller that's | ||||
| ; been waiting the longest that will get assigned to this newly available | ||||
| ; queue member. | ||||
| ; at same time until there are no more waiting callers or no more | ||||
| ; available members. The per-queue setting of autofill allows you | ||||
| ; to override the default setting on an individual queue level. | ||||
| ;  | ||||
| ;autofill=yes | ||||
| ; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user