[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