diff --git a/src/mod/applications/mod_callcenter/conf/autoload_configs/callcenter.conf.xml b/src/mod/applications/mod_callcenter/conf/autoload_configs/callcenter.conf.xml
index a069413ac6..51a472615a 100644
--- a/src/mod/applications/mod_callcenter/conf/autoload_configs/callcenter.conf.xml
+++ b/src/mod/applications/mod_callcenter/conf/autoload_configs/callcenter.conf.xml
@@ -2,6 +2,7 @@
+
diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c
index a04dd300c8..f1ce9651e5 100644
--- a/src/mod/applications/mod_callcenter/mod_callcenter.c
+++ b/src/mod/applications/mod_callcenter/mod_callcenter.c
@@ -119,7 +119,8 @@ typedef enum {
CC_AGENT_STATE_WAITING = 1,
CC_AGENT_STATE_RECEIVING = 2,
CC_AGENT_STATE_IN_A_QUEUE_CALL = 3,
- CC_AGENT_STATE_IDLE = 4
+ CC_AGENT_STATE_IDLE = 4,
+ CC_AGENT_STATE_RESERVED = 5
} cc_agent_state_t;
static struct cc_state_table AGENT_STATE_CHART[] = {
@@ -128,6 +129,7 @@ static struct cc_state_table AGENT_STATE_CHART[] = {
{"Receiving", CC_AGENT_STATE_RECEIVING},
{"In a queue call", CC_AGENT_STATE_IN_A_QUEUE_CALL},
{"Idle", CC_AGENT_STATE_IDLE},
+ {"Reserved", CC_AGENT_STATE_RESERVED},
{NULL, 0}
};
@@ -412,6 +414,7 @@ static struct {
int debug;
char *odbc_dsn;
char *dbname;
+ switch_bool_t reserve_agents;
int32_t threads;
int32_t running;
switch_mutex_t *mutex;
@@ -555,6 +558,15 @@ cc_queue_t *queue_set_config(cc_queue_t *queue)
}
+static int cc_execute_sql_affected_rows(char *sql) {
+ switch_cache_db_handle_t *dbh = NULL;
+ if (!(dbh = cc_get_db_handle())) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
+ return -1;
+ }
+ switch_cache_db_execute_sql(dbh, sql, NULL);
+ return switch_cache_db_affected_rows(dbh);
+}
char *cc_execute_sql2str(cc_queue_t *queue, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len)
{
@@ -1060,6 +1072,31 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
result = CC_STATUS_SUCCESS;
+ } else if (!strcasecmp(key, "state_if_waiting")) {
+ if (cc_agent_str2state(value) == CC_AGENT_STATE_UNKNOWN) {
+ result = CC_STATUS_AGENT_INVALID_STATE;
+ goto done;
+ } else {
+ sql = switch_mprintf("UPDATE agents SET state = '%q' WHERE name = '%q' AND state = '%q' AND status IN ('%q', '%q')",
+ value, agent,
+ cc_agent_state2str(CC_AGENT_STATE_WAITING),
+ cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE),
+ cc_agent_status2str(CC_AGENT_STATUS_AVAILABLE_ON_DEMAND));
+
+ if (cc_execute_sql_affected_rows(sql) > 0) {
+ result = CC_STATUS_SUCCESS;
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-state-change");
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-State", value);
+ switch_event_fire(&event);
+ }
+ } else {
+ result = CC_STATUS_AGENT_NOT_FOUND;
+ }
+ switch_safe_free(sql);
+ }
+
} else {
result = CC_STATUS_INVALID_KEY;
goto done;
@@ -1367,13 +1404,19 @@ static switch_status_t load_config(void)
globals.dbname = strdup(val);
} else if (!strcasecmp(var, "odbc-dsn")) {
globals.odbc_dsn = strdup(val);
+ } else if(!strcasecmp(var, "reserve-agents")) {
+ globals.reserve_agents = switch_true(val);
}
}
}
if (!globals.dbname) {
globals.dbname = strdup(CC_SQLITE_DB_NAME);
}
-
+ if (!globals.reserve_agents) {
+ globals.reserve_agents = SWITCH_FALSE;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reserving Agents before offering calls.\n");
+ }
/* Initialize database */
if (!(dbh = cc_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
@@ -2010,6 +2053,18 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
}
}
+ if (globals.reserve_agents) {
+ /* Updating agent state to Reserved only if it was Waiting previously, this is done to avoid race conditions
+ when updating agents table with external applications */
+ if (cc_agent_update("state_if_waiting", cc_agent_state2str(CC_AGENT_STATE_RESERVED), agent_name) == CC_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Reserved Agent %s\n", agent_name);
+ } else {
+ /* Agent changed state just before we tried to update his state to Reserved. */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to Reserve Agent: %s. Skipping...\n", agent_name);
+ return 0;
+ }
+ }
+
if (!strcasecmp(cbt->strategy,"ring-all")) {
/* Check if member is a ring-all mode */
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = 'ring-all' AND uuid = '%q' AND system = 'single_box'", cbt->member_uuid);