[asterisk-commits] russell: branch russell/data_retrieval r111598 - in /team/russell/data_retrie...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Mar 27 23:08:27 CDT 2008


Author: russell
Date: Thu Mar 27 23:08:27 2008
New Revision: 111598

URL: http://svn.digium.com/view/asterisk?view=rev&rev=111598
Log:
Save some code that I wrote on a plane back to Huntsville today.

We have had multiple discussions in the past of a "data retrieval" API for
Asterisk to accomplish the following things, mainly:
  1) Provide a more centralized implementation for the existing interfaces into
     Asterisk to retrieve data (CLI, Manager Interface, SNMP, etc.).
  2) By using a more common implementation, ensure that all interfaces into
     Asterisk have access to all of the same data.
  3) Provide an easier way to retrieve data between parts of Asterisk, (like
     actually making it possible for the SNMP module to access information
	 on SIP peers, without having to do something insane like connect to the
	 local manager interface!)

I have made a first pass at something to accomplish these goals.  The main API
definition and implementation are pretty simple, I think, and exist in main/data.c
and include/asterisk/data.h.

The code that demonstrates and tests what I have so far is:
  - In channels/chan_sip.c, I have implemented a single "data provider", called
    "sip_settings".  The "sip_settings" data provider would eventually provide
	all of what the "sip show settings" CLI command currently provides, but through
	this new interface.
  - There is an example of accessing this data in the CLI command that currently
    exists in main/data.c.  There is a "data get" CLI command which allows you to
	retrieve data from a data provider and have it presented to you at the CLI.
	So, "data get sip_settings" currently provides some information.

So, in theory, once this interface, or something like it gets agreed upon, a very
large number of the existing CLI commands and manager actions would be re-written
to this new interface.  Once they are on the new interface, they would then be
magically available to the CLI, manager interface, SNMP, or whatever other code
that someone wanted to write to access this information.

Added:
    team/russell/data_retrieval/include/asterisk/data.h   (with props)
    team/russell/data_retrieval/main/data.c   (with props)
Modified:
    team/russell/data_retrieval/channels/chan_sip.c
    team/russell/data_retrieval/include/asterisk/_private.h
    team/russell/data_retrieval/main/Makefile
    team/russell/data_retrieval/main/asterisk.c

Modified: team/russell/data_retrieval/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/russell/data_retrieval/channels/chan_sip.c?view=diff&rev=111598&r1=111597&r2=111598
==============================================================================
--- team/russell/data_retrieval/channels/chan_sip.c (original)
+++ team/russell/data_retrieval/channels/chan_sip.c Thu Mar 27 23:08:27 2008
@@ -176,6 +176,7 @@
 #include "asterisk/ast_version.h"
 #include "asterisk/event.h"
 #include "asterisk/tcptls.h"
+#include "asterisk/data.h"
 
 #ifndef FALSE
 #define FALSE    0
@@ -21433,6 +21434,37 @@
 	AST_CLI_DEFINE(sip_show_tcp, "List TCP Connections")
 };
 
+static struct ast_data_node *sip_settings_data(struct ast_data_provider *data_prov,
+	const struct ast_data_node *query)
+{
+	struct ast_data_node *settings_node;
+	int res = 0;
+
+	if (!(settings_node = ast_data_node_new("sip_settings"))) {
+		return NULL;
+	}
+
+	res |= ast_data_node_add_child_str(settings_node, "bindaddr", ast_inet_ntoa(bindaddr.sin_addr));
+	res |= ast_data_node_add_child_uint(settings_node, "bindport", (uint32_t) ntohs(bindaddr.sin_port));
+	res |= ast_data_node_add_child_bool(settings_node, "videosupport",
+		ast_test_flag(&global_flags[1], SIP_PAGE2_VIDEOSUPPORT));
+	res |= ast_data_node_add_child_bool(settings_node, "textsupport",
+		ast_test_flag(&global_flags[1], SIP_PAGE2_TEXTSUPPORT));
+	res |= ast_data_node_add_child_bool(settings_node, "autocreatepeer", autocreatepeer);
+	res |= ast_data_node_add_child_bool(settings_node, "match_auth_username", global_match_auth_username);
+		
+	if (res) {
+		ast_data_node_destroy(settings_node);
+		settings_node = NULL;
+	}
+
+	return settings_node;
+}
+
+static struct ast_data_provider sip_data_providers[] = {
+	AST_DATA_PROVIDER(sip_settings_data, "sip_settings"),
+};
+
 /*! \brief PBX load module - initialization */
 static int load_module(void)
 {
@@ -21474,6 +21506,8 @@
 
 	/* Register all CLI functions for SIP */
 	ast_cli_register_multiple(cli_sip, sizeof(cli_sip)/ sizeof(struct ast_cli_entry));
+
+	ast_data_provider_register_multiple(sip_data_providers, ARRAY_LEN(sip_data_providers));
 
 	/* Tell the RTP subdriver that we're here */
 	ast_rtp_proto_register(&sip_rtp);
@@ -21530,6 +21564,8 @@
 	/* Unregister CLI commands */
 	ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry));
 
+	ast_data_provider_unregister_multiple(sip_data_providers, ARRAY_LEN(sip_data_providers));
+
 	/* Disconnect from the RTP subsystem */
 	ast_rtp_proto_unregister(&sip_rtp);
 

Modified: team/russell/data_retrieval/include/asterisk/_private.h
URL: http://svn.digium.com/view/asterisk/team/russell/data_retrieval/include/asterisk/_private.h?view=diff&rev=111598&r1=111597&r2=111598
==============================================================================
--- team/russell/data_retrieval/include/asterisk/_private.h (original)
+++ team/russell/data_retrieval/include/asterisk/_private.h Thu Mar 27 23:08:27 2008
@@ -36,6 +36,7 @@
 void ast_autoservice_init(void);	/*!< Provided by autoservice.c */
 int ast_http_init(void);		/*!< Provided by http.c */
 int ast_http_reload(void);		/*!< Provided by http.c */
+int ast_data_init(void);        /*!< Provided by data.c */
 
 /*!
  * \brief Reload asterisk modules.

Added: team/russell/data_retrieval/include/asterisk/data.h
URL: http://svn.digium.com/view/asterisk/team/russell/data_retrieval/include/asterisk/data.h?view=auto&rev=111598
==============================================================================
--- team/russell/data_retrieval/include/asterisk/data.h (added)
+++ team/russell/data_retrieval/include/asterisk/data.h Thu Mar 27 23:08:27 2008
@@ -1,0 +1,148 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2008, Digium, Inc.
+ *
+ * Russell Bryant <russell at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \author Russell Bryant <russell at digium.com>
+ * \brief Asterisk Data Layer
+ * \ref AstDataLayer
+ */
+
+/*!
+ * \page AstDataLayer Asterisk Data Layer
+ *
+ * The purpose of this API is to ...
+ */
+
+#ifndef AST_DATA_H
+#define AST_DATA_H
+
+#include "asterisk/linkedlists.h"
+#include "asterisk/netsock.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/*********************************************************************************************/
+/*! @{ Data Node Reading */
+/*********************************************************************************************/
+
+/*!
+ * \brief A data node
+ *
+ * This is an opaque type.
+ */
+struct ast_data_node;
+
+enum ast_data_node_type {
+	AST_DATA_NODE_GROUPING,
+	AST_DATA_NODE_BOOL,
+	AST_DATA_NODE_UINT,
+	AST_DATA_NODE_STR,
+};
+
+enum ast_data_node_type ast_data_node_get_type(const struct ast_data_node *node);
+
+const char *ast_data_node_get_name(const struct ast_data_node *node);
+
+unsigned int ast_data_node_get_bool(const struct ast_data_node *node);
+
+uint32_t ast_data_node_get_uint(const struct ast_data_node *node);
+
+const char *ast_data_node_get_str(const struct ast_data_node *node);
+
+const struct ast_data_node *ast_data_node_get_child(const struct ast_data_node *node);
+
+const struct ast_data_node *ast_data_node_get_next(const struct ast_data_node *node);
+
+/*! @} */
+
+/*********************************************************************************************/
+/*! @{ Data Node Generation and Destruction */
+/*********************************************************************************************/
+
+struct ast_data_node *ast_data_node_new(const char *name);
+
+/*!
+ * \brief Destroy a node and all of its children
+ *
+ * \arg node The root node of a tree to destroy
+ *
+ * \return NULL for convenience
+ */
+struct ast_data_node *ast_data_node_destroy(struct ast_data_node *node);
+
+int ast_data_node_set_payload_bool(struct ast_data_node *node, unsigned int val);
+
+int ast_data_node_set_payload_uint(struct ast_data_node *node, uint32_t uint);
+
+int ast_data_node_set_payload_str(struct ast_data_node *node, const char *str);
+
+int ast_data_node_add_child(struct ast_data_node *parent, struct ast_data_node *child);
+
+int ast_data_node_add_child_bool(struct ast_data_node *parent, const char *name, unsigned int val);
+
+int ast_data_node_add_child_uint(struct ast_data_node *parent, const char *name, uint32_t uint);
+
+int ast_data_node_add_child_str(struct ast_data_node *parent, const char *name, const char *str);
+
+/*! @} */
+
+/*********************************************************************************************/
+/*! @{ Data Query */
+/*********************************************************************************************/
+
+struct ast_data_node *ast_data_query(const char *provider_name, const struct ast_data_node *query);
+
+/*! @} */
+
+/*********************************************************************************************/
+/*! @{ Data Providers */
+/*********************************************************************************************/
+
+struct ast_data_provider;
+
+typedef struct ast_data_node *(*ast_data_provider_cb)(struct ast_data_provider *data_prov,
+	const struct ast_data_node *query);
+
+struct ast_data_provider {
+	const char *name;
+	ast_data_provider_cb handler;
+};
+
+int ast_data_provider_register(struct ast_data_provider *data_prov);
+
+int ast_data_provider_unregister(struct ast_data_provider *data_prov);
+
+int ast_data_provider_register_multiple(struct ast_data_provider *data_prov, int num);
+
+int ast_data_provider_unregister_multiple(struct ast_data_provider *data_prov, int num);
+
+#define AST_DATA_PROVIDER(a, b) { .handler = a, .name = b }
+
+/*! @} */
+
+/*********************************************************************************************/
+/*********************************************************************************************/
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* AST_DATA_H */

Propchange: team/russell/data_retrieval/include/asterisk/data.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/russell/data_retrieval/include/asterisk/data.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/russell/data_retrieval/include/asterisk/data.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/russell/data_retrieval/main/Makefile
URL: http://svn.digium.com/view/asterisk/team/russell/data_retrieval/main/Makefile?view=diff&rev=111598&r1=111597&r2=111598
==============================================================================
--- team/russell/data_retrieval/main/Makefile (original)
+++ team/russell/data_retrieval/main/Makefile Thu Mar 27 23:08:27 2008
@@ -19,7 +19,7 @@
 
 RESAMPLE_OBJS:=libresample/src/resample.o libresample/src/resamplesubs.o libresample/src/filterkit.o
 
-OBJS= tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \
+OBJS:=tcptls.o io.o sched.o logger.o frame.o loader.o config.o channel.o \
 	translate.o file.o pbx.o cli.o md5.o term.o \
 	ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
 	cdr.o tdd.o acl.o rtp.o udptl.o manager.o asterisk.o \
@@ -30,7 +30,7 @@
 	cryptostub.o sha1.o http.o fixedjitterbuf.o abstract_jb.o \
 	strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \
 	astobj2.o hashtab.o global_datastores.o $(RESAMPLE_OBJS) version.o \
-	features.o
+	features.o data.o
 
 # we need to link in the objects statically, not as a library, because
 # otherwise modules will not have them available if none of the static

Modified: team/russell/data_retrieval/main/asterisk.c
URL: http://svn.digium.com/view/asterisk/team/russell/data_retrieval/main/asterisk.c?view=diff&rev=111598&r1=111597&r2=111598
==============================================================================
--- team/russell/data_retrieval/main/asterisk.c (original)
+++ team/russell/data_retrieval/main/asterisk.c Thu Mar 27 23:08:27 2008
@@ -3191,6 +3191,11 @@
 
 	ast_autoservice_init();
 
+	if (ast_data_init()) {
+		printf("%s", term_quit());
+		exit(1);
+	}
+
 	if (load_modules(1)) {		/* Load modules, pre-load only */
 		printf("%s", term_quit());
 		exit(1);

Added: team/russell/data_retrieval/main/data.c
URL: http://svn.digium.com/view/asterisk/team/russell/data_retrieval/main/data.c?view=auto&rev=111598
==============================================================================
--- team/russell/data_retrieval/main/data.c (added)
+++ team/russell/data_retrieval/main/data.c Thu Mar 27 23:08:27 2008
@@ -1,0 +1,423 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2008, Digium, Inc.
+ *
+ * Russell Bryant <russell at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Asterisk Data Layer
+ *
+ * \author Russell Bryant <russell at digium.com>
+ *
+ * \todo Consider ways to reduce copied code from CLI handling in the code for
+ *       handling data providers.
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <regex.h>
+
+#include "asterisk/_private.h"
+#include "asterisk/data.h"
+#include "asterisk/netsock.h"
+#include "asterisk/utils.h"
+#include "asterisk/strings.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/cli.h"
+
+struct ast_data_node {
+	enum ast_data_node_type node_type;
+	union {
+		unsigned int boolean:1;
+		uint32_t uint;
+		const char *str;
+	} payload;
+	AST_LIST_HEAD_NOLOCK(, ast_data_node) children;
+	AST_LIST_ENTRY(ast_data_node) entry;
+	char name[1];
+};
+
+#define NUM_DATA_PROV_BUCKETS 53
+
+struct ast_data_prov_holder {
+	struct ast_data_provider *data_prov;
+};
+
+static struct ao2_container *data_providers;
+
+const char *ast_data_node_get_name(const struct ast_data_node *node)
+{
+	return node->name;
+}
+
+enum ast_data_node_type ast_data_node_get_type(const struct ast_data_node *node)
+{
+	return node->node_type;
+}
+
+unsigned int ast_data_node_get_bool(const struct ast_data_node *node)
+{
+	return node->payload.boolean;
+}
+
+uint32_t ast_data_node_get_uint(const struct ast_data_node *node)
+{
+	return node->payload.uint;
+}
+
+const char *ast_data_node_get_str(const struct ast_data_node *node)
+{
+	return node->payload.str;
+}
+
+const struct ast_data_node *ast_data_node_get_child(const struct ast_data_node *node)
+{
+	return AST_LIST_FIRST(&node->children);
+}
+
+const struct ast_data_node *ast_data_node_get_next(const struct ast_data_node *node)
+{
+	return AST_LIST_NEXT(node, entry);
+}
+
+struct ast_data_node *ast_data_node_new(const char *name)
+{
+	struct ast_data_node *node;
+	size_t len;
+
+	len = sizeof(*node) + strlen(name);
+
+	if (!(node = ast_calloc(1, len)))
+		return NULL;
+	
+	strcpy(node->name, name);
+
+	return node;
+}
+
+struct ast_data_node *ast_data_node_destroy(struct ast_data_node *node)
+{
+	struct ast_data_node *child_node;
+
+	while ((child_node = AST_LIST_REMOVE_HEAD(&node->children, entry))) {
+		ast_data_node_destroy(child_node);
+	}
+
+	if (node->node_type == AST_DATA_NODE_STR) {
+		ast_free((char *) node->payload.str);
+		node->payload.str = NULL;
+	}
+
+	ast_free(node);
+
+	return NULL;
+}
+
+int ast_data_node_set_payload_bool(struct ast_data_node *node, unsigned int val)
+{
+	node->node_type = AST_DATA_NODE_BOOL;
+	node->payload.boolean = val ? 1 : 0;
+
+	return 0;
+}
+
+int ast_data_node_set_payload_uint(struct ast_data_node *node, uint32_t uint)
+{
+	node->node_type = AST_DATA_NODE_UINT;
+	node->payload.uint = uint;
+
+	return 0;
+}
+
+int ast_data_node_set_payload_str(struct ast_data_node *node, const char *str)
+{
+	if (!(node->payload.str = ast_strdup(str)))
+		return -1;
+	
+	node->node_type = AST_DATA_NODE_STR;
+
+	return 0;
+}
+
+int ast_data_node_add_child(struct ast_data_node *parent, struct ast_data_node *child)
+{
+	if (!parent || !child)
+		return -1;
+
+	AST_LIST_INSERT_TAIL(&parent->children, child, entry);
+
+	return 0;
+}
+
+int ast_data_node_add_child_bool(struct ast_data_node *parent, const char *name, unsigned int val)
+{
+	struct ast_data_node *node;
+
+	if (!(node = ast_data_node_new(name))) {
+		return -1;
+	}
+
+	ast_data_node_set_payload_bool(node, val);
+
+	return ast_data_node_add_child(parent, node);
+}
+
+int ast_data_node_add_child_uint(struct ast_data_node *parent, const char *name, uint32_t uint)
+{
+	struct ast_data_node *node;
+
+	if (!(node = ast_data_node_new(name))) {
+		return -1;
+	}
+
+	ast_data_node_set_payload_uint(node, uint);
+
+	return ast_data_node_add_child(parent, node);
+}
+
+int ast_data_node_add_child_str(struct ast_data_node *parent, const char *name, const char *str)
+{
+	struct ast_data_node *node;
+
+	if (!(node = ast_data_node_new(name))) {
+		return -1;
+	}
+
+	ast_data_node_set_payload_str(node, str);
+
+	return ast_data_node_add_child(parent, node);
+}
+
+struct ast_data_node *ast_data_query(const char *provider_name, const struct ast_data_node *query)
+{
+	struct ast_data_provider tmp_provider = {
+		.name = provider_name,
+	};
+	struct ast_data_prov_holder tmp_holder = {
+		.data_prov = &tmp_provider,
+	};
+	struct ast_data_prov_holder *holder;
+	struct ast_data_node *result;
+
+	if (!(holder = ao2_find(data_providers, &tmp_holder, OBJ_POINTER))) {
+		ast_log(LOG_ERROR, "Data provider '%s' not found for query\n", provider_name);
+		return NULL;
+	}
+
+	result = holder->data_prov->handler(holder->data_prov, query);
+
+	ao2_ref(holder, -1);
+	holder = NULL;
+
+	return result;
+}
+
+int ast_data_provider_register(struct ast_data_provider *data_prov)
+{
+	struct ast_data_prov_holder tmp_holder = {
+		.data_prov = data_prov,
+	};
+	struct ast_data_prov_holder *holder;
+
+	if ((holder = ao2_find(data_providers, &tmp_holder, OBJ_POINTER))) {
+		ast_log(LOG_ERROR, "Data provider '%s' is already registered\n", data_prov->name);
+		ao2_ref(holder, -1);
+		holder = NULL;
+		return -1;
+	}
+
+	if (!(holder = ao2_alloc(sizeof(*holder), NULL)))
+		return -1;
+
+	holder->data_prov = data_prov;
+
+	ao2_link(data_providers, holder);
+
+	ast_verb(2, "Registered Data Provider '%s'\n", data_prov->name);
+	
+	return 0;
+}
+
+int ast_data_provider_unregister(struct ast_data_provider *data_prov)
+{
+	struct ast_data_prov_holder tmp_holder = {
+		.data_prov = data_prov,
+	};
+	struct ast_data_prov_holder *holder;
+
+	if (!(holder = ao2_find(data_providers, &tmp_holder, OBJ_POINTER | OBJ_UNLINK)))
+		return -1;
+
+	ast_verb(2, "Unregistered Data Provider '%s'\n", holder->data_prov->name);
+
+	holder->data_prov = NULL;
+	ao2_ref(holder, -1);
+
+	return 0;
+}
+
+int ast_data_provider_register_multiple(struct ast_data_provider *data_prov, int num)
+{
+	int res = 0;
+
+	while (num--) {
+		res |= ast_data_provider_register(data_prov++);
+	}
+
+	return res;
+}
+
+int ast_data_provider_unregister_multiple(struct ast_data_provider *data_prov, int num)
+{
+	int res = 0;
+
+	while (num--) {
+		res |= ast_data_provider_unregister(data_prov++);
+	}
+
+	return res;
+}
+
+static int data_prov_hash(const void *obj, const int flags)
+{
+	const struct ast_data_prov_holder *holder = obj;
+
+	return ast_str_hash(holder->data_prov->name);
+}
+
+static int data_prov_cmp(void *obj, void *arg, int flags)
+{
+	struct ast_data_prov_holder *holder1 = obj;
+	struct ast_data_prov_holder *holder2 = arg;
+
+	return strcasecmp(holder1->data_prov->name, holder2->data_prov->name) ? 0 : CMP_MATCH;
+}
+
+static void cli_print_node(struct ast_cli_args *a, struct ast_str **buf, 
+	const struct ast_data_node *node, int level)
+{
+	int i;
+
+	if (!node)
+		return;
+
+	ast_str_set(buf, 0, "=== ");
+
+	for (i = 0; i < level; i++) {
+		ast_str_append(buf, 0, "---");
+	}
+
+	if (level) {
+		ast_str_append(buf, 0, ">");
+	}
+
+	ast_str_append(buf, 0, " %s: ", ast_data_node_get_name(node));
+
+	switch (ast_data_node_get_type(node)) {
+	case AST_DATA_NODE_GROUPING:
+		break;
+	case AST_DATA_NODE_BOOL:
+		ast_str_append(buf, 0, "%s", ast_data_node_get_bool(node) ? "yes" : "no");
+		break;
+	case AST_DATA_NODE_UINT:
+		ast_str_append(buf, 0, "%u", ast_data_node_get_uint(node));
+		break;
+	case AST_DATA_NODE_STR:
+		ast_str_append(buf, 0, "%s", ast_data_node_get_str(node));
+		break;
+	}
+
+	ast_cli(a->fd, "%s\n", (*buf)->str);
+
+	cli_print_node(a, buf, ast_data_node_get_child(node), level + 1);
+
+	cli_print_node(a, buf, ast_data_node_get_next(node), level);
+}
+
+static char *cli_data_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	const char *provider_name;
+	struct ast_data_node *results, *query;
+	struct ast_str *buf;
+
+	if (cmd == CLI_INIT) {
+		e->command = "data get";
+		e->usage =
+		"Usage: data get <data provider> [[<arg name> <arg value>] ...]\n"
+		"       Get data from the Asterisk Data Layer.\n"
+		"\n"
+		"Example: data get sip_settings\n"
+		"";
+		return NULL;
+	} else if (cmd == CLI_GENERATE) {
+		return NULL;
+	}
+
+	if (a->argc == e->args) {
+		return CLI_SHOWUSAGE;
+	}
+
+	provider_name = a->argv[e->args];
+
+	if (!(query = ast_data_node_new(provider_name))) {
+		return CLI_FAILURE;
+	}
+
+	if (!(results = ast_data_query(provider_name, query))) {
+		ast_data_node_destroy(query);
+		return CLI_FAILURE;
+	}
+
+	if (!(buf = ast_str_create(128))) {
+		ast_data_node_destroy(query);
+		ast_data_node_destroy(results);
+		return CLI_FAILURE;
+	}
+
+	ast_cli(a->fd,
+		"================================================================\n"
+		"=== Query: %s\n"
+		"================================================================\n"
+		"", provider_name);
+
+	cli_print_node(a, &buf, results, 0);
+
+	ast_cli(a->fd,
+		"================================================================\n"
+		"================================================================\n"
+		"");
+
+	ast_data_node_destroy(query);
+	ast_free(buf);
+
+	return CLI_SUCCESS;
+}
+
+static struct ast_cli_entry data_cli[] = {
+	AST_CLI_DEFINE(cli_data_get, "Get data from the ADL (Asterisk Data Layer)"),
+};
+
+int ast_data_init(void)
+{
+	if (!(data_providers = ao2_container_alloc(NUM_DATA_PROV_BUCKETS, data_prov_hash, data_prov_cmp)))
+		return -1;
+
+	ast_cli_register_multiple(data_cli, ARRAY_LEN(data_cli));
+
+	return 0;
+}

Propchange: team/russell/data_retrieval/main/data.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/russell/data_retrieval/main/data.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/russell/data_retrieval/main/data.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list