[asterisk-commits] russell: branch russell/events r74157 - /team/russell/events/channels/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Jul 9 15:07:04 CDT 2007
Author: russell
Date: Mon Jul 9 15:07:03 2007
New Revision: 74157
URL: http://svn.digium.com/view/asterisk?view=rev&rev=74157
Log:
Add support for explicitly setting the state of agent groups. There are many
benefits to doing this, such as moving one step closer to having app_queue not
be required to poll chan_agent for device state changes. Also, the last known
state of agent groups will be cached, so checking for it doesn't require calling
into chan_agent and locking up the agents container while it figures it out.
Modified:
team/russell/events/channels/chan_agent.c
Modified: team/russell/events/channels/chan_agent.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/channels/chan_agent.c?view=diff&rev=74157&r1=74156&r2=74157
==============================================================================
--- team/russell/events/channels/chan_agent.c (original)
+++ team/russell/events/channels/chan_agent.c Mon Jul 9 15:07:03 2007
@@ -147,6 +147,8 @@
static char savecallsin[AST_MAX_BUF] = "";
static int updatecdr = 0;
static char beep[AST_MAX_BUF] = "beep";
+
+static enum ast_device_state group_states[sizeof(ast_group_t) * 8];
#define GETAGENTBYCALLERID "AGENTBYCALLERID"
@@ -176,6 +178,7 @@
char loginchan[80]; /**< channel they logged in from */
char logincallerid[80]; /**< Caller ID they had when they logged in */
struct ast_channel *chan; /**< Channel we use */
+ enum ast_device_state state; /*!< the last known state of this agent */
AST_LIST_ENTRY(agent_pvt) list; /**< Next Agent in the linked list. */
};
@@ -316,6 +319,7 @@
p->app_sleep_cond = 1;
p->group = group;
p->pending = pending;
+ p->state = AST_DEVICE_UNAVAILABLE;
AST_LIST_INSERT_TAIL(&agents, p, list);
}
@@ -694,9 +698,87 @@
pbx_builtin_setvar_helper(NULL, buf, agent);
}
+static void agent_set_group_state(int group_bit, enum ast_device_state state)
+{
+ int group = ffs(group_bit);
+
+ /* Should never happen ... */
+ if (!group)
+ return;
+
+ group--;
+
+ if (group >= ARRAY_LEN(group_states)) {
+ ast_log(LOG_ERROR, "Group '%d' is not a valid agent group!\n", group);
+ return;
+ }
+
+ if (state == group_states[group])
+ return;
+
+ group_states[group] = state;
+
+ /* Groups can be encoded in 2 formats ... */
+ ast_devstate_changed(state, "Agent/@%d", group);
+ ast_devstate_changed(state, "Agent/:%d", group);
+}
+
+/*!
+ * \brief Set the state of an agent and its groups as appropriate
+ *
+ * \note Agents are currently one of the following:
+ * AST_DEVICE_UNAVAILABLE
+ * AST_DEVICE_NOT_INUSE
+ * AST_DEVICE_BUSY
+ */
static void agent_set_state(struct agent_pvt *pvt, enum ast_device_state state)
{
+ int i;
+
+ if (pvt->state == state)
+ return;
+
+ pvt->state = state;
ast_devstate_changed(state, "Agent/%s", pvt->agent);
+
+ if (!pvt->group)
+ return;
+
+ /* Handle each group this agent is a member of */
+ for (i = 1; i < sizeof(ast_group_t) * 8; i <<= 1) {
+ /* Start with the state of this agent. */
+ enum ast_device_state group_state = state;
+ struct agent_pvt *cur;
+
+ /* If the agent is NOT_INUSE, then consider the group available */
+ if (group_state == AST_DEVICE_NOT_INUSE) {
+ agent_set_group_state(i, group_state);
+ continue;
+ }
+
+ /* Determine the group state based on the other agents in the group.
+ * If any agent is available (NOT_INUSE) set the group as available. */
+ AST_LIST_LOCK(&agents);
+ AST_LIST_TRAVERSE(&agents, cur, list) {
+ if (cur == pvt)
+ continue;
+ if (!(cur->group & i))
+ continue;
+
+ /* This agent is a member of the group */
+
+ if (cur->state == AST_DEVICE_NOT_INUSE) {
+ group_state = AST_DEVICE_NOT_INUSE;
+ break;
+ } else if (group_state == AST_DEVICE_UNAVAILABLE &&
+ cur->state == AST_DEVICE_BUSY) {
+ group_state = AST_DEVICE_BUSY;
+ }
+ }
+ AST_LIST_UNLOCK(&agents);
+
+ agent_set_group_state(i, group_state);
+ }
}
static int agent_hangup(struct ast_channel *ast)
@@ -985,7 +1067,7 @@
*
* \returns Always 0, or so it seems.
*/
-static int read_agent_config(void)
+static int read_agent_config(int reload)
{
struct ast_config *cfg;
struct ast_config *ucfg;
@@ -995,6 +1077,7 @@
const char *catname;
const char *hasagent;
int genhasagent;
+ int i;
group = 0;
autologoff = 0;
@@ -1017,6 +1100,11 @@
strcpy(recordformatext, "wav");
urlprefix[0] = '\0';
savecallsin[0] = '\0';
+
+ if (!reload) {
+ for (i = 0; i < ARRAY_LEN(group_states); i++)
+ group_states[i] = AST_DEVICE_UNKNOWN;
+ }
/* Read in [general] section for persistence */
if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents")))
@@ -2144,11 +2232,8 @@
/*! \brief Part of PBX channel interface
*
- * This module is now pretty close to not needing this callback at all, as it
- * provides state information explicitly in ast_devstate_changed() calls. However,
- * this function is still used to get the state of agent groups. To remove this
- * completely, changing the state of an agent throughout the module needs to be
- * smart enough to also change the state of agent groups as appropriate.
+ * This function is almost not needed. The module should set states for known agents
+ * and agent groups at load time, though, to ensure the cache gets populated.
*/
static int agent_devicestate(void *data)
{
@@ -2289,7 +2374,7 @@
return -1;
}
/* Read in the config */
- if (!read_agent_config())
+ if (!read_agent_config(0))
return AST_MODULE_LOAD_DECLINE;
if (persistent_agents)
reload_agents();
@@ -2312,7 +2397,7 @@
static int reload(void)
{
- read_agent_config();
+ read_agent_config(1);
if (persistent_agents)
reload_agents();
return 0;
More information about the asterisk-commits
mailing list