mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
Merged revisions 107068 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r107068 | mmichelson | 2008-03-10 10:45:13 -0500 (Mon, 10 Mar 2008) | 10 lines app_queue has now been doxygenified thanks to snuffy! The ony thing I changed was the way that locks are referenced, since the old 1.2 names were still used in the comments. (closes issue #11997) Reported by: snuffy Patches: bug_11997_queue_doxy.diff uploaded by snuffy (license 35) ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@107069 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
260
apps/app_queue.c
260
apps/app_queue.c
@@ -93,7 +93,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/strings.h"
|
||||
#include "asterisk/global_datastores.h"
|
||||
|
||||
/* Please read before modifying this file.
|
||||
/*!
|
||||
* \par Please read before modifying this file.
|
||||
* There are three locks which are regularly used
|
||||
* throughout this file, the queue list lock, the lock
|
||||
* for each individual queue, and the interface list lock.
|
||||
@@ -132,17 +133,17 @@ static struct strategy {
|
||||
|
||||
#define DEFAULT_RETRY 5
|
||||
#define DEFAULT_TIMEOUT 15
|
||||
#define RECHECK 1 /* Recheck every second to see we we're at the top yet */
|
||||
#define MAX_PERIODIC_ANNOUNCEMENTS 10 /* The maximum periodic announcements we can have */
|
||||
#define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /* The minimum number of seconds between position announcements
|
||||
The default value of 15 provides backwards compatibility */
|
||||
#define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
|
||||
#define MAX_PERIODIC_ANNOUNCEMENTS 10 /*!< The maximum periodic announcements we can have */
|
||||
#define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15 /*!< The minimum number of seconds between position announcements
|
||||
The default value of 15 provides backwards compatibility */
|
||||
#define MAX_QUEUE_BUCKETS 53
|
||||
|
||||
#define RES_OKAY 0 /* Action completed */
|
||||
#define RES_EXISTS (-1) /* Entry already exists */
|
||||
#define RES_OUTOFMEMORY (-2) /* Out of memory */
|
||||
#define RES_NOSUCHQUEUE (-3) /* No such queue */
|
||||
#define RES_NOT_DYNAMIC (-4) /* Member is not dynamic */
|
||||
#define RES_OKAY 0 /*!< Action completed */
|
||||
#define RES_EXISTS (-1) /*!< Entry already exists */
|
||||
#define RES_OUTOFMEMORY (-2) /*!< Out of memory */
|
||||
#define RES_NOSUCHQUEUE (-3) /*!< No such queue */
|
||||
#define RES_NOT_DYNAMIC (-4) /*!< Member is not dynamic */
|
||||
|
||||
static char *app = "Queue";
|
||||
|
||||
@@ -313,15 +314,16 @@ const struct {
|
||||
};
|
||||
|
||||
/*! \brief We define a custom "local user" structure because we
|
||||
use it not only for keeping track of what is in use but
|
||||
also for keeping track of who we're dialing.
|
||||
|
||||
There are two "links" defined in this structure, q_next and call_next.
|
||||
q_next links ALL defined callattempt structures into a linked list. call_next is
|
||||
a link which allows for a subset of the callattempts to be traversed. This subset
|
||||
is used in wait_for_answer so that irrelevant callattempts are not traversed. This
|
||||
also is helpful so that queue logs are always accurate in the case where a call to
|
||||
a member times out, especially if using the ringall strategy. */
|
||||
* use it not only for keeping track of what is in use but
|
||||
* also for keeping track of who we're dialing.
|
||||
*
|
||||
* There are two "links" defined in this structure, q_next and call_next.
|
||||
* q_next links ALL defined callattempt structures into a linked list. call_next is
|
||||
* a link which allows for a subset of the callattempts to be traversed. This subset
|
||||
* is used in wait_for_answer so that irrelevant callattempts are not traversed. This
|
||||
* also is helpful so that queue logs are always accurate in the case where a call to
|
||||
* a member times out, especially if using the ringall strategy.
|
||||
*/
|
||||
|
||||
struct callattempt {
|
||||
struct callattempt *q_next;
|
||||
@@ -343,7 +345,7 @@ struct queue_ent {
|
||||
char announce[80]; /*!< Announcement to play for member when call is answered */
|
||||
char context[AST_MAX_CONTEXT]; /*!< Context when user exits queue */
|
||||
char digits[AST_MAX_EXTENSION]; /*!< Digits entered while in queue */
|
||||
int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
|
||||
int valid_digits; /*!< Digits entered correspond to valid extension. Exited */
|
||||
int pos; /*!< Where we are in the queue */
|
||||
int prio; /*!< Our priority */
|
||||
int last_pos_said; /*!< Last position we told the user */
|
||||
@@ -355,8 +357,8 @@ struct queue_ent {
|
||||
int pending; /*!< Non-zero if we are attempting to call a member */
|
||||
int max_penalty; /*!< Limit the members that can take this call to this penalty or lower */
|
||||
int min_penalty; /*!< Limit the members that can take this call to this penalty or higher */
|
||||
int linpos; /*!< If using linear strategy, what position are we at? */
|
||||
int linwrapped; /*!< Is the linpos wrapped? */
|
||||
int linpos; /*!< If using linear strategy, what position are we at? */
|
||||
int linwrapped; /*!< Is the linpos wrapped? */
|
||||
time_t start; /*!< When we started holding */
|
||||
time_t expire; /*!< When this entry should expire (time out of queue) */
|
||||
struct ast_channel *chan; /*!< Our channel */
|
||||
@@ -572,6 +574,7 @@ static inline struct call_queue *queue_unref(struct call_queue *q)
|
||||
return q;
|
||||
}
|
||||
|
||||
/*! \brief Set variables of queue */
|
||||
static void set_queue_variables(struct queue_ent *qe)
|
||||
{
|
||||
|
||||
@@ -666,7 +669,12 @@ struct statechange {
|
||||
int state;
|
||||
char dev[0];
|
||||
};
|
||||
/*! \brief set a member's status based on device state of that member's state_interface*/
|
||||
|
||||
/*! \brief set a member's status based on device state of that member's state_interface.
|
||||
*
|
||||
* Lock interface list find sc, iterate through each queues queue_member list for member to
|
||||
* update state inside queues
|
||||
*/
|
||||
static void *handle_statechange(struct statechange *sc)
|
||||
{
|
||||
struct call_queue *q;
|
||||
@@ -751,9 +759,7 @@ static void *handle_statechange(struct statechange *sc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Data used by the device state thread
|
||||
*/
|
||||
/*! \brief Data used by the device state thread */
|
||||
static struct {
|
||||
/*! Set to 1 to stop the thread */
|
||||
unsigned int stop:1;
|
||||
@@ -803,6 +809,7 @@ static void *device_state_thread(void *data)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*! \brief Producer of the statechange queue */
|
||||
static int statechange_queue(const char *dev, enum ast_device_state state)
|
||||
{
|
||||
@@ -821,6 +828,7 @@ static int statechange_queue(const char *dev, enum ast_device_state state)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_state_cb(const struct ast_event *event, void *unused)
|
||||
{
|
||||
enum ast_device_state state;
|
||||
@@ -891,6 +899,10 @@ static int member_cmp_fn(void *obj1, void *obj2, int flags)
|
||||
return strcasecmp(mem1->interface, mem2->interface) ? 0 : CMP_MATCH;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initialize Queue default values.
|
||||
* \note the queue's lock must be held before executing this function
|
||||
*/
|
||||
static void init_queue(struct call_queue *q)
|
||||
{
|
||||
int i;
|
||||
@@ -1049,7 +1061,15 @@ static void clear_and_free_interfaces(void)
|
||||
AST_LIST_UNLOCK(&interfaces);
|
||||
}
|
||||
|
||||
/*Note: call this with the rule_lists locked */
|
||||
/*!
|
||||
* \brief Change queue penalty by adding rule.
|
||||
*
|
||||
* Check rule for errors with time or fomatting, see if rule is relative to rest
|
||||
* of queue, iterate list of rules to find correct insertion point, insert and return.
|
||||
* \retval -1 on failure
|
||||
* \retval 0 on success
|
||||
* \note Call this with the rule_lists locked
|
||||
*/
|
||||
static int insert_penaltychange (const char *list_name, const char *content, const int linenum)
|
||||
{
|
||||
char *timestr, *maxstr, *minstr, *contentdup;
|
||||
@@ -1122,12 +1142,13 @@ static int insert_penaltychange (const char *list_name, const char *content, con
|
||||
}
|
||||
|
||||
/*! \brief Configure a queue parameter.
|
||||
\par
|
||||
For error reporting, line number is passed for .conf static configuration.
|
||||
For Realtime queues, linenum is -1.
|
||||
The failunknown flag is set for config files (and static realtime) to show
|
||||
errors for unknown parameters. It is cleared for dynamic realtime to allow
|
||||
extra fields in the tables. */
|
||||
*
|
||||
* The failunknown flag is set for config files (and static realtime) to show
|
||||
* errors for unknown parameters. It is cleared for dynamic realtime to allow
|
||||
* extra fields in the tables.
|
||||
* \note For error reporting, line number is passed for .conf static configuration,
|
||||
* for Realtime queues, linenum is -1.
|
||||
*/
|
||||
static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
|
||||
{
|
||||
if (!strcasecmp(param, "musicclass") ||
|
||||
@@ -1294,6 +1315,12 @@ static void queue_set_param(struct call_queue *q, const char *param, const char
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Find rt member record to update otherwise create one.
|
||||
*
|
||||
* Search for member in queue, if found update penalty/paused state,
|
||||
* if no memeber exists create one flag it as a RT member and add to queue member list.
|
||||
*/
|
||||
static void rt_handle_member_record(struct call_queue *q, char *interface, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface)
|
||||
{
|
||||
struct member *m, tmpmem;
|
||||
@@ -1341,6 +1368,7 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, const
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Iterate through queue's member list and delete them */
|
||||
static void free_members(struct call_queue *q, int all)
|
||||
{
|
||||
/* Free non-dynamic members */
|
||||
@@ -1357,6 +1385,7 @@ static void free_members(struct call_queue *q, int all)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Free queue's member list then its string fields */
|
||||
static void destroy_queue(void *obj)
|
||||
{
|
||||
struct call_queue *q = obj;
|
||||
@@ -1387,9 +1416,16 @@ static struct call_queue *alloc_queue(const char *queuename)
|
||||
return q;
|
||||
}
|
||||
|
||||
/*!\brief Reload a single queue via realtime.
|
||||
\return Return the queue, or NULL if it doesn't exist.
|
||||
\note Should be called with the global qlock locked. */
|
||||
/*!
|
||||
* \brief Reload a single queue via realtime.
|
||||
*
|
||||
* Check for statically defined queue first, check if deleted RT queue,
|
||||
* check for new RT queue, if queue vars are not defined init them with defaults.
|
||||
* reload RT queue vars, set RT queue members dead and reload them, return finished queue.
|
||||
* \retval the queue,
|
||||
* \retval NULL if it doesn't exist.
|
||||
* \note Should be called with the "queues" container locked.
|
||||
*/
|
||||
static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
|
||||
{
|
||||
struct ast_variable *v;
|
||||
@@ -1530,7 +1566,7 @@ static struct call_queue *load_realtime_queue(const char *queuename)
|
||||
q = ao2_find(queues, &tmpq, OBJ_POINTER);
|
||||
|
||||
if (!q || q->realtime) {
|
||||
/*! \note Load from realtime before taking the global qlock, to avoid blocking all
|
||||
/*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
|
||||
queue operations while waiting for the DB.
|
||||
|
||||
This will be two separate database transactions, so we might
|
||||
@@ -1708,6 +1744,11 @@ static int play_file(struct ast_channel *chan, const char *filename)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Check for valid exit from queue via goto
|
||||
* \retval 0 if failure
|
||||
* \retval 1 if successful
|
||||
*/
|
||||
static int valid_exit(struct queue_ent *qe, char digit)
|
||||
{
|
||||
int digitlen = strlen(qe->digits);
|
||||
@@ -1867,7 +1908,11 @@ static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
|
||||
ao2_unlock(qe->parent);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Caller leaving queue.
|
||||
*
|
||||
* Search the queue to find the leaving client, if found remove from queue
|
||||
* create manager event, move others up the queue.
|
||||
*/
|
||||
static void leave_queue(struct queue_ent *qe)
|
||||
{
|
||||
struct call_queue *q;
|
||||
@@ -1922,7 +1967,7 @@ static void leave_queue(struct queue_ent *qe)
|
||||
queue_unref(q);
|
||||
}
|
||||
|
||||
/* Hang up a list of outgoing calls */
|
||||
/*! \brief Hang up a list of outgoing calls */
|
||||
static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception)
|
||||
{
|
||||
struct callattempt *oo;
|
||||
@@ -1988,8 +2033,11 @@ static int update_dial_status(struct call_queue *q, struct member *member, int s
|
||||
return update_status(q, member, status);
|
||||
}
|
||||
|
||||
/* traverse all defined queues which have calls waiting and contain this member
|
||||
return 0 if no other queue has precedence (higher weight) or 1 if found */
|
||||
/*!
|
||||
* \brief traverse all defined queues which have calls waiting and contain this member
|
||||
* \retval 0 if no other queue has precedence (higher weight)
|
||||
* \retval 1 if found
|
||||
*/
|
||||
static int compare_weight(struct call_queue *rq, struct member *member)
|
||||
{
|
||||
struct call_queue *q;
|
||||
@@ -1997,7 +2045,7 @@ static int compare_weight(struct call_queue *rq, struct member *member)
|
||||
int found = 0;
|
||||
struct ao2_iterator queue_iter;
|
||||
|
||||
/* &qlock and &rq->lock already set by try_calling()
|
||||
/* q's lock and rq's lock already set by try_calling()
|
||||
* to solve deadlock */
|
||||
queue_iter = ao2_iterator_init(queues, 0);
|
||||
while ((q = ao2_iterator_next(&queue_iter))) {
|
||||
@@ -2034,6 +2082,7 @@ static void do_hang(struct callattempt *o)
|
||||
o->chan = NULL;
|
||||
}
|
||||
|
||||
/*! \brief convert "\n" to "\nVariable: " ready for manager to use */
|
||||
static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
|
||||
{
|
||||
struct ast_str *buf = ast_str_alloca(len + 1);
|
||||
@@ -2071,10 +2120,19 @@ static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
|
||||
return vars;
|
||||
}
|
||||
|
||||
/*! \brief Part 2 of ring_one
|
||||
/*!
|
||||
* \brief Part 2 of ring_one
|
||||
*
|
||||
* Does error checking before attempting to request a channel and call a member. This
|
||||
* function is only called from ring_one
|
||||
* Does error checking before attempting to request a channel and call a member.
|
||||
* This function is only called from ring_one().
|
||||
* Failure can occur if:
|
||||
* - Agent on call
|
||||
* - Agent is paused
|
||||
* - Wrapup time not expired
|
||||
* - Priority by another queue
|
||||
*
|
||||
* \retval 1 on success to reach a free agent
|
||||
* \retval 0 on failure to get agent.
|
||||
*/
|
||||
static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
|
||||
{
|
||||
@@ -2224,13 +2282,15 @@ static struct callattempt *find_best(struct callattempt *outgoing)
|
||||
return best;
|
||||
}
|
||||
|
||||
/*! \brief Place a call to a queue member
|
||||
/*!
|
||||
* \brief Place a call to a queue member.
|
||||
*
|
||||
* Once metrics have been calculated for each member, this function is used
|
||||
* to place a call to the appropriate member (or members). The low-level
|
||||
* channel-handling and error detection is handled in ring_entry
|
||||
*
|
||||
* Returns 1 if a member was called successfully, 0 otherwise
|
||||
* \retval 1 if a member was called successfully
|
||||
* \retval 0 otherwise
|
||||
*/
|
||||
static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
|
||||
{
|
||||
@@ -2261,6 +2321,7 @@ static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *bus
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*! \brief Search for best metric and add to Round Robbin queue */
|
||||
static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
|
||||
{
|
||||
struct callattempt *best = find_best(outgoing);
|
||||
@@ -2284,6 +2345,7 @@ static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Search for best metric and add to Linear queue */
|
||||
static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
|
||||
{
|
||||
struct callattempt *best = find_best(outgoing);
|
||||
@@ -2307,6 +2369,7 @@ static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Playback announcement to queued members if peroid has elapsed */
|
||||
static int say_periodic_announcement(struct queue_ent *qe, int ringing)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -2357,6 +2420,7 @@ static int say_periodic_announcement(struct queue_ent *qe, int ringing)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! \brief Record that a caller gave up on waiting in queue */
|
||||
static void record_abandoned(struct queue_ent *qe)
|
||||
{
|
||||
ao2_lock(qe->parent);
|
||||
@@ -2645,7 +2709,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
|
||||
|
||||
return peer;
|
||||
}
|
||||
/*! \brief Check if we should start attempting to call queue members
|
||||
|
||||
/*!
|
||||
* \brief Check if we should start attempting to call queue members.
|
||||
*
|
||||
* The behavior of this function is dependent first on whether autofill is enabled
|
||||
* and second on whether the ring strategy is ringall. If autofill is not enabled,
|
||||
@@ -2723,6 +2789,13 @@ static int is_our_turn(struct queue_ent *qe)
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief update rules for queues
|
||||
*
|
||||
* Calculate min/max penalties making sure if relative they stay within bounds.
|
||||
* Update queues penalty and set dialplan vars, goto next list entry.
|
||||
*/
|
||||
static void update_qe_rule(struct queue_ent *qe)
|
||||
{
|
||||
int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
|
||||
@@ -2823,6 +2896,10 @@ static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *r
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief update the queue status
|
||||
* \retval Always 0
|
||||
*/
|
||||
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl)
|
||||
{
|
||||
struct member *mem;
|
||||
@@ -2862,6 +2939,8 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom
|
||||
* A numeric metric is given to each member depending on the ring strategy used
|
||||
* by the queue. Members with lower metrics will be called before members with
|
||||
* higher metrics
|
||||
* \retval -1 if penalties are exceeded
|
||||
* \retval 0 otherwise
|
||||
*/
|
||||
static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
|
||||
{
|
||||
@@ -2926,6 +3005,7 @@ enum agent_complete_reason {
|
||||
TRANSFER
|
||||
};
|
||||
|
||||
/*! \brief Send out AMI message with member call completion status information */
|
||||
static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
|
||||
const struct ast_channel *peer, const struct member *member, time_t callstart,
|
||||
char *vars, size_t vars_len, enum agent_complete_reason rsn)
|
||||
@@ -2961,6 +3041,7 @@ static void send_agent_complete(const struct queue_ent *qe, const char *queuenam
|
||||
(long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
|
||||
qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
|
||||
}
|
||||
|
||||
/*! \brief A large function which calls members, updates statistics, and bridges the caller and a member
|
||||
*
|
||||
* Here is the process of this function
|
||||
@@ -3649,10 +3730,9 @@ static struct member *interface_exists(struct call_queue *q, const char *interfa
|
||||
}
|
||||
|
||||
|
||||
/* Dump all members in a specific queue to the database
|
||||
/*! \brief Dump all members in a specific queue to the database
|
||||
*
|
||||
* <pm_family>/<queuename> = <interface>;<penalty>;<paused>[|...]
|
||||
*
|
||||
*/
|
||||
static void dump_queue_members(struct call_queue *pm_queue)
|
||||
{
|
||||
@@ -3694,6 +3774,12 @@ static void dump_queue_members(struct call_queue *pm_queue)
|
||||
ast_db_del(pm_family, pm_queue->name);
|
||||
}
|
||||
|
||||
/*! \brief Remove member from queue
|
||||
* \retval RES_NOT_DYNAMIC when they aren't a RT member
|
||||
* \retval RES_NOSUCHQUEUE queue does not exist
|
||||
* \retval RES_OKAY removed member from queue
|
||||
* \retval RES_EXISTS queue exists but no members
|
||||
*/
|
||||
static int remove_from_queue(const char *queuename, const char *interface)
|
||||
{
|
||||
struct call_queue *q, tmpq = {
|
||||
@@ -3736,14 +3822,20 @@ static int remove_from_queue(const char *queuename, const char *interface)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Add member to queue
|
||||
* \retval RES_NOT_DYNAMIC when they aren't a RT member
|
||||
* \retval RES_NOSUCHQUEUE queue does not exist
|
||||
* \retval RES_OKAY added member from queue
|
||||
* \retval RES_EXISTS queue exists but no members
|
||||
* \retval RES_OUT_OF_MEMORY queue exists but not enough memory to create member
|
||||
*/
|
||||
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
|
||||
{
|
||||
struct call_queue *q;
|
||||
struct member *new_member, *old_member;
|
||||
int res = RES_NOSUCHQUEUE;
|
||||
|
||||
/* \note Ensure the appropriate realtime queue is loaded. Note that this
|
||||
/*! \note Ensure the appropriate realtime queue is loaded. Note that this
|
||||
* short-circuits if the queue is already in memory. */
|
||||
if (!(q = load_realtime_queue(queuename)))
|
||||
return res;
|
||||
@@ -3896,8 +3988,8 @@ static int set_member_penalty(char *queuename, char *interface, int penalty)
|
||||
}
|
||||
|
||||
/* \brief Gets members penalty.
|
||||
*
|
||||
* \return Return the members penalty or RESULT_FAILURE on error. */
|
||||
* \return Return the members penalty or RESULT_FAILURE on error.
|
||||
*/
|
||||
static int get_member_penalty(char *queuename, char *interface)
|
||||
{
|
||||
int foundqueue = 0, penalty;
|
||||
@@ -3928,7 +4020,7 @@ static int get_member_penalty(char *queuename, char *interface)
|
||||
return RESULT_FAILURE;
|
||||
}
|
||||
|
||||
/* Reload dynamic queue members persisted into the astdb */
|
||||
/*! \brief Reload dynamic queue members persisted into the astdb */
|
||||
static void reload_queue_members(void)
|
||||
{
|
||||
char *cur_ptr;
|
||||
@@ -4025,6 +4117,7 @@ static void reload_queue_members(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief PauseQueueMember application */
|
||||
static int pqm_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *parse;
|
||||
@@ -4036,7 +4129,7 @@ static int pqm_exec(struct ast_channel *chan, void *data)
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename]|interface[|options][|reason])\n");
|
||||
ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename],interface[,options][,reason])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4045,7 +4138,7 @@ static int pqm_exec(struct ast_channel *chan, void *data)
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (ast_strlen_zero(args.interface)) {
|
||||
ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface[|options[|reason]])\n");
|
||||
ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4060,6 +4153,7 @@ static int pqm_exec(struct ast_channel *chan, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief UnPauseQueueMember application */
|
||||
static int upqm_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *parse;
|
||||
@@ -4071,7 +4165,7 @@ static int upqm_exec(struct ast_channel *chan, void *data)
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename]|interface[|options[|reason]])\n");
|
||||
ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename],interface[,options[,reason]])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4080,7 +4174,7 @@ static int upqm_exec(struct ast_channel *chan, void *data)
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (ast_strlen_zero(args.interface)) {
|
||||
ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename]|interface[|options[|reason]])\n");
|
||||
ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4095,6 +4189,7 @@ static int upqm_exec(struct ast_channel *chan, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief RemoveQueueMember application */
|
||||
static int rqm_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
@@ -4107,7 +4202,7 @@ static int rqm_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[|interface[|options]])\n");
|
||||
ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[,interface[,options]])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4149,6 +4244,7 @@ static int rqm_exec(struct ast_channel *chan, void *data)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! \brief AddQueueMember application */
|
||||
static int aqm_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
@@ -4164,7 +4260,7 @@ static int aqm_exec(struct ast_channel *chan, void *data)
|
||||
int penalty = 0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[|[interface]|[penalty][|options][|membername]])\n");
|
||||
ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,[interface],[penalty][,options][,membername]])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4211,6 +4307,7 @@ static int aqm_exec(struct ast_channel *chan, void *data)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*! \brief QueueLog application */
|
||||
static int ql_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *parse;
|
||||
@@ -4224,7 +4321,7 @@ static int ql_exec(struct ast_channel *chan, void *data)
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "QueueLog requires arguments (queuename|uniqueid|membername|event[|additionalinfo]\n");
|
||||
ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4234,7 +4331,7 @@ static int ql_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (ast_strlen_zero(args.queuename) || ast_strlen_zero(args.uniqueid)
|
||||
|| ast_strlen_zero(args.membername) || ast_strlen_zero(args.event)) {
|
||||
ast_log(LOG_WARNING, "QueueLog requires arguments (queuename|uniqueid|membername|event[|additionalinfo])\n");
|
||||
ast_log(LOG_WARNING, "QueueLog requires arguments (queuename,uniqueid,membername,event[,additionalinfo])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4244,6 +4341,7 @@ static int ql_exec(struct ast_channel *chan, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Copy rule from global list into specified queue */
|
||||
static void copy_rules(struct queue_ent *qe, const char *rulename)
|
||||
{
|
||||
struct penalty_rule *pr_iter;
|
||||
@@ -4557,6 +4655,11 @@ stop:
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief create interface var with all queue details.
|
||||
* \retval 0 on success
|
||||
* \retval -1 on error
|
||||
*/
|
||||
static int queue_function_var(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
int res = -1;
|
||||
@@ -4598,6 +4701,11 @@ static int queue_function_var(struct ast_channel *chan, const char *cmd, char *d
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Get number either busy / free or total members of a specific queue
|
||||
* \retval number of members (busy / free / total)
|
||||
* \retval -1 on error
|
||||
*/
|
||||
static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
int count = 0;
|
||||
@@ -4647,6 +4755,11 @@ static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *d
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Get the total number of members in a specific queue (Deprecated)
|
||||
* \retval number of members
|
||||
* \retval -1 on error
|
||||
*/
|
||||
static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
int count = 0;
|
||||
@@ -4685,7 +4798,7 @@ static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, cha
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue */
|
||||
static int queue_function_queuewaitingcount(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
int count = 0;
|
||||
@@ -4697,7 +4810,7 @@ static int queue_function_queuewaitingcount(struct ast_channel *chan, const char
|
||||
buf[0] = '\0';
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
|
||||
ast_log(LOG_ERROR, "QUEUE_WAITING_COUNT requires an argument: queuename\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4721,6 +4834,7 @@ static int queue_function_queuewaitingcount(struct ast_channel *chan, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue */
|
||||
static int queue_function_queuememberlist(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
struct call_queue *q, tmpq = {
|
||||
@@ -4768,8 +4882,7 @@ static int queue_function_queuememberlist(struct ast_channel *chan, const char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Dialplan function QUEUE_MEMBER_PENALTY()
|
||||
* Gets the members penalty. */
|
||||
/*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty. */
|
||||
static int queue_function_memberpenalty_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
int penalty;
|
||||
@@ -4800,8 +4913,7 @@ static int queue_function_memberpenalty_read(struct ast_channel *chan, const cha
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Dialplan function QUEUE_MEMBER_PENALTY()
|
||||
* Sets the members penalty. */
|
||||
/*! \brief Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty. */
|
||||
static int queue_function_memberpenalty_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
|
||||
{
|
||||
int penalty;
|
||||
@@ -5178,6 +5290,12 @@ static void do_print(struct mansession *s, int fd, const char *str)
|
||||
ast_cli(fd, "%s\n", str);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Show queue(s) status and statistics
|
||||
*
|
||||
* List the queues strategy, calls processed, members logged in,
|
||||
* other queue statistics such as avg hold time.
|
||||
*/
|
||||
static char *__queues_show(struct mansession *s, int fd, int argc, char **argv)
|
||||
{
|
||||
struct call_queue *q;
|
||||
@@ -5355,7 +5473,7 @@ static int manager_queue_rule_show(struct mansession *s, const struct message *m
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Dump summary of queue info */
|
||||
/*! \brief Summary of queue info via the AMI */
|
||||
static int manager_queues_summary(struct mansession *s, const struct message *m)
|
||||
{
|
||||
time_t now;
|
||||
@@ -5427,7 +5545,7 @@ static int manager_queues_summary(struct mansession *s, const struct message *m)
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Dump queue status */
|
||||
/*! \brief Queue status info via AMI */
|
||||
static int manager_queues_status(struct mansession *s, const struct message *m)
|
||||
{
|
||||
time_t now;
|
||||
|
Reference in New Issue
Block a user