[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r382849 - in /team/rmudgett/bridge_pha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Mar 12 11:25:16 CDT 2013
Author: rmudgett
Date: Tue Mar 12 11:25:12 2013
New Revision: 382849
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=382849
Log:
Create a bridge manager thread to handle items for the bridge.
The main use expected for now is bridge COLP identity changes.
Modified:
team/rmudgett/bridge_phase/include/asterisk/bridging.h
team/rmudgett/bridge_phase/main/asterisk.c
team/rmudgett/bridge_phase/main/bridging.c
Modified: team/rmudgett/bridge_phase/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/bridging.h?view=diff&rev=382849&r1=382848&r2=382849
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/bridging.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/bridging.h Tue Mar 12 11:25:12 2013
@@ -269,6 +269,15 @@
};
/*!
+ * \brief Initialize the bridging system.
+ * \since 12.0.0
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int ast_bridge_init(void);
+
+/*!
* \brief Create a new bridge
*
* \param capabilities The capabilities that we require to be used on the bridge
Modified: team/rmudgett/bridge_phase/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/asterisk.c?view=diff&rev=382849&r1=382848&r2=382849
==============================================================================
--- team/rmudgett/bridge_phase/main/asterisk.c (original)
+++ team/rmudgett/bridge_phase/main/asterisk.c Tue Mar 12 11:25:12 2013
@@ -241,6 +241,7 @@
#include "asterisk/uuid.h"
#include "asterisk/sorcery.h"
#include "asterisk/stasis.h"
+#include "asterisk/bridging.h"
#include "../defaults.h"
@@ -4266,6 +4267,11 @@
exit(1);
}
+ if (ast_bridge_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
+
if (ast_enum_init()) {
printf("%s", term_quit());
exit(1);
Modified: team/rmudgett/bridge_phase/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging.c?view=diff&rev=382849&r1=382848&r2=382849
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging.c (original)
+++ team/rmudgett/bridge_phase/main/bridging.c Tue Mar 12 11:25:12 2013
@@ -76,6 +76,63 @@
/*! Function handlers for built in interval features */
static void *builtin_interval_handlers[AST_BRIDGE_BUILTIN_INTERVAL_END];
+/*! Bridge manager service request */
+struct bridge_manager_request {
+ /*! List of bridge service requests. */
+ AST_LIST_ENTRY(bridge_manager_request) node;
+ /*! Refed bridge requesting service. */
+ struct ast_bridge *bridge;
+};
+
+struct bridge_manager_controller {
+ /*! Condition, used to wake up the bridge manager thread. */
+ ast_cond_t cond;
+ /*! Queue of bridge service requests. */
+ AST_LIST_HEAD_NOLOCK(, bridge_manager_request) service_requests;
+ /*! Manager thread */
+ pthread_t thread;
+ /*! TRUE if the manager needs to stop. */
+ unsigned int stop:1;
+};
+
+/*! Bridge manager controller. */
+static struct bridge_manager_controller *bridge_manager;
+
+/*!
+ * \brief Request service for a bridge from the bridge manager.
+ * \since 12.0.0
+ *
+ * \param bridge Requesting service.
+ *
+ * \return Nothing
+ */
+void ast_bridge_manager_service_req(struct ast_bridge *bridge);//BUGBUG not used yet
+void ast_bridge_manager_service_req(struct ast_bridge *bridge)
+{
+ struct bridge_manager_request *request;
+
+ ao2_lock(bridge_manager);
+ if (bridge_manager->stop) {
+ ao2_unlock(bridge_manager);
+ return;
+ }
+
+ /* Create the service request. */
+ request = ast_calloc(1, sizeof(*request));
+ if (!request) {
+ /* Well. This isn't good. */
+ ao2_unlock(bridge_manager);
+ return;
+ }
+ ao2_ref(bridge, +1);
+ request->bridge = bridge;
+
+ /* Put request into the queue and wake the bridge manager. */
+ AST_LIST_INSERT_TAIL(&bridge_manager->service_requests, request, node);
+ ast_cond_signal(&bridge_manager->cond);
+ ao2_unlock(bridge_manager);
+}
+
int __ast_bridge_technology_register(struct ast_bridge_technology *technology, struct ast_module *module)
{
struct ast_bridge_technology *current;
@@ -854,7 +911,8 @@
* bridge. The bridge ao2 object destructor will stop the
* thread if it is running.
*/
-static void *bridge_thread(void *data)
+void *bridge_thread(void *data);//BUGBUG not used
+void *bridge_thread(void *data)
{
struct ast_bridge *bridge = data;
struct ast_frame *action;
@@ -1300,6 +1358,38 @@
ast_module_unref(old_technology->mod);
return 0;
+}
+
+/*!
+ * \internal
+ * \brief Notify the bridge that it has been reconfigured.
+ * \since 12.0.0
+ *
+ * \param bridge Reconfigured bridge.
+ *
+ * \details
+ * After a series of ast_bridge_channel_push and
+ * ast_bridge_channel_pull calls, you need to call this function
+ * to cause the bridge to complete restruturing for the change
+ * in the channel makeup of the bridge.
+ *
+ * \note On entry, the bridge is already locked.
+ *
+ * \return Nothing
+ */
+static void ast_bridge_reconfigured(struct ast_bridge *bridge)
+{
+ if (!bridge->reconfigured) {
+ return;
+ }
+ bridge->reconfigured = 0;
+ if (ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_SMART)
+ && smart_bridge_operation(bridge)) {
+ /* Smart bridge failed. Dissolve the bridge. */
+ bridge_force_out_all(bridge);
+ return;
+ }
+ bridge_complete_join(bridge);
}
/*! \brief Run in a multithreaded model. Each joined channel does writing/reading in their own thread. TODO: Improve */
@@ -1676,22 +1766,8 @@
bridge_channel->bridge->callid = ast_read_threadstorage_callid();
}
- /* If the bridge does not have a thread yet, start it up */
- if (bridge_channel->bridge->thread == AST_PTHREADT_NULL
- && !bridge_channel->bridge->dissolved) {
- ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
- if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) {
-/* BUGBUG need to output the bridge id for tracking why. */
- ast_log(LOG_WARNING, "Failed to create a bridge thread for bridge %p.\n",
- bridge_channel->bridge);
-
- /* Mark the bridge as dissolved because the bridge failed. */
- bridge_channel->bridge->thread = AST_PTHREADT_NULL;
- bridge_channel->bridge->dissolved = 1;
- }
- }
-
ast_bridge_channel_push(bridge_channel);
+ ast_bridge_reconfigured(bridge_channel->bridge);
/* Actually execute the respective threading model, and keep our bridge thread alive */
while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
@@ -1742,6 +1818,7 @@
}
ast_bridge_channel_pull(bridge_channel);
+ ast_bridge_reconfigured(bridge_channel->bridge);
/* See if we need to dissolve the bridge itself if they hung up */
switch (bridge_channel->state) {
@@ -2359,6 +2436,8 @@
ast_bridge_channel_push(bridge_channel);
}
+ ast_bridge_reconfigured(bridge1);
+ ast_bridge_reconfigured(bridge2);
ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge2, bridge1);
}
@@ -3002,3 +3081,158 @@
}
ao2_unlock(bridge);
}
+
+/*!
+ * \internal
+ * \brief Service the bridge manager request.
+ * \since 12.0.0
+ *
+ * \param bridge requesting service.
+ *
+ * \return Nothing
+ */
+static void bridge_manager_service(struct ast_bridge *bridge)
+{
+ struct ast_frame *action;
+
+ ao2_lock(bridge);
+ if (bridge->callid) {
+ ast_callid_threadassoc_change(bridge->callid);
+ }
+
+ /* Run a pending bridge action. */
+ action = AST_LIST_REMOVE_HEAD(&bridge->action_queue, frame_list);
+ if (action) {
+ switch (action->frametype) {
+ case AST_FRAME_BRIDGE_ACTION:
+ bridge_action_bridge(bridge, action);
+ break;
+ default:
+ /* Unexpected deferred frame type. Should never happen. */
+ ast_assert(0);
+ break;
+ }
+ ast_frfree(action);
+ }
+ ao2_unlock(bridge);
+}
+
+/*!
+ * \internal
+ * \brief Bridge manager service thread.
+ * \since 12.0.0
+ *
+ * \return Nothing
+ */
+static void *bridge_manager_thread(void *data)
+{
+ struct bridge_manager_controller *manager = data;
+ struct bridge_manager_request *request;
+
+ ao2_lock(manager);
+ while (!manager->stop) {
+ request = AST_LIST_REMOVE_HEAD(&manager->service_requests, node);
+ if (!request) {
+ ast_cond_wait(&manager->cond, ao2_object_get_lockaddr(manager));
+ continue;
+ }
+ ao2_unlock(manager);
+
+ /* Service the bridge. */
+ bridge_manager_service(request->bridge);
+ ao2_ref(request->bridge, -1);
+ ast_free(request);
+
+ ao2_lock(manager);
+ }
+ ao2_unlock(manager);
+
+ return NULL;
+}
+
+/*!
+ * \internal
+ * \brief Destroy the bridge manager controller.
+ * \since 12.0.0
+ *
+ * \param obj Bridge manager to destroy.
+ *
+ * \return Nothing
+ */
+static void bridge_manager_destroy(void *obj)
+{
+ struct bridge_manager_controller *manager = obj;
+ struct bridge_manager_request *request;
+
+ if (manager->thread != AST_PTHREADT_NULL) {
+ /* Stop the manager thread. */
+ ao2_lock(manager);
+ manager->stop = 1;
+ ast_cond_signal(&manager->cond);
+ ao2_unlock(manager);
+ pthread_join(manager->thread, NULL);
+ }
+
+ /* Destroy the service request queue. */
+ while ((request = AST_LIST_REMOVE_HEAD(&manager->service_requests, node))) {
+ ao2_ref(request->bridge, -1);
+ ast_free(request);
+ }
+
+ ast_cond_destroy(&manager->cond);
+}
+
+/*!
+ * \internal
+ * \brief Create the bridge manager controller.
+ * \since 12.0.0
+ *
+ * \retval manager on success.
+ * \retval NULL on error.
+ */
+static struct bridge_manager_controller *bridge_manager_create(void)
+{
+ struct bridge_manager_controller *manager;
+
+ manager = ao2_alloc(sizeof(*manager), bridge_manager_destroy);
+ if (!manager) {
+ /* Well. This isn't good. */
+ return NULL;
+ }
+ ast_cond_init(&manager->cond, NULL);
+ AST_LIST_HEAD_INIT_NOLOCK(&manager->service_requests);
+
+ /* Create the bridge manager thread. */
+ if (ast_pthread_create(&manager->thread, NULL, bridge_manager_thread, manager)) {
+ /* Well. This isn't good either. */
+ manager->thread = AST_PTHREADT_NULL;
+ ao2_ref(manager, -1);
+ manager = NULL;
+ }
+
+ return manager;
+}
+
+/*!
+ * \internal
+ * \brief Shutdown the bridging system.
+ * \since 12.0.0
+ *
+ * \return Nothing
+ */
+static void bridge_shutdown(void)
+{
+ ao2_cleanup(bridge_manager);
+ bridge_manager = NULL;
+}
+
+int ast_bridge_init(void)
+{
+ bridge_manager = bridge_manager_create();
+ if (!bridge_manager) {
+ return -1;
+ }
+
+ ast_register_atexit(bridge_shutdown);
+ return 0;
+}
More information about the asterisk-commits
mailing list