mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-20 12:20:12 +00:00
Move device state distribution to Stasis-core
In the move from Asterisk's event system to Stasis, this makes distributed device state aggregation always-on, removes unnecessary task processors where possible, and collapses aggregate and non-aggregate states into a single cache for ease of retrieval. This also removes an intermediary step in device state aggregation. Review: https://reviewboard.asterisk.org/r/2389/ (closes issue ASTERISK-21101) Patch-by: Kinsey Moore <kmoore@digium.com> git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@385860 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -990,9 +990,6 @@ static const struct autopause {
|
||||
{ QUEUE_AUTOPAUSE_ALL,"all" },
|
||||
};
|
||||
|
||||
|
||||
static struct ast_taskprocessor *devicestate_tps;
|
||||
|
||||
#define DEFAULT_RETRY 5
|
||||
#define DEFAULT_TIMEOUT 15
|
||||
#define RECHECK 1 /*!< Recheck every second to see we we're at the top yet */
|
||||
@@ -1037,8 +1034,8 @@ static int montype_default = 0;
|
||||
/*! \brief queues.conf [general] option */
|
||||
static int shared_lastcall = 1;
|
||||
|
||||
/*! \brief Subscription to device state change events */
|
||||
static struct ast_event_sub *device_state_sub;
|
||||
/*! \brief Subscription to device state change messages */
|
||||
static struct stasis_subscription *device_state_sub;
|
||||
|
||||
/*! \brief queues.conf [general] option */
|
||||
static int update_cdr = 0;
|
||||
@@ -1618,12 +1615,6 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct statechange {
|
||||
AST_LIST_ENTRY(statechange) entry;
|
||||
int state;
|
||||
char dev[0];
|
||||
};
|
||||
|
||||
/*! \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
|
||||
@@ -1742,10 +1733,10 @@ static int is_member_available(struct member *mem)
|
||||
}
|
||||
|
||||
/*! \brief set a member's status based on device state of that member's interface*/
|
||||
static int handle_statechange(void *datap)
|
||||
static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_topic *topic, struct stasis_message *msg)
|
||||
{
|
||||
struct statechange *sc = datap;
|
||||
struct ao2_iterator miter, qiter;
|
||||
struct ast_device_state_message *dev_state;
|
||||
struct member *m;
|
||||
struct call_queue *q;
|
||||
char interface[80], *slash_pos;
|
||||
@@ -1753,6 +1744,16 @@ static int handle_statechange(void *datap)
|
||||
int found_member; /* Found this member in this queue */
|
||||
int avail = 0; /* Found an available member in this queue */
|
||||
|
||||
if (ast_device_state_message_type() != stasis_message_type(msg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dev_state = stasis_message_data(msg);
|
||||
if (dev_state->eid) {
|
||||
/* ignore non-aggregate states */
|
||||
return;
|
||||
}
|
||||
|
||||
qiter = ao2_iterator_init(queues, 0);
|
||||
while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
|
||||
ao2_lock(q);
|
||||
@@ -1770,9 +1771,9 @@ static int handle_statechange(void *datap)
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(interface, sc->dev)) {
|
||||
if (!strcasecmp(interface, dev_state->device)) {
|
||||
found_member = 1;
|
||||
update_status(q, m, sc->state);
|
||||
update_status(q, m, dev_state->state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1804,39 +1805,18 @@ static int handle_statechange(void *datap)
|
||||
ao2_iterator_destroy(&qiter);
|
||||
|
||||
if (found) {
|
||||
ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", sc->dev, sc->state, ast_devstate2str(sc->state));
|
||||
ast_debug(1, "Device '%s' changed to state '%d' (%s)\n",
|
||||
dev_state->device,
|
||||
dev_state->state,
|
||||
ast_devstate2str(dev_state->state));
|
||||
} else {
|
||||
ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", sc->dev, sc->state, ast_devstate2str(sc->state));
|
||||
ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
|
||||
dev_state->device,
|
||||
dev_state->state,
|
||||
ast_devstate2str(dev_state->state));
|
||||
}
|
||||
|
||||
ast_free(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_state_cb(const struct ast_event *event, void *unused)
|
||||
{
|
||||
enum ast_device_state state;
|
||||
const char *device;
|
||||
struct statechange *sc;
|
||||
size_t datapsize;
|
||||
|
||||
state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
|
||||
device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
|
||||
|
||||
if (ast_strlen_zero(device)) {
|
||||
ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
|
||||
return;
|
||||
}
|
||||
datapsize = sizeof(*sc) + strlen(device) + 1;
|
||||
if (!(sc = ast_calloc(1, datapsize))) {
|
||||
ast_log(LOG_ERROR, "failed to calloc a state change struct\n");
|
||||
return;
|
||||
}
|
||||
sc->state = state;
|
||||
strcpy(sc->dev, device);
|
||||
if (ast_taskprocessor_push(devicestate_tps, handle_statechange, sc) < 0) {
|
||||
ast_free(sc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*! \brief Helper function which converts from extension state to device state values */
|
||||
@@ -9876,8 +9856,9 @@ static int unload_module(void)
|
||||
|
||||
res |= ast_data_unregister(NULL);
|
||||
|
||||
if (device_state_sub)
|
||||
ast_event_unsubscribe(device_state_sub);
|
||||
if (device_state_sub) {
|
||||
device_state_sub = stasis_unsubscribe(device_state_sub);
|
||||
}
|
||||
|
||||
ast_extension_state_del(0, extension_state_cb);
|
||||
|
||||
@@ -9887,7 +9868,6 @@ static int unload_module(void)
|
||||
queue_t_unref(q, "Done with iterator");
|
||||
}
|
||||
ao2_iterator_destroy(&q_iter);
|
||||
devicestate_tps = ast_taskprocessor_unreference(devicestate_tps);
|
||||
ao2_ref(queues, -1);
|
||||
ast_unload_realtime("queue_members");
|
||||
return res;
|
||||
@@ -9948,12 +9928,8 @@ static int load_module(void)
|
||||
res |= ast_custom_function_register(&queuewaitingcount_function);
|
||||
res |= ast_custom_function_register(&queuememberpenalty_function);
|
||||
|
||||
if (!(devicestate_tps = ast_taskprocessor_get("app_queue", 0))) {
|
||||
ast_log(LOG_WARNING, "devicestate taskprocessor reference failed - devicestate notifications will not occur\n");
|
||||
}
|
||||
|
||||
/* in the following subscribe call, do I use DEVICE_STATE, or DEVICE_STATE_CHANGE? */
|
||||
if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "AppQueue Device state", NULL, AST_EVENT_IE_END))) {
|
||||
if (!(device_state_sub = stasis_subscribe(ast_device_state_topic_all(), device_state_cb, NULL))) {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user