[asterisk-commits] mmichelson: branch group/CCSS r215214 - in /team/group/CCSS: include/asterisk...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 1 16:06:24 CDT 2009


Author: mmichelson
Date: Tue Sep  1 16:06:21 2009
New Revision: 215214

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=215214
Log:
Provide means for monitors to register with the core.

This provides a way for a channel driver to register
a device monitor type so that the appropriate type
of monitor may be created when CC is requested. I need
to modify app_dial so that the frame data of an
AST_CONTROL_CC frame contains the type of monitor
that should be created.

A similar mechanism will be needed for agents, too.
I glossed over this step earlier since I am focusing
strictly on generic agents for now, though. With monitors
I can't do that though. It may be possible to combine
the registration of agents and monitors, although I don't
think I will do that just in case for some reason
someone should wish to only make a monitor or only
make an agent for a specific channel driver. Eh,
I'll think about it.


Modified:
    team/group/CCSS/include/asterisk/ccss.h
    team/group/CCSS/main/ccss.c

Modified: team/group/CCSS/include/asterisk/ccss.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/CCSS/include/asterisk/ccss.h?view=diff&rev=215214&r1=215213&r2=215214
==============================================================================
--- team/group/CCSS/include/asterisk/ccss.h (original)
+++ team/group/CCSS/include/asterisk/ccss.h Tue Sep  1 16:06:21 2009
@@ -480,6 +480,8 @@
 };
 
 struct ast_cc_monitor_callbacks {
+	/* Type of the monitor callbacks */
+	const char *type;
 	/* Allocate callback */
 	int (*init)(struct ast_cc_monitor *monitor, const int core_id);
 	/* Request CCSS callback */
@@ -490,8 +492,18 @@
 	enum ast_device_state(*status_request)(struct ast_cc_monitor *monitor, const int core_id);
 	/* Unsuspend monitoring callback */
 	int (*unsuspend)(struct ast_cc_monitor *monitor, const int core_id);
-	/* Destroy callback (XXX handled in ao2 destructor?) */
-	void (*destructor)(struct ast_cc_monitor *monitor, const int core_id);
+	/*!
+	 * Destroy callback 
+	 *
+	 * This destructor is never called directly. Instead, it is passed
+	 * to the astobj2 system so that when the refcount for the monitor
+	 * reaches zero, this function is called.
+	 *
+	 * The parameter is a void pointer since that is what ao2 requires
+	 * for its destructors. However, the contents passed will always
+	 * be a pointer to the monitor being destroyed.
+	 */
+	void (*destructor)(void *monitor);
 	/* Pass status upstream callback (XXX ???) */
 };
 
@@ -643,6 +655,20 @@
 
 /*!
  * \since 1.6.4
+ * \brief Register a set of monitor callbacks with the core
+ *
+ * This is made so that at monitor creation time, the proper callbacks
+ * may be installed and the proper .init callback may be called for the
+ * monitor to establish private data.
+ *
+ * \param callbacks The callbacks used by the monitor implementation
+ * \retval 0 Successfully registered
+ * \retval -1 Failure to register
+ */
+int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks);
+
+/*!
+ * \since 1.6.4
  * \brief Initialize CCSS
  *
  * XXX This needs to be updated as more functionality is added.

Modified: team/group/CCSS/main/ccss.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/CCSS/main/ccss.c?view=diff&rev=215214&r1=215213&r2=215214
==============================================================================
--- team/group/CCSS/main/ccss.c (original)
+++ team/group/CCSS/main/ccss.c Tue Sep  1 16:06:21 2009
@@ -58,6 +58,14 @@
 	unsigned int cc_max_agents;
 	unsigned int cc_max_monitors;
 	char cc_callback_macro[AST_MAX_EXTENSION];
+};
+
+/* XXX Consider making this an RWLIST */
+AST_LIST_HEAD_STATIC(cc_monitor_backends, cc_monitor_backend);
+
+struct cc_monitor_backend {
+	AST_LIST_ENTRY(cc_monitor_backend) next;
+	const struct ast_cc_monitor_callbacks *callbacks;
 };
 
 /* XXX I'm making these defaults up right now with no real regard for
@@ -760,10 +768,39 @@
 	ast_free(agent_pvt);
 }
 
-static struct ast_cc_monitor *cc_monitor_instance_init(enum ast_cc_monitor_type type, const char * const name)
-{
-	/* STUB */
-	return NULL;
+static const struct ast_cc_monitor_callbacks *find_monitor_callbacks(const char * const type)
+{
+	struct cc_monitor_backend *backend;
+	const struct ast_cc_monitor_callbacks *callbacks = NULL;
+
+	AST_LIST_LOCK(&cc_monitor_backends);
+	AST_LIST_TRAVERSE(&cc_monitor_backends, backend, next) {
+		if (!strcmp(backend->callbacks->type, type)) {
+			ast_log(LOG_NOTICE, "Returning backend %s\n", backend->callbacks->type);
+			callbacks = backend->callbacks;
+			break;
+		}
+	}
+	AST_LIST_UNLOCK(&cc_monitor_backends);
+	return callbacks;
+}
+
+static struct ast_cc_monitor *cc_monitor_instance_init(enum ast_cc_monitor_type type, const char * const callback_type, const char * const monitor_name, const int core_id)
+{
+	struct ast_cc_monitor *monitor;
+	const struct ast_cc_monitor_callbacks *callbacks = find_monitor_callbacks(callback_type);
+
+	ast_assert(callbacks != NULL);
+
+	if (!(monitor = ao2_alloc(sizeof(*monitor) + strlen(monitor_name), callbacks->destructor))) {
+		return NULL;
+	}
+
+	monitor->type = type;
+	strcpy(monitor->name, monitor_name);
+	monitor->callbacks = callbacks;
+	monitor->callbacks->init(monitor, core_id);
+	return monitor;
 }
 
 static int cc_monitor_tree_init(const int core_id)
@@ -778,8 +815,7 @@
 	 * 1. Use the core_id to find the core instance
 	 * and pending offer.
 	 *
-	 * 2. Get a reference to the root monitor. This
-	 * may entail creating the root monitor.
+	 * 2. Get a reference to the root monitor. 
 	 *
 	 * 3. Morph the pending offer into a monitor
 	 * tree. For each item in the pending offer's
@@ -984,9 +1020,10 @@
 static int cc_extension_monitor_suspend(struct ast_cc_monitor *monitor, const int core_id);
 static enum ast_device_state cc_extension_monitor_status_request(struct ast_cc_monitor *monitor, const int core_id);
 static int cc_extension_monitor_unsuspend(struct ast_cc_monitor *monitor, const int core_id);
-static void cc_extension_monitor_destructor(struct ast_cc_monitor *monitor, const int core_id);
+static void cc_extension_monitor_destructor(void *monitor);
 
 static struct ast_cc_monitor_callbacks extension_monitor_cbs = {
+	.type = "extension",
 	.init = cc_extension_monitor_init,
 	.request_cc = cc_extension_monitor_request_cc,
 	.suspend = cc_extension_monitor_suspend,
@@ -1025,10 +1062,26 @@
 	return 0;
 }
 
-static void cc_extension_monitor_destructor(struct ast_cc_monitor *monitor, const int core_id)
+static void cc_extension_monitor_destructor(void *monitor)
 {
 	/* STUB */
 	return;
+}
+
+int ast_cc_monitor_register(const struct ast_cc_monitor_callbacks *callbacks)
+{
+	struct cc_monitor_backend *backend = ast_calloc(1, sizeof(*backend));
+
+	if (!backend) {
+		return -1;
+	}
+
+	backend->callbacks = callbacks;
+
+	AST_LIST_LOCK(&cc_monitor_backends);
+	AST_LIST_INSERT_TAIL(&cc_monitor_backends, backend, next);
+	AST_LIST_UNLOCK(&cc_monitor_backends);
+	return 0;
 }
 
 int ast_cc_init(void)
@@ -1052,11 +1105,16 @@
 	if (!(cc_sched_thread = ast_sched_thread_create())) {
 		return -1;
 	}
-	if (!(root_monitor = cc_monitor_instance_init(AST_CC_ROOT_MONITOR, "root"))) {
+	/* Root monitor doesn't care about the core id. The root monitor uses
+	 * extension monitor callbacks since the gist of those will be to traverse
+	 * their child links and call each of their children's callbacks
+	 */
+	if (!(root_monitor = cc_monitor_instance_init(AST_CC_ROOT_MONITOR, "extension", "root", -1))) {
 		return -1;
 	}
 	ast_log(LOG_NOTICE, "Successfully created CC sched_thread context\n");
 	res = ast_register_application2(ccreq_app, ccreq_exec, NULL, NULL, NULL);
 	res |= ast_register_application2(cccancel_app, cccancel_exec, NULL, NULL, NULL);
+	res |= ast_cc_monitor_register(&extension_monitor_cbs);
 	return res;
 }




More information about the asterisk-commits mailing list