[asterisk-commits] eliel: branch group/data_api_gsoc2009 r203541 - in /team/group/data_api_gsoc2...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Jun 25 19:53:43 CDT 2009


Author: eliel
Date: Thu Jun 25 19:53:40 2009
New Revision: 203541

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=203541
Log:
Start generating the tree based only in the path.


Modified:
    team/group/data_api_gsoc2009/include/asterisk/data.h
    team/group/data_api_gsoc2009/main/data.c

Modified: team/group/data_api_gsoc2009/include/asterisk/data.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/data_api_gsoc2009/include/asterisk/data.h?view=diff&rev=203541&r1=203540&r2=203541
==============================================================================
--- team/group/data_api_gsoc2009/include/asterisk/data.h (original)
+++ team/group/data_api_gsoc2009/include/asterisk/data.h Thu Jun 25 19:53:40 2009
@@ -204,10 +204,10 @@
 
 /*!
  * \brief Release the allocated memory of a tree.
- * \param[in] obj The sub-tree pointer returned by a call to ast_data_get.
+ * \param[in] root The sub-tree pointer returned by a call to ast_data_get.
  * \see ast_data_get
  */
-void ast_data_free(void *obj);
+void ast_data_free(struct ast_data *root);
 
 /*!
  * \brief Allocate a 'data' node structure.

Modified: team/group/data_api_gsoc2009/main/data.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/data_api_gsoc2009/main/data.c?view=diff&rev=203541&r1=203540&r2=203541
==============================================================================
--- team/group/data_api_gsoc2009/main/data.c (original)
+++ team/group/data_api_gsoc2009/main/data.c Thu Jun 25 19:53:40 2009
@@ -32,7 +32,8 @@
 #include "asterisk/data.h"
 #include "asterisk/astobj2.h"
 
-#define NUM_DATA_NODE_BUCKETS 60
+#define NUM_DATA_NODE_BUCKETS	60
+#define NUM_DATA_RESULT_BUCKETS 60
 
 /*! \brief The data tree to be returned by the callbacks and 
 		   managed by functions local to this file. */
@@ -442,7 +443,8 @@
 		res = __ast_data_register(data_entries[i].path, data_entries[i].handler,
 				registrar);
 		if (res) {
-			/* unregister all the already registered nodes, and make this action atomic. */
+			/* unregister all the already registered nodes, and make
+			 * this an atomic atomic. */
 			while ((--i) >= 0) {
 				__ast_data_unregister(data_entries[i].path, registrar);
 			}
@@ -479,13 +481,28 @@
  */
 static void data_result_destructor(void *obj)
 {
-	struct ast_data *node = obj;
-
-	if (node->type == AST_DATA_STRING) {
-		/* If there is a string in the node, release the
-		 * used memory to store it. */
-		ast_free(node->payload.str);
-	}
+	struct ast_data *child, *root = obj;
+	struct ao2_iterator i;
+
+	switch (root->type) {
+	case AST_DATA_POINTER:
+	case AST_DATA_STRING:
+		ast_free(root->payload.ptr);
+		break;
+	case AST_DATA_CONTAINER:
+		i = ao2_iterator_init(root->children, 0);
+
+		while ((child = ao2_iterator_next(&i))) {
+			ao2_unlink(root->children, child);
+			ao2_ref(child, -1);
+		}
+
+		break;
+	default:
+		break;
+	}
+
+	ast_free(root);
 }
 
 static struct ast_data *data_result_create(const char *name)
@@ -497,6 +514,14 @@
 
 	res = ao2_alloc(sizeof(*res) + namelen, data_result_destructor);
 	if (!res) {
+		return NULL;
+	}
+
+	/* initialize the children container */
+	res->children = ao2_container_alloc(NUM_DATA_RESULT_BUCKETS, data_result_hash,
+		data_result_cmp);
+	if (!res->children) {
+		ao2_ref(res, -1);
 		return NULL;
 	}
 
@@ -525,6 +550,7 @@
 
 	found = ao2_find(root->children, find_node, OBJ_POINTER);
 
+	/* release the temporary created node used for searching. */
 	ao2_ref(find_node, -1);
 
 	return found;
@@ -579,12 +605,14 @@
 /*!
  * \internal
  * \brief
+ * \param[in] query
  * \param[in] root_provider
  * \param[in] parent_node_name
  * \retval NULL on error.
  * \retval non-NULL The generated result tree.
  */
-static struct ast_data *data_result_generate_node(struct data_provider *root_provider,
+static struct ast_data *data_result_generate_node(const struct ast_data_query *query,
+	const struct data_provider *root_provider,
 	const char *parent_node_name)
 {
 	struct ast_data *generated, *node;
@@ -598,7 +626,7 @@
 	}
 
 	/* if this is a terminal node, just run the callback function. */
-	if (root_provider->handler->get) {
+	if (root_provider->handler && root_provider->handler->get) {
 		generated = root_provider->handler->get();
 		if (generated) {
 			data_result_add_child(node, generated);
@@ -610,7 +638,7 @@
 	/* if this is not a terminal node, generate every child node. */
 	i = ao2_iterator_init(root_provider->children, 0);
 	while ((provider = ao2_iterator_next(&i))) {
-		generated = data_result_generate_node(provider, provider->name);
+		generated = data_result_generate_node(query, provider, provider->name);
 		if (generated) {
 			data_result_add_child(node, generated);
 		}
@@ -623,14 +651,56 @@
 /*!
  * \internal
  * \brief Generate a result tree based on a query.
- * \param[in] query The query used to generate the tree.
+ * \param[in] query The complete query structure.
+ * \param[in] search_path The path to retrieve.
  * \retval NULL on error.
  * \retval non-NULL The generated data result.
  */
-static struct ast_data *data_result_generate(const struct ast_data_query *query)
-{
-	/* parse the query, and generate the syntax */
-	return NULL;
+static struct ast_data *data_result_generate(const struct ast_data_query *query, const char *search_path)
+{
+	char *node_name, *tmp_path;
+	struct data_provider *provider_child, *tmp_provider_child;
+	struct ast_data *result;
+
+	if (!search_path) {
+		/* generate all the trees?. */
+		return NULL;
+	}
+
+	tmp_path = ast_strdupa(search_path);
+	if (!tmp_path) {
+		return NULL;
+	}
+
+	/* start searching the root node name */
+	node_name = next_node_name(&tmp_path);
+	provider_child = data_provider_find(root_data, node_name, NULL);
+
+	/* continue with the rest of the path. */
+	while (provider_child) {
+		node_name = next_node_name(&tmp_path);
+		if (!node_name) {
+			break;
+		}
+
+		tmp_provider_child = data_provider_find(provider_child->children, node_name, NULL);
+
+		/* release the reference from this child */
+		ao2_ref(provider_child, -1);
+
+		provider_child = tmp_provider_child;
+	}
+
+	if (!provider_child) {
+		ast_log(LOG_ERROR, "Invalid path '%s', '%s' not found.\n", tmp_path, node_name);
+		return NULL;
+	}
+
+	result = data_result_generate_node(query, provider_child, provider_child->name);
+
+	ao2_ref(provider_child, -1);
+
+	return result;
 }
 
 struct ast_data *ast_data_get(const struct ast_data_query *query)
@@ -638,7 +708,7 @@
 	struct ast_data *res;
 
 	data_read_lock();
-	res = data_result_generate(query);
+	res = data_result_generate(query, query->path);
 	data_unlock();
 
 	if (!res) {
@@ -670,6 +740,8 @@
  * \param name
  * \param type
  * \param ptr
+ * \retval NULL on error.
+ * \retval non-NULL The added child node pointer.
  */
 static struct ast_data *__ast_data_add(struct ast_data *root, const char *name,
 	enum ast_data_type type, void *ptr)
@@ -677,10 +749,12 @@
 	struct ast_data *node;
 	size_t namelen = 1 + (ast_strlen_zero(name) ? 0 : strlen(name));
 
-	if ((!root->children &&
-		 !(root->children = ao2_container_alloc(NUM_DATA_NODE_BUCKETS,
-			data_result_hash, data_result_cmp))) || 
-		!(node = ao2_alloc(sizeof(*node) + namelen, ast_data_free))) {
+	if (!root || !root->children) {
+		/* invalid data result node. */
+		return NULL;
+	}
+
+	if (!(node = ao2_alloc(sizeof(*node) + namelen, data_result_destructor))) {
 		return NULL;
 	}
 
@@ -764,35 +838,10 @@
 	return data_result_create(name);
 }
 
-/*!
- * \brief Destroy an ast_data structure
- * \param[in] obj ast_data object
- */
-void ast_data_free(void *obj)
-{
-	struct ast_data *root = obj;
-	struct ao2_iterator i;
-	struct ast_data *child;
-
-	switch (root->type) {
-		case AST_DATA_POINTER:
-		case AST_DATA_STRING:
-			ast_free(root->payload.ptr);
-			break;
-
-		case AST_DATA_CONTAINER:
-			i = ao2_iterator_init(root->children, 0);
-
-			while ((child = ao2_iterator_next(&i))) {
-				ao2_ref(child, -2);
-			}
-
-			break;
-
-		default: break;
-	}
-
-	ast_free(root);
+void ast_data_free(struct ast_data *root)
+{
+	/* destroy it, this will destroy all the internal nodes. */
+	ao2_ref(root, -1);
 }
 
 /* XXX: test callback */
@@ -818,9 +867,20 @@
 /* XXX: test */
 static void runtest(void)
 {
+	struct ast_data *res;
+	struct ast_data_query query = {
+		.path = "asterisk/node1",
+	};
 
 	/* some tests */
 	ast_data_register_multiple(test_providers, ARRAY_LEN(test_providers));
+
+	res = ast_data_get(&query);
+
+	if (res) {
+		ast_data_free(res);
+	}
+
 	ast_data_unregister(NULL);
 }
 




More information about the asterisk-commits mailing list