[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