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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Aug 4 16:50:34 CDT 2009


Author: eliel
Date: Tue Aug  4 16:50:30 2009
New Revision: 210474

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=210474
Log:
Implement the filtering mechanism, now the nodes being filtered wont be
added to the result tree.


Modified:
    team/group/data_api_gsoc2009/apps/app_queue.c
    team/group/data_api_gsoc2009/include/asterisk/channel.h
    team/group/data_api_gsoc2009/include/asterisk/data.h
    team/group/data_api_gsoc2009/main/channel.c
    team/group/data_api_gsoc2009/main/data.c
    team/group/data_api_gsoc2009/tests/test_data.c

Modified: team/group/data_api_gsoc2009/apps/app_queue.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/data_api_gsoc2009/apps/app_queue.c?view=diff&rev=210474&r1=210473&r2=210474
==============================================================================
--- team/group/data_api_gsoc2009/apps/app_queue.c (original)
+++ team/group/data_api_gsoc2009/apps/app_queue.c Tue Aug  4 16:50:30 2009
@@ -7540,6 +7540,7 @@
  * \param[in] queue The queue to add.
  */
 static void queues_data_provider_get_helper(const struct ast_data_search *search,
+	const struct ast_data_filter *filter,
 	struct ast_data *data_root, struct call_queue *queue)
 {
 	int member_notmatch, caller_notmatch, caller_channel_notmatch;
@@ -7555,12 +7556,12 @@
 		return;
 	}
 
-	data_queue = ast_data_add_node(data_root, "queue");
+	data_queue = ast_data_add_node(filter, data_root, "queue");
 	if (!data_queue) {
 		return;
 	}
 
-	ast_data_add_structure(call_queue, data_queue, queue);
+	ast_data_add_structure(filter, call_queue, data_queue, queue);
 
 	member_notmatch = ast_data_search_has_condition(search, "queue/members/member");
 	/* add queue members */
@@ -7573,20 +7574,20 @@
 		}
 
 		if (!data_members) {
-			data_members = ast_data_add_node(data_queue, "members");
+			data_members = ast_data_add_node(filter, data_queue, "members");
 			if (!data_members) {
 				ao2_ref(member, -1);
 				continue;
 			}
 		}
 
-		data_member = ast_data_add_node(data_members, "member");
+		data_member = ast_data_add_node(filter, data_members, "member");
 		if (!data_member) {
 			ao2_ref(member, -1);
 			continue;
 		}
 
-		ast_data_add_structure(member, data_member, member);
+		ast_data_add_structure(filter, member, data_member, member);
 
 		ao2_ref(member, -1);
 	}
@@ -7614,26 +7615,26 @@
 			}
 
 			if (!data_callers) {
-				data_callers = ast_data_add_node(data_queue, "callers");
+				data_callers = ast_data_add_node(filter, data_queue, "callers");
 				if (!data_callers) {
 					continue;
 				}
 			}
 
-			data_caller = ast_data_add_node(data_callers, "caller");
+			data_caller = ast_data_add_node(filter, data_callers, "caller");
 			if (!data_caller) {
 				continue;
 			}
 
-			ast_data_add_structure(queue_ent, data_caller, qe);
+			ast_data_add_structure(filter, queue_ent, data_caller, qe);
 
 			/* add the caller channel. */
-			data_caller_channel = ast_data_add_node(data_caller, "channel");
+			data_caller_channel = ast_data_add_node(filter, data_caller, "channel");
 			if (!data_caller_channel) {
 				continue;
 			}
 
-			ast_channel_data_add_structure(data_caller_channel, qe->chan);
+			ast_channel_data_add_structure(filter, data_caller_channel, qe->chan);
 		}
 	}
 
@@ -7651,6 +7652,7 @@
  * \retval non-NULL The generated tree.
  */
 static int queues_data_provider_get(const struct ast_data_search *search,
+	const struct ast_data_filter *filter,
 	struct ast_data *data_root)
 {
 	struct ao2_iterator i;
@@ -7683,7 +7685,7 @@
 			queue_unref(queue_realtime);
 		}
 
-		queues_data_provider_get_helper(search, data_root, queue);
+		queues_data_provider_get_helper(search, filter, data_root, queue);
 		ao2_unlock(queue);
 		queue_unref(queue);
 	}

Modified: team/group/data_api_gsoc2009/include/asterisk/channel.h
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/data_api_gsoc2009/include/asterisk/channel.h?view=diff&rev=210474&r1=210473&r2=210474
==============================================================================
--- team/group/data_api_gsoc2009/include/asterisk/channel.h (original)
+++ team/group/data_api_gsoc2009/include/asterisk/channel.h Tue Aug  4 16:50:30 2009
@@ -2671,12 +2671,14 @@
 
 /*!
  * \brief Insert into an astdata tree, the channel structure.
+ * \param[in] filter The filtering tree.
  * \param[in] tree The ast data tree.
  * \param[in] chan The channel structure to add to tree.
  * \retval <0 on error.
  * \retval 0 on success.
  */
-int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *chan);
+int ast_channel_data_add_structure(const struct ast_data_filter *filter,
+	struct ast_data *tree, struct ast_channel *chan);
 
 /*!
  * \brief Compare to channel structures using the data api.

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=210474&r1=210473&r2=210474
==============================================================================
--- team/group/data_api_gsoc2009/include/asterisk/data.h (original)
+++ team/group/data_api_gsoc2009/include/asterisk/data.h Tue Aug  4 16:50:30 2009
@@ -101,6 +101,9 @@
 /*! \brief opaque definition of an ast_data_search structure. */
 struct ast_data_search;
 
+/*! \brief opaque definition of an ast_data_filter structure. */
+struct ast_data_filter;
+
 /*! \brief structure retrieved from a node, with the nodes content. */
 struct ast_data_retrieve {
 	enum ast_data_type type;
@@ -118,6 +121,7 @@
 };
 
 typedef int (*ast_data_get_cb)(const struct ast_data_search *search,
+	const struct ast_data_filter *filter,
 	struct ast_data *root);
 typedef int *(*ast_data_put_cb)(void);
 
@@ -431,91 +435,108 @@
 
 /*!
  * \brief Add a container child.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_node(struct ast_data *root, const char *childname);
+struct ast_data *ast_data_add_node(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname);
 
 /*!
  * \brief Add an integer node type.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \param[in] value The value for the new node.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_int(struct ast_data *root, const char *childname,
+struct ast_data *ast_data_add_int(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	int value);
 
 /*!
  * \brief Add an unsigned integer node type.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \param[in] value The value for the new node.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_uint(struct ast_data *root, const char *childname,
+struct ast_data *ast_data_add_uint(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	unsigned int value);
 
 /*!
  * \brief Add a floating point node type.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \param[in] dbl The value for the new node.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_dbl(struct ast_data *root, const char *childname,
+struct ast_data *ast_data_add_dbl(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	double dbl);
 /*!
  * \brief Add a ipv4 address type.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \param[in] addr The ipv4 address value.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_ipaddr(struct ast_data *root, const char *childname,
+struct ast_data *ast_data_add_ipaddr(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	struct in_addr addr);
 
 /*!
  * \brief Add a ptr node type.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \param[in] ptr The pointer value to add.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_ptr(struct ast_data *root, const char *childname,
+struct ast_data *ast_data_add_ptr(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	void *ptr);
 
 /*!
  * \brief Add a string node type.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \param[in] value The value for the new node.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_str(struct ast_data *root, const char *childname,
+struct ast_data *ast_data_add_str(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	const char *string);
 
 /*!
  * \brief Add a boolean node type.
+ * \param[in] filter The filtering tree.
  * \param[in] root The root of the ast_data to insert into.
  * \param[in] childname The name of the child element to be added.
  * \param[in] value The value for the new node.
  * \retval NULL on error (memory exhaustion only).
  * \retval non-NULL a newly allocated node.
  */
-struct ast_data *ast_data_add_bool(struct ast_data *root, const char *childname,
+struct ast_data *ast_data_add_bool(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	unsigned int boolean);
 
 /*!
  * \brief Add a complete structure to a node.
+ * \param[in] filter The filtering tree.
  * \param[in] root Where to add the structure.
  * \param[in] mapping The structure mapping array.
  * \param[in] mapping_len The lenght of the mapping array.
@@ -523,11 +544,11 @@
  * \retval 0 on success.
  * \retval 1 on error.
  */
-int __ast_data_add_structure(struct ast_data *root,
-	const struct ast_data_mapping_structure *mapping, size_t mapping_len,
-	void *structure);
-#define ast_data_add_structure(structure_name, root, structure)				\
-	__ast_data_add_structure(root, __data_mapping_structure_##structure_name,	\
+int __ast_data_add_structure(const struct ast_data_filter *filter,
+	struct ast_data *root, const struct ast_data_mapping_structure *mapping,
+	size_t mapping_len, void *structure);
+#define ast_data_add_structure(filter, structure_name, root, structure)				\
+	__ast_data_add_structure(filter, root, __data_mapping_structure_##structure_name,	\
 		ARRAY_LEN(__data_mapping_structure_##structure_name), structure)
 
 /*!

Modified: team/group/data_api_gsoc2009/main/channel.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/data_api_gsoc2009/main/channel.c?view=diff&rev=210474&r1=210473&r2=210474
==============================================================================
--- team/group/data_api_gsoc2009/main/channel.c (original)
+++ team/group/data_api_gsoc2009/main/channel.c Tue Aug  4 16:50:30 2009
@@ -257,9 +257,10 @@
 	return var;
 }
 
-int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *chan)
-{
-	return ast_data_add_structure(ast_channel, tree, chan);
+int ast_channel_data_add_structure(const struct ast_data_filter *filter,
+	struct ast_data *tree, struct ast_channel *chan)
+{
+	return ast_data_add_structure(filter, ast_channel, tree, chan);
 }
 
 int ast_channel_data_cmp_structure(const struct ast_data_search *tree,

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=210474&r1=210473&r2=210474
==============================================================================
--- team/group/data_api_gsoc2009/main/data.c (original)
+++ team/group/data_api_gsoc2009/main/data.c Tue Aug  4 16:50:30 2009
@@ -40,6 +40,7 @@
 #define NUM_DATA_NODE_BUCKETS	59
 #define NUM_DATA_RESULT_BUCKETS 59
 #define NUM_DATA_SEARCH_BUCKETS 59
+#define NUM_DATA_FILTER_BUCKETS 59
 
 /*! \brief The last compatible version. */
 static const uint32_t latest_handler_compatible_version = 0;
@@ -75,18 +76,6 @@
 	char name[0];
 };
 
-struct data_filter_node;
-
-AST_LIST_HEAD(data_filter_list, data_filter_node);
-
-struct data_filter_node {
-	/*! \brief The list of filter or search requirements
-	           ( container of type struct ast_data ) */
-	struct data_filter_list children;
-	AST_LIST_ENTRY(data_filter_node) next;
-	char name[0];
-};
-
 /*! \brief Type of comparisons allow in the search string. */
 enum data_search_comparison {
 	DATA_CMP_UNKNOWN,
@@ -102,14 +91,19 @@
 struct ast_data_search {
 	/*! \brief The value of the comparison. */
 	char *value;
-
 	/*! \brief The type of comparison. */
 	enum data_search_comparison cmp_type;
-
 	/*! \brief reference another node. */
 	struct ao2_container *children;
-
 	/*! \brief The name of the node we are trying to compare. */
+	char name[0];
+};
+
+/*! \brief The filter node. */
+struct ast_data_filter {
+	/*! \brief node childrens. */
+	struct ao2_container *children;
+	/*! \brief node name. */
 	char name[0];
 };
 
@@ -1431,39 +1425,125 @@
 
 /*!
  * \internal
- * \brief Destroy a list of data filter nodes.
- * \param[in] Data filter list to be destroyed.
- */
-static void data_filter_list_destroy(struct data_filter_list *flist)
-{
-	struct data_filter_node *node;
-
-	while ((node = AST_RWLIST_REMOVE_HEAD(flist, next))) {
-		data_filter_list_destroy(&(node->children));
-		ast_free(node);
-	}
-}
-
-/*!
- * \internal
- * \brief
- */
-static struct data_filter_node *data_filter_add_node(struct data_filter_list *flist, char *name)
-{
-	struct data_filter_node *node;
-
-	AST_LIST_TRAVERSE(flist, node, next) {
-		if (!strcasecmp(node->name, name)) {
-			return node;
-		}
-	}
-
-	node = ast_calloc(1, sizeof(*node) + strlen(name) + 1);
+ * \brief Common string hash function for data nodes
+ */
+static int data_filter_hash(const void *obj, const int flags)
+{
+	const struct ast_data_filter *node = obj;
+	return ast_str_hash(node->name);
+}
+
+/*!
+ * \internal
+ * \brief Common string comparison function
+ */
+static int data_filter_cmp(void *obj, void *arg, int flags)
+{
+	struct ast_data_filter *node1 = obj, *node2 = arg;
+	return strcasecmp(node1->name, node2->name) ? 0 : CMP_MATCH;
+}
+
+/*!
+ * \internal
+ * \brief Destroy a data filter tree.
+ * \param[in] obj Data filter list to be destroyed.
+ */
+static void data_filter_destructor(void *obj)
+{
+	struct ast_data_filter *filter = obj;
+
+	ao2_ref(filter->children, -1);
+}
+
+/*!
+ * \internal
+ * \brief Allocate a filter node.
+ * \retval NULL on error.
+ * \retval non-NULL The allocated search node structure.
+ */
+static struct ast_data_filter *data_filter_alloc(const char *name)
+{
+	struct ast_data_filter *res;
+	size_t name_len = strlen(name) + 1;
+
+	res = ao2_alloc(sizeof(*res) + name_len, data_filter_destructor);
+	if (!res) {
+		return NULL;
+	}
+
+	res->children = ao2_container_alloc(NUM_DATA_FILTER_BUCKETS, data_filter_hash,
+		data_filter_cmp);
+
+	if (!res) {
+		ao2_ref(res, -1);
+		return NULL;
+	}
+
+	strcpy(res->name, name);
+
+	return res;
+}
+
+/*!
+ * \internal
+ * \brief Release a filter tree.
+ * \param[in] filter The filter tree root node.
+ */
+static void data_filter_release(struct ast_data_filter *filter)
+{
+	ao2_ref(filter, -1);
+}
+
+/*!
+ * \internal
+ * \brief Find a child node, based on his name.
+ * \param[in] parent Where to find the node.
+ * \param[in] name The node name to find.
+ * \retval NULL if a node wasn't found.
+ * \retval The node found.
+ * \note Remember to decrement the ref count of the returned node after using it.
+ */
+static struct ast_data_filter *data_filter_find(struct ao2_container *parent,
+	const char *name)
+{
+	struct ast_data_filter *find_node, *found;
+
+	find_node = data_filter_alloc(name);
+	if (!find_node) {
+		return NULL;
+	}
+
+	found = ao2_find(parent, find_node, OBJ_POINTER);
+
+	/* free the created node used for searching. */
+	ao2_ref(find_node, -1);
+
+	return found;
+}
+
+/*!
+ * \internal
+ * \brief Add a child to the specified node.
+ * \param[in] root The root node where to add the child.
+ * \param[in] name The name of the node to add.
+ * \note Remember to decrement the ref count after using the returned node.
+ */
+static struct ast_data_filter *data_filter_add_child(struct ao2_container *root,
+	char *name)
+{
+	struct ast_data_filter *node;
+
+	node = data_filter_find(root, name);
+	if (node) {
+		return node;
+	}
+
+	node = data_filter_alloc(name);
 	if (!node) {
 		return NULL;
 	}
-	strcpy(node->name, name);
-	AST_LIST_INSERT_TAIL(flist, node, next);
+
+	ao2_link(root, node);
 
 	return node;
 }
@@ -1476,13 +1556,14 @@
  * \retval NULL on error.
  * \retval non-NULL A tree with the wanted nodes.
  */
-static struct data_filter_list *data_filter_add_nodes(struct data_filter_list *flist, char *path)
-{
-	struct data_filter_node *node;
+static int data_filter_add_nodes(struct ao2_container *root, char *path)
+{
+	struct ast_data_filter *node;
 	char *savepath, *saveptr, *token, *node_name;
+	int ret = 0;
 
 	if (!path) {
-		return NULL;
+		return 0;
 	}
 
 	savepath = ast_strdupa(path);
@@ -1490,25 +1571,21 @@
 	node_name = next_node_name(&savepath);
 
 	if (!node_name) {
-		return NULL;
+		return 0;
 	}
 
 	for (token = strtok_r(node_name, "|", &saveptr);
 			token; token = strtok_r(NULL, "|", &saveptr)) {
-		if (!flist) {
-			flist = ast_calloc(1, sizeof(*flist));
-			if (!flist) {
-				return NULL;
-			}
-		}
-		node = data_filter_add_node(flist, token);
+		node = data_filter_add_child(root, token);
 		if (!node) {
 			continue;
 		}
-		data_filter_add_nodes(&(node->children), savepath);
-	}
-
-	return flist;
+		data_filter_add_nodes(node->children, savepath);
+		ret = 1;
+		ao2_ref(node, -1);
+	}
+
+	return ret;
 }
 
 /*!
@@ -1516,10 +1593,11 @@
  * \brief Generate a filter list based on a filter string provided by the API user.
  * \param[in] A filter string to create a filter from.
  */
-static struct data_filter_list *data_filter_generate(const char *constfilter)
-{
-	struct data_filter_list *filter = NULL;
+static struct ast_data_filter *data_filter_generate(const char *constfilter)
+{
+	struct ast_data_filter *filter = NULL;
 	char *strfilter, *token, *saveptr;
+	int node_added = 0;
 
 	if (!constfilter) {
 		return NULL;
@@ -1527,8 +1605,18 @@
 
 	strfilter = ast_strdupa(constfilter);
 
+	filter = data_filter_alloc("/");
+	if (!filter) {
+		return NULL;
+	}
+
 	for (token = strtok_r(strfilter, ",", &saveptr); token; token = strtok_r(NULL, ",", &saveptr)) {
-		filter = data_filter_add_nodes(filter, token);
+		node_added = data_filter_add_nodes(filter->children, token);
+	}
+
+	if (!node_added) {
+		ao2_ref(filter, -1);
+		return NULL;
 	}
 
 	return filter;
@@ -1546,12 +1634,14 @@
 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,
-	const struct ast_data_search *search)
-{
-	struct ast_data *generated, *node;
+	const struct ast_data_search *search,
+	const struct ast_data_filter *filter)
+{
+	struct ast_data *generated = NULL, *node;
 	struct ao2_iterator i;
 	struct data_provider *provider;
 	struct ast_data_search *search_child = NULL;
+	struct ast_data_filter *filter_child = NULL;
 
 	node = data_result_create(parent_node_name);
 	if (!node) {
@@ -1565,7 +1655,7 @@
 
 	/* if this is a terminal node, just run the callback function. */
 	if (root_provider->handler && root_provider->handler->get) {
-		root_provider->handler->get(search, node);
+		root_provider->handler->get(search, filter, node);
 		ast_module_unref(root_provider->module);
 		return node;
 	}
@@ -1577,12 +1667,28 @@
 	/* 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))) {
+		/* get the internal search node. */
 		if (search) {
 			search_child = data_search_find(search->children, provider->name);
 		}
-		generated = data_result_generate_node(query, provider, provider->name, search_child);
+		/* get the internal filter node. */
+		if (filter) {
+			filter_child = data_filter_find(filter->children, provider->name);
+		}
+		if (!filter || filter_child) {
+			/* only generate the internal node, if we have something to
+			 * generate based on the filtering string. */
+			generated = data_result_generate_node(query, provider, provider->name,
+				search_child, filter_child);
+		}
+		/* decrement the refcount of the internal search node. */
 		if (search_child) {
 			ao2_ref(search_child, -1);
+		}
+
+		/* decrement the refcount of the internal filter node. */
+		if (filter_child) {
+			ao2_ref(filter_child, -1);
 		}
 
 		if (generated) {
@@ -1611,7 +1717,7 @@
 	struct data_provider *provider_child, *tmp_provider_child;
 	struct ast_data *result, *result_filtered;
 	struct ast_data_search *search = NULL, *search_child = NULL;
-	struct data_filter_list *flist = NULL;
+	struct ast_data_filter *filter = NULL, *filter_child = NULL;
 
 	if (!search_path) {
 		/* generate all the trees?. */
@@ -1649,15 +1755,20 @@
 	/* generate the search tree. */
 	if (query->search) {
 		search = data_search_generate(query->search);
-		search_child = data_search_find(search->children, provider_child->name);
+		if (search) {
+			search_child = data_search_find(search->children, provider_child->name);
+		}
 	}
 
 	/* generate the filter tree. */
 	if (query->filter) {
-		flist = data_filter_generate(query->filter);
-	}
-
-	result = data_result_generate_node(query, provider_child, provider_child->name, search_child);
+		filter = data_filter_generate(query->filter);
+		if (filter) {
+			filter_child = data_filter_find(filter->children, provider_child->name);
+		}
+	}
+
+	result = data_result_generate_node(query, provider_child, provider_child->name, search_child, filter);
 
 	/* release the requested provider. */
 	ao2_ref(provider_child, -1);
@@ -1666,6 +1777,11 @@
 	if (search_child) {
 		ao2_ref(search_child, -1);
 	}
+
+	if (filter_child) {
+		ao2_ref(filter_child, -1);
+	}
+
 	if (search) {
 		data_search_release(search);
 	}
@@ -1673,9 +1789,8 @@
 	result_filtered = result;
 
 	/* release the generated filter tree. */
-	if (flist) {
-		data_filter_list_destroy(flist);
-		ast_free(flist);
+	if (filter) {
+		data_filter_release(filter);
 	}
 
 	return result_filtered;
@@ -1827,14 +1942,25 @@
  * \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,
+static struct ast_data *__ast_data_add(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *name,
 	enum ast_data_type type, void *ptr)
 {
 	struct ast_data *node;
+	struct ast_data_filter *filter_node;
 
 	if (!root || !root->children) {
 		/* invalid data result node. */
 		return NULL;
+	}
+
+	/* check if we need to add this node, based on the filter. */
+	if (filter) {
+		filter_node = data_filter_find(filter->children, name);
+		if (!filter_node) {
+			return NULL;
+		}
+		ao2_ref(filter_node, -1);
 	}
 
 	node = data_result_create(name);
@@ -1876,51 +2002,60 @@
 	return node;
 }
 
-struct ast_data *ast_data_add_node(struct ast_data *root, const char *name)
-{
-	return __ast_data_add(root, name, AST_DATA_CONTAINER, NULL);
-}
-
-struct ast_data *ast_data_add_int(struct ast_data *root, const char *name, int value)
-{
-	return __ast_data_add(root, name, AST_DATA_INTEGER, &value);
-}
-
-struct ast_data *ast_data_add_uint(struct ast_data *root, const char *name,
+struct ast_data *ast_data_add_node(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *name)
+{
+	return __ast_data_add(filter, root, name, AST_DATA_CONTAINER, NULL);
+}
+
+struct ast_data *ast_data_add_int(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *name, int value)
+{
+	return __ast_data_add(filter, root, name, AST_DATA_INTEGER, &value);
+}
+
+struct ast_data *ast_data_add_uint(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *name,
 	unsigned int value)
 {
-	return __ast_data_add(root, name, AST_DATA_UNSIGNED_INTEGER, &value);
-}
-
-struct ast_data *ast_data_add_dbl(struct ast_data *root, const char *childname,
+	return __ast_data_add(filter, root, name, AST_DATA_UNSIGNED_INTEGER, &value);
+}
+
+struct ast_data *ast_data_add_dbl(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	double dbl)
 {
-	return __ast_data_add(root, childname, AST_DATA_DOUBLE, &dbl);
-}
-
-struct ast_data *ast_data_add_bool(struct ast_data *root, const char *childname,
+	return __ast_data_add(filter, root, childname, AST_DATA_DOUBLE, &dbl);
+}
+
+struct ast_data *ast_data_add_bool(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	unsigned int boolean)
 {
-	return __ast_data_add(root, childname, AST_DATA_BOOLEAN, &boolean);
-}
-
-struct ast_data *ast_data_add_ipaddr(struct ast_data *root, const char *childname,
+	return __ast_data_add(filter, root, childname, AST_DATA_BOOLEAN, &boolean);
+}
+
+struct ast_data *ast_data_add_ipaddr(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	struct in_addr addr)
 {
-	return __ast_data_add(root, childname, AST_DATA_IPADDR, &addr);
-}
-
-struct ast_data *ast_data_add_ptr(struct ast_data *root, const char *childname,
+	return __ast_data_add(filter, root, childname, AST_DATA_IPADDR, &addr);
+}
+
+struct ast_data *ast_data_add_ptr(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	void *ptr)
 {
-	return __ast_data_add(root, childname, AST_DATA_POINTER, ptr);
-}
-
-struct ast_data *ast_data_add_str(struct ast_data *root, const char *childname,
+	return __ast_data_add(filter, root, childname, AST_DATA_POINTER, ptr);
+}
+
+struct ast_data *ast_data_add_str(const struct ast_data_filter *filter,
+	struct ast_data *root, const char *childname,
 	const char *value)
 {
 	char *name;
 	size_t namelen = 1 + (ast_strlen_zero(value) ? 0 : strlen(value));
+	struct ast_data *res;
 
 	if (!(name = ast_malloc(namelen))) {
 		return NULL;
@@ -1928,49 +2063,65 @@
 
 	strcpy(name, (ast_strlen_zero(value) ? "" : value));
 
-	return __ast_data_add(root, childname, AST_DATA_STRING, name);
-}
-
-int __ast_data_add_structure(struct ast_data *root,
+	res = __ast_data_add(filter, root, childname, AST_DATA_STRING, name);
+	if (!res) {
+		ast_free(name);
+	}
+
+	return res;
+}
+
+int __ast_data_add_structure(const struct ast_data_filter *filter, struct ast_data *root,
 	const struct ast_data_mapping_structure *mapping, size_t mapping_len,
 	void *structure)
 {
 	int i;
+	struct ast_data_filter *filter_child = NULL;
+
+	if (filter) {
+		filter_child = data_filter_find(filter->children, root->name);
+		if (!filter_child) {
+			return 0;
+		}
+	}
 
 	for (i = 0; i < mapping_len; i++) {
 		switch (mapping[i].type) {
 		case AST_DATA_INTEGER:
-			ast_data_add_int(root, mapping[i].name,
+			ast_data_add_int(filter_child, root, mapping[i].name,
 				mapping[i].get.AST_DATA_INTEGER(structure));
 			break;
 		case AST_DATA_UNSIGNED_INTEGER:
-			ast_data_add_uint(root, mapping[i].name,
+			ast_data_add_uint(filter_child, root, mapping[i].name,
 				mapping[i].get.AST_DATA_UNSIGNED_INTEGER(structure));
 			break;
 		case AST_DATA_DOUBLE:
-			ast_data_add_dbl(root, mapping[i].name,
+			ast_data_add_dbl(filter_child, root, mapping[i].name,
 				mapping[i].get.AST_DATA_DOUBLE(structure));
 			break;
 		case AST_DATA_BOOLEAN:
-			ast_data_add_bool(root, mapping[i].name,
+			ast_data_add_bool(filter_child, root, mapping[i].name,
 				mapping[i].get.AST_DATA_BOOLEAN(structure));
 			break;
 		case AST_DATA_STRING:
-			ast_data_add_str(root, mapping[i].name,
+			ast_data_add_str(filter_child, root, mapping[i].name,
 				mapping[i].get.AST_DATA_STRING(structure));
 			break;
 		case AST_DATA_CONTAINER:
 			break;
 		case AST_DATA_IPADDR:
-			ast_data_add_ipaddr(root, mapping[i].name,
+			ast_data_add_ipaddr(filter_child, root, mapping[i].name,
 				mapping[i].get.AST_DATA_IPADDR(structure));
 			break;
 		case AST_DATA_POINTER:
-			ast_data_add_ptr(root, mapping[i].name,
+			ast_data_add_ptr(filter_child, root, mapping[i].name,
 				mapping[i].get.AST_DATA_POINTER(structure));
 			break;
 		}
 	}
+
+	ao2_ref(filter_child, -1);
+
 	return 0;
 }
 

Modified: team/group/data_api_gsoc2009/tests/test_data.c
URL: http://svn.asterisk.org/svn-view/asterisk/team/group/data_api_gsoc2009/tests/test_data.c?view=diff&rev=210474&r1=210473&r2=210474
==============================================================================
--- team/group/data_api_gsoc2009/tests/test_data.c (original)
+++ team/group/data_api_gsoc2009/tests/test_data.c Tue Aug  4 16:50:30 2009
@@ -55,7 +55,9 @@
 
 AST_DATA_STRUCTURE(test_structure, DATA_EXPORT_TEST_STRUCTURE);
 
-static int test_data_full_provider(const struct ast_data_search *search, struct ast_data *root)
+static int test_data_full_provider(const struct ast_data_search *search,
+	const struct ast_data_filter *filter,
+	struct ast_data *root)
 {
 	struct ast_data *test_structure;
 	struct test_structure local_test_structure = {
@@ -65,18 +67,20 @@
 		.a_uint = 20
 	};
 
-	test_structure = ast_data_add_node(root, "test_structure");
+	test_structure = ast_data_add_node(filter, root, "test_structure");
 	if (!test_structure) {
 		ast_debug(1, "Internal data api error\n");
 		return 0;
 	}
 
-	ast_data_add_structure(test_structure, test_structure, &local_test_structure);
+	ast_data_add_structure(filter, test_structure, test_structure, &local_test_structure);
 
 	return 0;
 }
 
-static int test_data_null_provider(const struct ast_data_search *search, struct ast_data *root)
+static int test_data_null_provider(const struct ast_data_search *search,
+	const struct ast_data_filter *filter,
+	struct ast_data *root)
 {
 	return 0;
 }
@@ -102,7 +106,8 @@
 	AST_DATA_ENTRY("test/null/node1/node2/node3/node4/node5/node6", &null_provider),
 };
 
-static char *handle_cli_data_get_bench(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_cli_data_get_bench(struct ast_cli_entry *e, int cmd,
+	struct ast_cli_args *a)
 {
 	struct ast_data_query query_null = {
 		.version = AST_DATA_QUERY_VERSION,
@@ -130,7 +135,8 @@
 	ast_cli(a->fd, "Null provider\n");
 	start = ast_tvnow();
 	res = ast_data_get(&query_null);
-	ast_cli(a->fd, "Test complete - %" PRIi64 " us\n", ast_tvdiff_us(ast_tvnow(), start));
+	ast_cli(a->fd, "Test complete - %" PRIi64 " us\n",
+		ast_tvdiff_us(ast_tvnow(), start));
 	ast_data_free(res);
 	/* TODO: Show tree deph and number of nodes. */
 
@@ -138,14 +144,16 @@
 	ast_cli(a->fd, "Full test tree\n");
 	start = ast_tvnow();
 	res = ast_data_get(&query_full);
-	ast_cli(a->fd, "Test complete - %" PRIi64 " us\n", ast_tvdiff_us(ast_tvnow(), start));
+	ast_cli(a->fd, "Test complete - %" PRIi64 " us\n",
+		ast_tvdiff_us(ast_tvnow(), start));
 	ast_data_free(res);
 	/* TODO: Show tree deph and number of nodes. */
 
 	return CLI_SUCCESS;
 }
 
-static char *handle_cli_data_get_automatic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_cli_data_get_automatic(struct ast_cli_entry *e, int cmd,
+	struct ast_cli_args *a)
 {
 	struct ast_data *res, *node;
 	struct ast_data_iterator *i;
@@ -203,7 +211,8 @@
 	return CLI_SUCCESS;
 }
 
-static char *handle_cli_data_get_dump(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_cli_data_get_dump(struct ast_cli_entry *e, int cmd,
+	struct ast_cli_args *a)
 {
 	char *res = CLI_SUCCESS;
 	struct ast_xml_doc *doc;




More information about the asterisk-commits mailing list