[asterisk-commits] eliel: branch eliel/data_retrieval r182956 - in /team/eliel/data_retrieval: i...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Mar 18 12:44:08 CDT 2009


Author: eliel
Date: Wed Mar 18 12:44:05 2009
New Revision: 182956

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=182956
Log:
Initial version of the data retrieval subsystem.
This is just an idea, to manager asterisk data based on xml and a hierarchy structure.

Added:
    team/eliel/data_retrieval/include/asterisk/data.h   (with props)
    team/eliel/data_retrieval/main/data.c   (with props)
Modified:
    team/eliel/data_retrieval/include/asterisk/_private.h
    team/eliel/data_retrieval/include/asterisk/xml.h
    team/eliel/data_retrieval/main/Makefile
    team/eliel/data_retrieval/main/asterisk.c
    team/eliel/data_retrieval/main/xml.c

Modified: team/eliel/data_retrieval/include/asterisk/_private.h
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/include/asterisk/_private.h?view=diff&rev=182956&r1=182955&r2=182956
==============================================================================
--- team/eliel/data_retrieval/include/asterisk/_private.h (original)
+++ team/eliel/data_retrieval/include/asterisk/_private.h Wed Mar 18 12:44:05 2009
@@ -41,6 +41,7 @@
 int ast_timing_init(void);		/*!< Provided by timing.c */
 int ast_indications_init(void); /*!< Provided by indications.c */
 int ast_indications_reload(void);/*!< Provided by indications.c */
+int ast_data_init(void);		/*!< Provided by data.c */
 
 /*!
  * \brief Reload asterisk modules.

Added: team/eliel/data_retrieval/include/asterisk/data.h
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/include/asterisk/data.h?view=auto&rev=182956
==============================================================================
--- team/eliel/data_retrieval/include/asterisk/data.h (added)
+++ team/eliel/data_retrieval/include/asterisk/data.h Wed Mar 18 12:44:05 2009
@@ -1,0 +1,97 @@
+/*
+ * 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 Data retrieval API.
+ * \author Eliel C. Sardanons (LU1ALY) <eliels at gmail.com>
+ */
+
+#ifndef AST_DATA_H
+#define AST_DATA_H
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/*! \brief opaque definition. */
+struct ast_data;
+
+typedef struct ast_data *(*ast_data_cb)(void);
+
+/*!
+ * \brief Register a data provider.
+ * \param path
+ * \param handler
+ * \retval < 0 on error.
+ * \retval 0 on success.
+ */
+int ast_data_register(const char *path, ast_data_cb handler);
+
+/*!
+ * \brief Unregister a data provider.
+ * \param path
+ * \retval < 0 on error.
+ * \retval 0 on success.
+ */
+int ast_data_unregister(const char *path);
+
+/*!
+ * \brief Retrieve data from the specified path.
+ * \param path What data to get.
+ * \retval NULL if no data was found on the specified node.
+ * \retval A dynamically allocated structure with the data you asked for.
+ * \see ast_data_free
+ */
+struct ast_data *ast_data_get(const char *path);
+
+/*!
+ * \brief Release the ast_data structure.
+ * \param data Which data handler to release.
+ */
+void ast_data_free(struct ast_data *data);
+
+/*!
+ * \brief
+ * \param handler
+ * \param path
+ * \returns
+ */
+unsigned int ast_data_get_uint(struct ast_data *handler, const char *path);
+
+/*!
+ * \brief
+ * \param handler
+ * \param path
+ * \returns
+ */
+char *ast_data_get_str(struct ast_data *handler, const char *path);
+
+/*!
+ * \brief
+ * \param handler
+ * \param path
+ * \returns
+ */
+unsigned char ast_data_get_bool(struct ast_data *handler, const char *path);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* AST_DATA_H */

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

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

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

Modified: team/eliel/data_retrieval/include/asterisk/xml.h
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/include/asterisk/xml.h?view=diff&rev=182956&r1=182955&r2=182956
==============================================================================
--- team/eliel/data_retrieval/include/asterisk/xml.h (original)
+++ team/eliel/data_retrieval/include/asterisk/xml.h Wed Mar 18 12:44:05 2009
@@ -45,11 +45,47 @@
  */
 struct ast_xml_doc *ast_xml_open(char *filename);
 
+/*! \brief
+ *  \retval NULL on error.
+ *  \retval The allocated document structure.
+ */
+struct ast_xml_doc *ast_xml_new(void);
+
+/*! \brief
+ *  \param name
+ *  \retval NULL on error.
+ *  \retval The allocated node structe.
+ */
+struct ast_xml_node *ast_xml_new_node(const char *name);
+
+/*! \brief
+ * \param parent
+ * \param child_name
+ * \retval NULL on error.
+ */
+struct ast_xml_node *ast_xml_new_child(struct ast_xml_node *parent, const char *child_name);
+
+/*!
+ * \brief Add a child node, to a specified parent node.
+ * \param parent Where to add the child node.
+ * \param child The child node to add.
+ * \retval NULL on error.
+ * \retval The add child node on success.
+ */
+struct ast_xml_node *ast_xml_add_child(struct ast_xml_node *parent, struct ast_xml_node *child);
+
 /*! \brief Close an already open document and free the used
  *        structure.
  *  \retval doc The document reference.
  */
 void ast_xml_close(struct ast_xml_doc *doc);
+
+/*! \brief
+ * \param doc
+ * \param node
+ * \retval NULL on error.
+ */
+void ast_xml_set_root(struct ast_xml_doc *doc, struct ast_xml_node *node);
 
 /*! \brief Get the document root node.
  *  \param doc Document reference
@@ -98,6 +134,12 @@
  */
 const char *ast_xml_get_text(struct ast_xml_node *node);
 
+/*! \brief Set an element content string.
+ *  \param node Node from where to set the content string.
+ *  \param content The text to insert in the node.
+ */
+void ast_xml_set_text(struct ast_xml_node *node, const char *content);
+
 /*! \brief Get the name of a node. */
 const char *ast_xml_node_get_name(struct ast_xml_node *node);
 

Modified: team/eliel/data_retrieval/main/Makefile
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/main/Makefile?view=diff&rev=182956&r1=182955&r2=182956
==============================================================================
--- team/eliel/data_retrieval/main/Makefile (original)
+++ team/eliel/data_retrieval/main/Makefile Wed Mar 18 12:44:05 2009
@@ -29,7 +29,7 @@
 	strcompat.o threadstorage.o dial.o event.o adsistub.o audiohook.o \
 	astobj2.o hashtab.o global_datastores.o version.o \
 	features.o taskprocessor.o timing.o datastore.o xml.o xmldoc.o \
-	strings.o bridging.o poll.o
+	strings.o bridging.o poll.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/eliel/data_retrieval/main/asterisk.c
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/main/asterisk.c?view=diff&rev=182956&r1=182955&r2=182956
==============================================================================
--- team/eliel/data_retrieval/main/asterisk.c (original)
+++ team/eliel/data_retrieval/main/asterisk.c Wed Mar 18 12:44:05 2009
@@ -3545,6 +3545,12 @@
 	ast_xmldoc_load_documentation();
 #endif
 
+	/* initialize the data retrieval API */
+	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/eliel/data_retrieval/main/data.c
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/main/data.c?view=auto&rev=182956
==============================================================================
--- team/eliel/data_retrieval/main/data.c (added)
+++ team/eliel/data_retrieval/main/data.c Wed Mar 18 12:44:05 2009
@@ -1,0 +1,465 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2008, Eliel C. Sardanons (LU1ALY) <eliels at gmail.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 Data retrieval API.
+ *
+ * \author Eliel C. Sardanons (LU1ALY) <eliels at gmail.com>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/_private.h"
+#include "asterisk/utils.h"
+#include "asterisk/lock.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/xml.h"
+#include "asterisk/data.h"
+
+struct ast_data {
+	/*! \brief The returned xml dom. */
+	struct ast_xml_doc *doc;
+	/*! \brief Current node. */
+	struct ast_xml_node *current;
+};
+
+/*! \brief A data container node pointing to the registered handler. */
+struct data_node {
+	/*! \brief node content handler. */
+	ast_data_cb read;
+	/*! \brief Node usage. */
+	int usage;
+	/*! \brief node childrens. */
+	AST_LIST_HEAD_NOLOCK(, data_node) children;
+	AST_LIST_ENTRY(data_node) entry;
+	/*! \brief node name. */
+	char name[0];
+};
+
+/*! \brief The asterisk data maint content structure. */
+static struct data_node *root_data;
+
+/*!
+ * \internal
+ * \brief asterisk data locking mechanism.
+ */
+static ast_rwlock_t root_data_lock;
+
+/*!
+ * \internal
+ * \brief Lock the data registered handlers structure for writing.
+ */
+static void data_write_lock(void)
+{
+	ast_rwlock_wrlock(&root_data_lock);
+}
+
+/*!
+ * \internal
+ * \brief Lock the data registered handlers structure for reading.
+ */
+static void data_read_lock(void)
+{
+	ast_rwlock_rdlock(&root_data_lock);
+}
+
+/*!
+ * \internal
+ * \brief Unlock the data registered handlers structure.
+ */
+static void data_unlock(void)
+{
+	ast_rwlock_unlock(&root_data_lock);
+}
+
+/*!
+ * \internal
+ * \brief Find a child node with a given name.
+ * \param parent The initial node.
+ * \param name The name of the child node to find.
+ * \retval NULL if no childrent with that name found.
+ * \retval A pointer to the found children.
+ */
+static struct data_node *data_find_child(struct data_node *parent, const char *name)
+{
+	struct data_node *child;
+
+	AST_LIST_TRAVERSE(&parent->children, child, entry) {
+		if (!strcasecmp(child->name, name)) {
+			break;
+		}
+	}
+
+	return child;
+}
+
+/*!
+ * \internal
+ * \brief Create a data node new
+ * \param name The node name.
+ * \retval NULL on error.
+ * \retval The allocated data node structure.
+ */
+static struct data_node *data_node_new(const char *name)
+{
+	struct data_node *node;
+	size_t namelen;
+
+	if (!name) {
+		return NULL;
+	}
+
+	namelen = strlen(name) + 1;
+
+	node = ast_calloc(1, sizeof(*node) + namelen);
+	if (!node) {
+		return NULL;
+	}
+
+	strcpy(node->name, name);
+
+	return node;
+}
+
+/*!
+ * \internal
+ * \brief Add a child node named 'name' to the 'parent' node.
+ * \param parent Where to add the child node.
+ * \param name The name of the child node.
+ */
+static struct data_node *data_node_add_child(struct data_node *parent, const char *name)
+{
+	struct data_node *child;
+
+	if (!parent || !name) {
+		return NULL;
+	}
+
+	child = data_node_new(name);
+	if (!child) {
+		return NULL;
+	}
+
+	child->usage = 1;
+	AST_LIST_INSERT_TAIL(&parent->children, child, entry);
+
+	return child;
+}
+
+/*!
+ * \internal
+ * \brief Release a group of nodes.
+ * \param path The path of nodes to release.
+ * \retval < 0 on error.
+ * \retval 0 on success.
+ */
+static int data_nodes_release(struct data_node *parent, const char *path)
+{
+	char *rpath, *node_name;
+	struct data_node *child, *tmp;
+
+	if (!parent || !path) {
+		return 0;
+	}
+
+	rpath = strdupa(path);
+	if (!rpath) {
+		return -1;
+	}
+
+	do {
+		node_name = strsep(&rpath, "/");
+		if (!node_name) {
+			/* no more nodes to destroy. */
+			return 0;
+		}
+	} while (!strlen(node_name));
+
+	child = data_find_child(parent, node_name);
+
+	if (!child) {
+		/* unknown node. */
+		ast_log(LOG_ERROR, "Unknown node %s\n", node_name);
+		return -1;
+	}
+
+	if (data_nodes_release(child, rpath) < 0) {
+		return -1;
+	}
+
+	child->usage--;
+	/* remove this node if no other data provider is using it. */
+	if (!child->usage) {
+		AST_LIST_TRAVERSE_SAFE_BEGIN(&parent->children, tmp, entry) {
+			if (tmp == child) {
+				AST_LIST_REMOVE_CURRENT(entry);
+				ast_free(child);
+				break;
+			}
+		}
+		AST_LIST_TRAVERSE_SAFE_END;
+	}
+
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Create the middle nodes for the specified path (asterisk/testnode1/childnode)
+ * \param parent Where to add the middle nodes structure.
+ * \param path The path of nodes to add.
+ */
+static struct data_node *data_nodes_create(struct data_node *parent, const char *path)
+{
+	char *rpath, *node_name;
+	struct data_node *child, *ret;
+
+	if (!parent || !path) {
+		return parent;
+	}
+
+	rpath = strdupa(path);
+	if (!rpath) {
+		return NULL;
+	}
+
+	do {
+		node_name = strsep(&rpath, "/");
+		if (!node_name) {
+			/* no more nodes to create. */
+			return parent;
+		}
+	} while (!strlen(node_name));
+
+	child = data_find_child(parent, node_name);
+
+	if (!child) {
+		child = data_node_add_child(parent, node_name);
+	}
+
+	ret = data_nodes_create(child, rpath);
+
+	return ret;
+}
+
+/*!
+ * \internal
+ * \brief
+ * \param path
+ * \retval NULL on error.
+ * \retval
+ */
+static struct data_node *data_retrieve_node(struct data_node *parent, const char *path)
+{
+	struct data_node *child = parent;
+	char *rpath, *node_name;
+
+	rpath = strdupa(path);
+	if (!rpath) {
+		return NULL;
+	}
+
+	while (child) {
+		do {
+			node_name = strsep(&rpath, "/");
+			if (!node_name) {
+				return child;
+			}
+		} while (!strlen(node_name));
+
+		child = data_find_child(child, node_name);
+		if (child && child->read) {
+			return child;
+		}
+	}
+
+	return NULL;
+}
+
+static struct ast_xml_node *data_generate_node(struct ast_xml_node *parent, struct data_node *node)
+{
+	struct data_node *child;
+	struct ast_xml_node *parent_child, *res;
+	struct ast_data *resdata;
+
+	AST_LIST_TRAVERSE(&node->children, child, entry) {
+		if (child->read) {
+			resdata = child->read();
+			return ast_xml_get_root(resdata->doc);
+		} else {
+			parent_child = ast_xml_new_child(parent, child->name);
+			res = data_generate_node(parent_child, child);
+			if (res) {
+				ast_xml_add_child(parent, res);
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/*!
+ * \internal
+ * \param node
+ * \retval NULL on error.
+ * \retval
+ */
+static struct ast_xml_doc *data_generate_result(struct data_node *node)
+{
+	struct ast_xml_doc *doc;
+	struct ast_xml_node *res_node;
+
+	doc = ast_xml_new();
+	if (!doc) {
+		ast_log(LOG_ERROR, "Unable to create the result container.\n");
+		return NULL;
+	}
+
+	res_node = ast_xml_new_node(node->name);
+	if (!res_node) {
+		ast_xml_close(doc);
+		ast_log(LOG_ERROR, "Unable to create the root node.\n");
+		return NULL;
+	}
+
+	ast_xml_set_root(doc, res_node);
+
+	data_generate_node(res_node, node);
+
+	return doc;
+}
+
+int ast_data_register(const char *path, ast_data_cb handler)
+{
+	struct data_node *node;
+
+	if (!path) {
+		return -1;
+	}
+
+	/* create the node structure for the registered handler. */
+	data_write_lock();
+	node = data_nodes_create(root_data, path);
+	if (!node) {
+		ast_log(LOG_ERROR, "Unable to create the specified path (%s).\n", path);
+		data_unlock();
+		return -1;
+	}
+	/* add handler to that node. */
+	node->read = handler;
+	data_unlock();
+
+	return 0;
+}
+
+int ast_data_unregister(const char *path)
+{
+	int res;
+
+	data_write_lock();
+	res = data_nodes_release(root_data, path);
+	data_unlock();
+
+	return res;
+}
+
+struct ast_data *ast_data_get(const char *path)
+{
+	struct data_node *last_node;
+	struct ast_xml_doc *retxmldoc;
+	struct ast_data *retdata;
+
+	if (!path) {
+		return NULL;
+	}
+
+	data_read_lock();
+	last_node = data_retrieve_node(root_data, path);
+	if (!last_node) {
+		ast_log(LOG_ERROR, "Unable to find %s\n", path);
+		data_unlock();
+		return NULL;
+	}
+
+	retxmldoc = data_generate_result(last_node);
+	data_unlock();
+
+	if (!retxmldoc) {
+		return NULL;
+	}
+
+	retdata = ast_calloc(1, sizeof(*retdata));
+	if (!retdata) {
+		ast_xml_close(retxmldoc);
+		return NULL;
+	}
+
+	retdata->doc = retxmldoc;
+	retdata->current = ast_xml_get_root(retxmldoc);
+
+	return retdata;
+}
+
+void ast_data_free(struct ast_data *data)
+{
+	ast_xml_close(data->doc);
+	ast_free(data);
+}
+
+unsigned int ast_data_get_uint(struct ast_data *handler, const char *path)
+{
+	return 0;
+}
+
+char *ast_data_get_str(struct ast_data *handler, const char *path)
+{
+	return "";
+}
+
+unsigned char ast_data_get_bool(struct ast_data *handler, const char *path)
+{
+	return 0;
+}
+
+static struct ast_data *test_data_provider(void)
+{
+	struct ast_xml_node *node;
+
+	node = ast_xml_new_node("jojo");
+
+	return (struct ast_data *) node;
+}
+
+int ast_data_init(void)
+{
+	struct ast_data *res;
+
+	ast_rwlock_init(&root_data_lock);
+
+	/* create the root node. */
+	root_data = data_node_new("asterisk");
+	if (!root_data) {
+		return -1;
+	}
+
+	ast_data_register("/pepe/prueba", test_data_provider);
+	res = ast_data_get("/");
+
+	return 0;
+}

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

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

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

Modified: team/eliel/data_retrieval/main/xml.c
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/main/xml.c?view=diff&rev=182956&r1=182955&r2=182956
==============================================================================
--- team/eliel/data_retrieval/main/xml.c (original)
+++ team/eliel/data_retrieval/main/xml.c Wed Mar 18 12:44:05 2009
@@ -27,7 +27,9 @@
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #if defined(HAVE_LIBXML2)
+#ifndef _POSIX_C_SOURCE
 #define _POSIX_C_SOURCE	200112L
+#endif
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 /* libxml2 ast_xml implementation. */
@@ -60,6 +62,49 @@
 	return (struct ast_xml_doc *) doc;
 }
 
+struct ast_xml_doc *ast_xml_new(void)
+{
+	xmlDoc *doc;
+
+	doc = xmlNewDoc((const xmlChar *) "1.0");
+
+	return (struct ast_xml_doc *) doc;
+}
+
+struct ast_xml_node *ast_xml_new_node(const char *name)
+{
+	xmlNode *node;
+
+	if (!name) {
+		return NULL;
+	}
+
+	node = xmlNewNode(NULL, (const xmlChar *) name);
+
+	return (struct ast_xml_node *) node;
+}
+
+struct ast_xml_node *ast_xml_new_child(struct ast_xml_node *parent, const char *child_name)
+{
+	xmlNode *child;
+
+	if (!parent || !child_name) {
+		return NULL;
+	}
+
+	child = xmlNewChild((xmlNode *) parent, NULL, (const xmlChar *) child_name, NULL);
+
+	return (struct ast_xml_node *) child;
+}
+
+struct ast_xml_node *ast_xml_add_child(struct ast_xml_node *parent, struct ast_xml_node *child)
+{
+	if (!parent || !child) {
+		return NULL;
+	}
+
+	return (struct ast_xml_node *) xmlAddChild((xmlNode *) parent, (xmlNode *) child);
+}
 
 void ast_xml_close(struct ast_xml_doc *doc)
 {
@@ -71,6 +116,14 @@
 	doc = NULL;
 }
 
+void ast_xml_set_root(struct ast_xml_doc *doc, struct ast_xml_node *node)
+{
+	if (!doc || !node) {
+		return;
+	}
+
+	xmlDocSetRootElement((xmlDoc *) doc, (xmlNode *) node);
+}
 
 struct ast_xml_node *ast_xml_get_root(struct ast_xml_doc *doc)
 {
@@ -167,6 +220,15 @@
 	return (const char *) xmlNodeGetContent((xmlNode *) node);
 }
 
+void ast_xml_set_text(struct ast_xml_node *node, const char *content)
+{
+	if (!node || !content) {
+		return;
+	}
+
+	xmlNodeSetContent((xmlNode *) node, (const xmlChar *) content);
+}
+
 const char *ast_xml_node_get_name(struct ast_xml_node *node)
 {
 	return (const char *) ((xmlNode *) node)->name;




More information about the asterisk-commits mailing list