[asterisk-commits] file: branch file/bridge_unreal_optimizer r410469 - in /team/file/bridge_unre...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Mar 11 15:52:23 CDT 2014
Author: file
Date: Tue Mar 11 15:52:16 2014
New Revision: 410469
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=410469
Log:
Invoke the optimization callbacks when an optimization attempt occurs.
Modified:
team/file/bridge_unreal_optimizer/bridges/bridge_unreal.c
team/file/bridge_unreal_optimizer/include/asterisk/core_unreal.h
team/file/bridge_unreal_optimizer/main/bridge.c
team/file/bridge_unreal_optimizer/main/core_local.c
Modified: team/file/bridge_unreal_optimizer/bridges/bridge_unreal.c
URL: http://svnview.digium.com/svn/asterisk/team/file/bridge_unreal_optimizer/bridges/bridge_unreal.c?view=diff&rev=410469&r1=410468&r2=410469
==============================================================================
--- team/file/bridge_unreal_optimizer/bridges/bridge_unreal.c (original)
+++ team/file/bridge_unreal_optimizer/bridges/bridge_unreal.c Tue Mar 11 15:52:16 2014
@@ -90,6 +90,9 @@
/*! \brief Taskprocessor which optimizes things */
static struct ast_taskprocessor *taskprocessor;
+
+/*! \brief Integer which is incremented to produce a unique id for optimization attempts */
+static unsigned int optimization_id;
/*! \brief Task structure which contains information for optimizing unreal bridges */
struct optimize_task_data {
@@ -105,6 +108,8 @@
struct ast_channel *peer_owner;
/*! \brief Peer in the outbound channel bridge */
struct ast_channel *peer_chan;
+ /*! \brief Optional callback functions */
+ struct ast_unreal_pvt_callbacks *callbacks;
};
/*! \brief Destructor for optimize task data */
@@ -124,7 +129,8 @@
static struct optimize_task_data *optimize_task_data_alloc(
struct ast_channel *owner, struct ast_channel *chan,
struct ast_bridge *bridge_owner, struct ast_bridge *bridge_chan,
- struct ast_channel *peer_owner, struct ast_channel *peer_chan)
+ struct ast_channel *peer_owner, struct ast_channel *peer_chan,
+ struct ast_unreal_pvt_callbacks *callbacks)
{
struct optimize_task_data *task_data = ao2_alloc(sizeof(*task_data),
optimize_task_data_destroy);
@@ -139,6 +145,7 @@
task_data->bridge_chan = ao2_bump(bridge_chan);
task_data->peer_owner = ast_channel_ref(peer_owner);
task_data->peer_chan = ast_channel_ref(peer_chan);
+ task_data->callbacks = callbacks;
return task_data;
}
@@ -149,18 +156,44 @@
struct optimize_task_data *task_data = data;
enum ast_bridge_optimization optimization = ast_bridges_allow_optimization(task_data->bridge_chan,
task_data->bridge_owner);
+ unsigned int id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
+ struct ast_bridge *dst_bridge = NULL, *src_bridge = NULL;
+ struct ast_channel *chan = NULL, *swap = NULL;
+ int res = 0;
switch (optimization) {
case AST_BRIDGE_OPTIMIZE_SWAP_TO_CHAN_BRIDGE:
- ast_bridge_move(task_data->bridge_chan, task_data->bridge_owner, task_data->peer_owner,
- task_data->chan, 1);
+ dst_bridge = task_data->bridge_chan;
+ src_bridge = task_data->bridge_owner;
+ chan = task_data->peer_owner;
+ swap = task_data->chan;
break;
case AST_BRIDGE_OPTIMIZE_SWAP_TO_PEER_BRIDGE:
- ast_bridge_move(task_data->bridge_owner, task_data->bridge_chan, task_data->peer_chan,
- task_data->owner, 1);
+ dst_bridge = task_data->bridge_owner;
+ src_bridge = task_data->bridge_chan;
+ chan = task_data->peer_chan;
+ swap = task_data->owner;
break;
default:
break;
+ }
+
+ /* If all required information is not present abort early */
+ if (!dst_bridge || !src_bridge || !chan || !swap) {
+ ao2_ref(task_data, -1);
+ return 0;
+ }
+
+ if (task_data->callbacks && task_data->callbacks->optimization_started) {
+ task_data->callbacks->optimization_started(task_data->owner, task_data->chan,
+ chan, (swap == task_data->owner) ? AST_UNREAL_OWNER : AST_UNREAL_CHAN, id);
+ }
+
+ res = ast_bridge_move(dst_bridge, src_bridge, chan, swap, 1);
+
+ if (task_data->callbacks && task_data->callbacks->optimization_finished) {
+ task_data->callbacks->optimization_finished(task_data->owner, task_data->chan,
+ !res ? 1 : 0, id);
}
ao2_ref(task_data, -1);
@@ -287,7 +320,7 @@
if (changed && pvt->bridge_owner && pvt->bridge_chan) {
struct optimize_task_data *task_data = optimize_task_data_alloc(pvt->owner,
pvt->chan, pvt->bridge_owner, pvt->bridge_chan, pvt->bridged_owner,
- pvt->bridged_chan);
+ pvt->bridged_chan, pvt->callbacks);
ast_debug(1, "Queueing task to remove unreal channels between bridge '%s' and '%s'\n",
pvt->bridge_owner->uniqueid, pvt->bridge_chan->uniqueid);
Modified: team/file/bridge_unreal_optimizer/include/asterisk/core_unreal.h
URL: http://svnview.digium.com/svn/asterisk/team/file/bridge_unreal_optimizer/include/asterisk/core_unreal.h?view=diff&rev=410469&r1=410468&r2=410469
==============================================================================
--- team/file/bridge_unreal_optimizer/include/asterisk/core_unreal.h (original)
+++ team/file/bridge_unreal_optimizer/include/asterisk/core_unreal.h Tue Mar 11 15:52:16 2014
@@ -58,27 +58,28 @@
struct ast_unreal_pvt_callbacks {
/*!
* \brief Called when an optimization attempt has started
- * \note p is locked when this callback is called
- * \param p The \ref ast_unreal_pvt object
+ * \param owner The owner channel
+ * \param chan The outbound channel
* \param source The channel that is optimizing into an unreal_pvt channel's bridge.
* If NULL, the optimization is being accomplished via a bridge merge.
* \param dest Indicator of which channel's bridge in the unreal_pvt will survive the
* optimization
* \param id Unique identifier for this optimization operation.
*/
- void (* const optimization_started)(struct ast_unreal_pvt *p, struct ast_channel *source,
- enum ast_unreal_channel_indicator dest, unsigned int id);
+ void (* const optimization_started)(struct ast_channel *owner, struct ast_channel *chan,
+ struct ast_channel *source, enum ast_unreal_channel_indicator dest, unsigned int id);
/*!
* \brief Called when an optimization attempt completed successfully
- * \note p is locked when this callback is called
- * \param p The \ref ast_unreal_pvt object
+ * \param owner The owner channel
+ * \param chan The outbound channel
* \param success Non-zero if the optimization succeeded, zero if the optimization
* met with fatal and permanent error
* \param id Unique identifier for this optimization. Same as the one from the optimization_started
* call
*/
- void (* const optimization_finished)(struct ast_unreal_pvt *p, int success, unsigned int id);
+ void (* const optimization_finished)(struct ast_channel *owner, struct ast_channel *chan,
+ int success, unsigned int id);
};
/*!
Modified: team/file/bridge_unreal_optimizer/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/team/file/bridge_unreal_optimizer/main/bridge.c?view=diff&rev=410469&r1=410468&r2=410469
==============================================================================
--- team/file/bridge_unreal_optimizer/main/bridge.c (original)
+++ team/file/bridge_unreal_optimizer/main/bridge.c Tue Mar 11 15:52:16 2014
@@ -114,8 +114,6 @@
static AST_RWLIST_HEAD_STATIC(bridge_technologies, ast_bridge_technology);
-static unsigned int optimization_id;
-
/* Initial starting point for the bridge array of channels */
#define BRIDGE_ARRAY_START 128
@@ -2323,107 +2321,6 @@
/*!
* \internal
- * \brief Lock the unreal channel stack for chan and prequalify it.
- * \since 12.0.0
- *
- * \param chan Unreal channel writing a frame into the channel driver.
- *
- * \note It is assumed that chan is already locked.
- *
- * \retval bridge on success with bridge and bridge_channel locked.
- * \retval NULL if cannot do optimization now.
- */
-static struct ast_bridge *optimize_lock_chan_stack(struct ast_channel *chan)
-{
- struct ast_bridge *bridge;
- struct ast_bridge_channel *bridge_channel;
-
- if (!AST_LIST_EMPTY(ast_channel_readq(chan))) {
- return NULL;
- }
- if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_EMULATE_DTMF)) {
- return NULL;
- }
- if (ast_channel_has_audio_frame_or_monitor(chan)) {
- /* Channel has an active monitor, audiohook, or framehook. */
- return NULL;
- }
- bridge_channel = ast_channel_internal_bridge_channel(chan);
- if (!bridge_channel || ast_bridge_channel_trylock(bridge_channel)) {
- return NULL;
- }
- bridge = bridge_channel->bridge;
- if (bridge_channel->activity != BRIDGE_CHANNEL_THREAD_SIMPLE
- || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
- || ast_bridge_trylock(bridge)) {
- ast_bridge_channel_unlock(bridge_channel);
- return NULL;
- }
- if (!bridge_channel_internal_allows_optimization(bridge_channel) ||
- !bridge_allows_optimization(bridge)) {
- ast_bridge_unlock(bridge);
- ast_bridge_channel_unlock(bridge_channel);
- return NULL;
- }
- return bridge;
-}
-
-/*!
- * \internal
- * \brief Lock the unreal channel stack for peer and prequalify it.
- * \since 12.0.0
- *
- * \param peer Other unreal channel in the pair.
- *
- * \retval bridge on success with bridge, bridge_channel, and peer locked.
- * \retval NULL if cannot do optimization now.
- */
-static struct ast_bridge *optimize_lock_peer_stack(struct ast_channel *peer)
-{
- struct ast_bridge *bridge;
- struct ast_bridge_channel *bridge_channel;
-
- if (ast_channel_trylock(peer)) {
- return NULL;
- }
- if (!AST_LIST_EMPTY(ast_channel_readq(peer))) {
- ast_channel_unlock(peer);
- return NULL;
- }
- if (ast_test_flag(ast_channel_flags(peer), AST_FLAG_EMULATE_DTMF)) {
- ast_channel_unlock(peer);
- return NULL;
- }
- if (ast_channel_has_audio_frame_or_monitor(peer)) {
- /* Peer has an active monitor, audiohook, or framehook. */
- ast_channel_unlock(peer);
- return NULL;
- }
- bridge_channel = ast_channel_internal_bridge_channel(peer);
- if (!bridge_channel || ast_bridge_channel_trylock(bridge_channel)) {
- ast_channel_unlock(peer);
- return NULL;
- }
- bridge = bridge_channel->bridge;
- if (bridge_channel->activity != BRIDGE_CHANNEL_THREAD_IDLE
- || bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT
- || ast_bridge_trylock(bridge)) {
- ast_bridge_channel_unlock(bridge_channel);
- ast_channel_unlock(peer);
- return NULL;
- }
- if (!bridge_allows_optimization(bridge) ||
- !bridge_channel_internal_allows_optimization(bridge_channel)) {
- ast_bridge_unlock(bridge);
- ast_bridge_channel_unlock(bridge_channel);
- ast_channel_unlock(peer);
- return NULL;
- }
- return bridge;
-}
-
-/*!
- * \internal
* \brief Indicates allowability of a swap optimization
*/
enum bridge_allow_swap {
@@ -2485,84 +2382,6 @@
/*!
* \internal
- * \brief Check and attempt to swap optimize out the unreal channels.
- * \since 12.0.0
- *
- * \param chan_bridge
- * \param chan_bridge_channel
- * \param peer_bridge
- * \param peer_bridge_channel
- * \param pvt Unreal data containing callbacks to call if the optimization actually
- * happens
- *
- * \retval 1 if unreal channels failed to optimize out.
- * \retval 0 if unreal channels were not optimized out.
- * \retval -1 if unreal channels were optimized out.
- */
-static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
- struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
- struct ast_bridge_channel *peer_bridge_channel,
- struct ast_unreal_pvt *pvt)
-{
- struct ast_bridge *dst_bridge;
- struct ast_bridge_channel *dst_bridge_channel;
- struct ast_bridge_channel *src_bridge_channel;
- struct ast_bridge_channel *other;
- int res = 1;
-
- switch (bridges_allow_swap_optimization(chan_bridge, peer_bridge)) {
- case SWAP_TO_CHAN_BRIDGE:
- dst_bridge = chan_bridge;
- dst_bridge_channel = chan_bridge_channel;
- src_bridge_channel = peer_bridge_channel;
- break;
- case SWAP_TO_PEER_BRIDGE:
- dst_bridge = peer_bridge;
- dst_bridge_channel = peer_bridge_channel;
- src_bridge_channel = chan_bridge_channel;
- break;
- case SWAP_PROHIBITED:
- default:
- return 0;
- }
-
- other = ast_bridge_channel_peer(src_bridge_channel);
- if (other && other->state == BRIDGE_CHANNEL_STATE_WAIT) {
- unsigned int id;
-
- if (ast_channel_trylock(other->chan)) {
- return 1;
- }
-
- id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
-
- ast_verb(3, "Move-swap optimizing %s <-- %s.\n",
- ast_channel_name(dst_bridge_channel->chan),
- ast_channel_name(other->chan));
-
- if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
- && pvt->callbacks->optimization_started) {
- pvt->callbacks->optimization_started(pvt, other->chan,
- dst_bridge_channel->chan == pvt->owner ? AST_UNREAL_OWNER : AST_UNREAL_CHAN,
- id);
- ast_set_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN);
- }
- other->swap = dst_bridge_channel->chan;
- if (!bridge_do_move(dst_bridge, other, 1, 1)) {
- ast_bridge_channel_leave_bridge(src_bridge_channel,
- BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, AST_CAUSE_NORMAL_CLEARING);
- res = -1;
- }
- if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
- pvt->callbacks->optimization_finished(pvt, res == 1, id);
- }
- ast_channel_unlock(other->chan);
- }
- return res;
-}
-
-/*!
- * \internal
* \brief Indicates allowability of a merge optimization
*/
enum bridge_allow_merge {
@@ -2606,112 +2425,6 @@
}
return MERGE_ALLOWED;
-}
-
-/*!
- * \internal
- * \brief Check and attempt to merge optimize out the unreal channels.
- * \since 12.0.0
- *
- * \param chan_bridge
- * \param chan_bridge_channel
- * \param peer_bridge
- * \param peer_bridge_channel
- * \param pvt Unreal data containing callbacks to call if the optimization actually
- * happens
- *
- * \retval 0 if unreal channels were not optimized out.
- * \retval -1 if unreal channels were optimized out.
- */
-static int try_merge_optimize_out(struct ast_bridge *chan_bridge,
- struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
- struct ast_bridge_channel *peer_bridge_channel,
- struct ast_unreal_pvt *pvt)
-{
- struct merge_direction merge;
- struct ast_bridge_channel *kick_me[] = {
- chan_bridge_channel,
- peer_bridge_channel,
- };
- unsigned int id;
-
- switch (bridges_allow_merge_optimization(chan_bridge, peer_bridge, ARRAY_LEN(kick_me), &merge)) {
- case MERGE_ALLOWED:
- break;
- case MERGE_PROHIBITED:
- return 0;
- case MERGE_NOT_ENOUGH_CHANNELS:
- ast_debug(4, "Can't optimize %s -- %s out, not enough channels in bridge %s.\n",
- ast_channel_name(chan_bridge_channel->chan),
- ast_channel_name(peer_bridge_channel->chan),
- merge.src->uniqueid);
- return 0;
- case MERGE_NO_MULTIMIX:
- ast_debug(4, "Can't optimize %s -- %s out, multimix is needed and it cannot be acquired.\n",
- ast_channel_name(chan_bridge_channel->chan),
- ast_channel_name(peer_bridge_channel->chan));
- return 0;
- }
-
- ast_verb(3, "Merge optimizing %s -- %s out.\n",
- ast_channel_name(chan_bridge_channel->chan),
- ast_channel_name(peer_bridge_channel->chan));
-
- id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
-
- if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
- && pvt->callbacks->optimization_started) {
- pvt->callbacks->optimization_started(pvt, NULL,
- merge.dest == ast_channel_internal_bridge(pvt->owner) ? AST_UNREAL_OWNER : AST_UNREAL_CHAN,
- id);
- ast_set_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN);
- }
- bridge_do_merge(merge.dest, merge.src, kick_me, ARRAY_LEN(kick_me), 1);
- if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
- pvt->callbacks->optimization_finished(pvt, 1, id);
- }
-
- return -1;
-}
-
-int ast_bridge_unreal_optimize_out(struct ast_channel *chan, struct ast_channel *peer, struct ast_unreal_pvt *pvt)
-{
- struct ast_bridge *chan_bridge;
- struct ast_bridge *peer_bridge;
- struct ast_bridge_channel *chan_bridge_channel;
- struct ast_bridge_channel *peer_bridge_channel;
- int res = 0;
-
- chan_bridge = optimize_lock_chan_stack(chan);
- if (!chan_bridge) {
- return res;
- }
- chan_bridge_channel = ast_channel_internal_bridge_channel(chan);
-
- peer_bridge = optimize_lock_peer_stack(peer);
- if (peer_bridge) {
- peer_bridge_channel = ast_channel_internal_bridge_channel(peer);
-
- res = try_swap_optimize_out(chan_bridge, chan_bridge_channel,
- peer_bridge, peer_bridge_channel, pvt);
- if (!res) {
- res = try_merge_optimize_out(chan_bridge, chan_bridge_channel,
- peer_bridge, peer_bridge_channel, pvt);
- } else if (0 < res) {
- res = 0;
- }
-
- /* Release peer locks. */
- ast_bridge_unlock(peer_bridge);
- ast_bridge_channel_unlock(peer_bridge_channel);
- ast_channel_unlock(peer);
- }
-
- /* Release chan locks. */
- ast_bridge_unlock(chan_bridge);
- ast_bridge_channel_unlock(chan_bridge_channel);
-
- return res;
}
enum ast_bridge_optimization ast_bridges_allow_optimization(struct ast_bridge *chan_bridge,
Modified: team/file/bridge_unreal_optimizer/main/core_local.c
URL: http://svnview.digium.com/svn/asterisk/team/file/bridge_unreal_optimizer/main/core_local.c?view=diff&rev=410469&r1=410468&r2=410469
==============================================================================
--- team/file/bridge_unreal_optimizer/main/core_local.c (original)
+++ team/file/bridge_unreal_optimizer/main/core_local.c Tue Mar 11 15:52:16 2014
@@ -141,9 +141,10 @@
static int local_call(struct ast_channel *ast, const char *dest, int timeout);
static int local_hangup(struct ast_channel *ast);
static int local_devicestate(const char *data);
-static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct ast_channel *source,
- enum ast_unreal_channel_indicator dest, unsigned int id);
-static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int success, unsigned int id);
+static void local_optimization_started_cb(struct ast_channel *owner, struct ast_channel *chan,
+ struct ast_channel *source, enum ast_unreal_channel_indicator dest, unsigned int id);
+static void local_optimization_finished_cb(struct ast_channel *owner, struct ast_channel *chan,
+ int success, unsigned int id);
static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message *msg);
@@ -321,19 +322,19 @@
return res;
}
-static struct ast_multi_channel_blob *local_channel_optimization_blob(struct local_pvt *p,
- struct ast_json *json_object)
+static struct ast_multi_channel_blob *local_channel_optimization_blob(
+ struct ast_channel *owner, struct ast_channel *chan, struct ast_json *json_object)
{
struct ast_multi_channel_blob *payload;
RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup);
- local_one_snapshot = ast_channel_snapshot_create(p->base.owner);
+ local_one_snapshot = ast_channel_snapshot_create(owner);
if (!local_one_snapshot) {
return NULL;
}
- local_two_snapshot = ast_channel_snapshot_create(p->base.chan);
+ local_two_snapshot = ast_channel_snapshot_create(chan);
if (!local_two_snapshot) {
return NULL;
}
@@ -349,13 +350,12 @@
}
/*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_started_cb */
-static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct ast_channel *source,
- enum ast_unreal_channel_indicator dest, unsigned int id)
+static void local_optimization_started_cb(struct ast_channel *owner, struct ast_channel *chan,
+ struct ast_channel *source, enum ast_unreal_channel_indicator dest, unsigned int id)
{
RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
- struct local_pvt *p = (struct local_pvt *)base;
json_object = ast_json_pack("{s: i, s: i}",
"dest", dest, "id", id);
@@ -364,7 +364,7 @@
return;
}
- payload = local_channel_optimization_blob(p, json_object);
+ payload = local_channel_optimization_blob(owner, chan, json_object);
if (!payload) {
return;
}
@@ -384,16 +384,16 @@
return;
}
- stasis_publish(ast_channel_topic(p->base.owner), msg);
+ stasis_publish(ast_channel_topic(owner), msg);
}
/*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_finished_cb */
-static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int success, unsigned int id)
+static void local_optimization_finished_cb(struct ast_channel *owner, struct ast_channel *chan,
+ int success, unsigned int id)
{
RAII_VAR(struct ast_json *, json_object, ast_json_null(), ast_json_unref);
RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
- struct local_pvt *p = (struct local_pvt *)base;
json_object = ast_json_pack("{s: i, s: i}", "success", success, "id", id);
@@ -401,7 +401,7 @@
return;
}
- payload = local_channel_optimization_blob(p, json_object);
+ payload = local_channel_optimization_blob(owner, chan, json_object);
if (!payload) {
return;
}
@@ -411,7 +411,7 @@
return;
}
- stasis_publish(ast_channel_topic(p->base.owner), msg);
+ stasis_publish(ast_channel_topic(owner), msg);
}
static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message *message)
More information about the asterisk-commits
mailing list