[asterisk-commits] eliel: branch eliel/data_retrieval r183630 - /team/eliel/data_retrieval/main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Mar 20 16:56:35 CDT 2009
Author: eliel
Date: Fri Mar 20 16:56:32 2009
New Revision: 183630
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=183630
Log:
Move the code to start using astobj2 instead of AST_LIST
Modified:
team/eliel/data_retrieval/main/data.c
Modified: team/eliel/data_retrieval/main/data.c
URL: http://svn.digium.com/svn-view/asterisk/team/eliel/data_retrieval/main/data.c?view=diff&rev=183630&r1=183629&r2=183630
==============================================================================
--- team/eliel/data_retrieval/main/data.c (original)
+++ team/eliel/data_retrieval/main/data.c Fri Mar 20 16:56:32 2009
@@ -28,25 +28,26 @@
#include "asterisk/_private.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
-#include "asterisk/linkedlists.h"
#include "asterisk/xml.h"
#include "asterisk/data.h"
+#include "asterisk/astobj2.h"
+
+#define NUM_DATA_NODE_BUCKETS 60
/*! \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 children nodes. */
+ struct ao2_container *children;
+ /*! \brief The parent container of this data_node. */
+ struct ao2_container *parent;
/*! \brief node name. */
char name[0];
};
/*! \brief The asterisk data maint content structure. */
-static struct data_node *root_data;
+static struct ao2_container *root_data;
/*!
* \internal
@@ -54,6 +55,29 @@
*/
static ast_rwlock_t root_data_lock;
+/*!
+ * \internal
+ * \brief Common string hash function.
+ */
+static int data_node_hash(const void *obj, const int flags)
+{
+ const struct data_node *node = obj;
+
+ return ast_str_hash(node->name);
+}
+
+/*!
+ * \internal
+ * \brief Compare two data_node's.
+ */
+static int data_node_cmp(void *obj, void *arg, int flags)
+{
+ struct data_node *node1 = obj;
+ struct data_node *node2 = arg;
+
+ return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
+}
+
/*!
* \internal
* \brief Lock the data registered handlers structure for writing.
@@ -67,10 +91,12 @@
* \internal
* \brief Lock the data registered handlers structure for reading.
*/
+#if 0
static void data_read_lock(void)
{
ast_rwlock_rdlock(&root_data_lock);
}
+#endif
/*!
* \internal
@@ -83,23 +109,18 @@
/*!
* \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;
+ * \brief Get the next node name in a path (/node1/node2)
+ * Avoid null nodes like //node1//node2/node3.
+ */
+static char *next_node_name(char **path)
+{
+ char *res;
+
+ do {
+ res = strsep(path, "/");
+ } while (res && !strlen(res));
+
+ return res;
}
/*!
@@ -120,12 +141,18 @@
namelen = strlen(name) + 1;
- node = ast_calloc(1, sizeof(*node) + namelen);
+ node = ao2_alloc(sizeof(*node) + namelen, NULL);
if (!node) {
return NULL;
}
strcpy(node->name, name);
+
+ /* initialize the childrens container. */
+ if (!(node->children = ao2_container_alloc(NUM_DATA_NODE_BUCKETS, data_node_hash, data_node_cmp))) {
+ ao2_ref(node, -1);
+ return NULL;
+ }
return node;
}
@@ -136,23 +163,42 @@
* \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)
+static struct data_node *data_node_add_child(struct ao2_container *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);
+ child->parent = parent;
+
+ ao2_link(parent, child);
+
+ ao2_ref(child, -1);
return child;
+}
+
+/*!
+ * \internal
+ * \brief
+ */
+static struct data_node *data_find_child(struct ao2_container *parent, const char *name)
+{
+ struct data_node *find_node, *found;
+
+ find_node = data_node_new(name);
+ if (!find_node) {
+ return NULL;
+ }
+
+ found = ao2_find(parent, find_node, OBJ_POINTER);
+
+ ao2_ref(find_node, -1);
+
+ return found;
}
/*!
@@ -162,52 +208,33 @@
* \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;
- }
+static int data_nodes_release(struct ao2_container *parent, const char *path)
+{
+ char *node_name, *rpath;
+ struct data_node *child;
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));
+ node_name = next_node_name(&rpath);
+ if (!node_name) {
+ return -1;
+ }
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;
- }
+ ast_log(LOG_ERROR, "Unable to find node '%s'\n", node_name);
+ return -1;
+ }
+
+ /* if this is not a terminal node. */
+ if (!child->read && rpath) {
+ data_nodes_release(child->children, rpath);
+ }
+ ast_log(LOG_ERROR, "RELEASING NODE %s (%d)\n", child->name, ao2_ref(child, 0));
+ ao2_ref(child, -2);
return 0;
}
@@ -218,128 +245,39 @@
* \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)
+static struct data_node *data_nodes_create(struct ao2_container *parent, const char *path)
{
char *rpath, *node_name;
- struct data_node *child, *ret;
-
- if (!parent || !path) {
- return parent;
- }
+ struct data_node *child, *ret = NULL;
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));
+ node_name = next_node_name(&rpath);
+ if (!node_name) {
+ /* no more nodes to create. */
+ return NULL;
+ }
child = data_find_child(parent, node_name);
if (!child) {
+ ast_log(LOG_ERROR, "CREATING NODE %s\n", node_name);
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_node_retrieve(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);
- /* is this a terminal node? */
- if (child && child->read) {
- return child;
- }
- }
-
- return NULL;
-}
-
-static struct ast_data *data_generate_node(struct ast_xml_node *parent, struct data_node *node)
-{
- struct data_node *child;
- struct ast_xml_node *parent_child;
- struct ast_data *resdata;
-
- AST_LIST_TRAVERSE(&node->children, child, entry) {
- if (child->read) {
- resdata = child->read();
- return resdata;
- } else {
- parent_child = ast_xml_new_child(parent, child->name);
- resdata = data_generate_node(parent_child, child);
- if (resdata) {
- ast_xml_add_child(parent, (struct ast_xml_node *) resdata);
- }
- }
- }
-
- return NULL;
-}
-
-/*!
- * \internal
- * \param node
- * \retval NULL on error.
- * \retval
- */
-static struct ast_xml_node *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 res_node;
-}
-
-int ast_data_register(const char *path, ast_data_cb handler)
+ } else {
+ ast_log(LOG_ERROR, "ENTERING NODE %s => %d\n", node_name, ao2_ref(child, 0));
+ }
+
+ if (rpath) {
+ ret = data_nodes_create(child->children, rpath);
+ }
+
+ return ret ? ret : child;
+}
+
+int ast_data_register(const char *path, ast_data_cb read_handler)
{
struct data_node *node;
@@ -349,6 +287,7 @@
/* 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);
@@ -356,7 +295,8 @@
return -1;
}
/* add handler to that node. */
- node->read = handler;
+ node->read = read_handler;
+
data_unlock();
return 0;
@@ -364,85 +304,42 @@
int ast_data_unregister(const char *path)
{
- int res;
+ int ret;
data_write_lock();
- res = data_nodes_release(root_data, path);
+ ret = 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_node *retxml;
-
- if (!path) {
- return NULL;
- }
-
- data_read_lock();
- last_node = data_node_retrieve(root_data, path);
- if (!last_node) {
- ast_log(LOG_ERROR, "Unable to find %s\n", path);
- data_unlock();
- return NULL;
- }
-
- retxml = data_generate_result(last_node);
- data_unlock();
-
- if (!retxml) {
- return NULL;
- }
-
- return (struct ast_data *) retxml;
-}
-
-void ast_data_free(struct ast_data *data)
-{
- ast_xml_close(ast_xml_get_doc((struct ast_xml_node *) 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)
-{
+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)
+{
+ ast_rwlock_init(&root_data_lock);
+
+ if (!(root_data = ao2_container_alloc(NUM_DATA_NODE_BUCKETS, data_node_hash, data_node_cmp))) {
+ return -1;
+ }
+
+ ast_data_register("asterisk/pepe/prueba", test_data_provider);
+ ast_data_register("asterisk/pepe/jose", test_data_provider);
+
+ ast_data_unregister("asterisk/pepe/prueba");
+ ast_data_unregister("asterisk/pepe/jose");
+
+ ast_data_register("asterisk/pepe/prueba", test_data_provider);
+ ast_data_unregister("asterisk/pepe/prueba");
+
+ ast_log(LOG_ERROR, "RES = %d\n", ao2_container_count(root_data));
+
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;
-}
More information about the asterisk-commits
mailing list