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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jul 17 13:55:28 CDT 2009


Author: eliel
Date: Fri Jul 17 13:55:24 2009
New Revision: 207090

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=207090
Log:
Make a first implementation of the CLI command "queue show" using
the tree returned by the data api.
The callers list is missing, i first need to map the ast_channel structure.

Modified:
    team/group/data_api_gsoc2009/apps/app_queue.c
    team/group/data_api_gsoc2009/include/asterisk/data.h
    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=207090&r1=207089&r2=207090
==============================================================================
--- team/group/data_api_gsoc2009/apps/app_queue.c (original)
+++ team/group/data_api_gsoc2009/apps/app_queue.c Fri Jul 17 13:55:24 2009
@@ -6315,101 +6315,114 @@
 */
 static char *__queues_show(struct mansession *s, int fd, int argc, const char * const *argv)
 {
-	struct call_queue *q;
 	struct ast_str *out = ast_str_alloca(240);
-	int found = 0;
-	time_t now = time(NULL);
-	struct ao2_iterator queue_iter;
-	struct ao2_iterator mem_iter;
-
-	if (argc != 2 && argc != 3)
+	//int found = 0;
+	//time_t now = time(NULL);
+	struct ast_data *queues, *queue, *member;
+	struct ast_data_iterator *iq, *im;
+	struct ast_data_query query = {
+		.path = "asterisk/application/app_queue/queues",
+	};
+	float sl;
+	int callscompleted, has_members = 0, penalty, calls;
+	const char *name, *membername, *interface;
+
+	if (argc != 2 && argc != 3) {
 		return CLI_SHOWUSAGE;
+	}
 
 	if (argc == 3)	{ /* specific queue */
-		if ((q = load_realtime_queue(argv[2]))) {
-			queue_unref(q);
-		}
-	} else if (ast_check_realtime("queues")) {
-		/* This block is to find any queues which are defined in realtime but
-		 * which have not yet been added to the in-core container
-		 */
-		struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
-		char *queuename;
-		if (cfg) {
-			for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) {
-				if ((q = load_realtime_queue(queuename))) {
-					queue_unref(q);
-				}
-			}
-			ast_config_destroy(cfg);
-		}
-	}
-
-	queue_iter = ao2_iterator_init(queues, F_AO2I_DONTLOCK);
-	ao2_lock(queues);
-	while ((q = ao2_iterator_next(&queue_iter))) {
-		float sl;
-		struct call_queue *realtime_queue = NULL;
-
-		ao2_lock(q);
-		/* This check is to make sure we don't print information for realtime
-		 * queues which have been deleted from realtime but which have not yet
-		 * been deleted from the in-core container
-		 */
-		if (q->realtime && !(realtime_queue = load_realtime_queue(q->name))) {
-			ao2_unlock(q);
-			queue_unref(q);
+	}
+
+	queues = ast_data_get(&query);
+	if (!queues) {
+		return CLI_FAILURE;
+	}
+
+	iq = ast_data_iterator_init(queues, "queue");
+	if (!iq) {
+		ast_data_free(queues);
+		return CLI_FAILURE;
+	}
+
+	while ((queue = ast_data_iterator_next(iq))) {
+		name = ast_data_retrieve_string(queue, "name");
+		if (argc == 3 && strcasecmp(name, argv[2])) {
 			continue;
-		} else if (q->realtime) {
-			queue_unref(realtime_queue);
-		}
-		if (argc == 3 && strcasecmp(q->name, argv[2])) {
-			ao2_unlock(q);
-			queue_unref(q);
-			continue;
-		}
-		found = 1;
-
-		ast_str_set(&out, 0, "%-12.12s has %d calls (max ", q->name, q->count);
-		if (q->maxlen)
-			ast_str_append(&out, 0, "%d", q->maxlen);
-		else
+		}
+
+		ast_str_set(&out, 0, "%-12.12s has %d calls (max ", name,
+			ast_data_retrieve_int(queue, "count"));
+
+		if (ast_data_retrieve_int(queue, "maxlen")) {
+			ast_str_append(&out, 0, "%d", ast_data_retrieve_int(queue, "maxlen"));
+		} else {
 			ast_str_append(&out, 0, "unlimited");
+		}
+
 		sl = 0;
-		if (q->callscompleted > 0)
-			sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
-		ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime, %ds talktime), W:%d, C:%d, A:%d, SL:%2.1f%% within %ds",
-			int2strat(q->strategy), q->holdtime, q->talktime, q->weight,
-			q->callscompleted, q->callsabandoned,sl,q->servicelevel);
+		callscompleted = ast_data_retrieve_int(queue, "callscompleted");
+		if (callscompleted) {
+			sl = 100 * ((float) ast_data_retrieve_int(queue, "callscompletedinsl")
+				/ (float) callscompleted); 
+		}
+		ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime, %ds talktime),"
+			" W:%d, C:%d, A:%d, SL:%2.1f%% within %ds",
+			int2strat(ast_data_retrieve_int(queue, "strategy")),
+			ast_data_retrieve_int(queue, "holdtime"),
+			ast_data_retrieve_int(queue, "talktime"),
+			ast_data_retrieve_int(queue, "weight"),
+			ast_data_retrieve_int(queue, "callscompleted"),
+			ast_data_retrieve_int(queue, "callsabandoned"),
+			sl,
+			ast_data_retrieve_int(queue, "servicelevel"));
+
 		do_print(s, fd, ast_str_buffer(out));
-		if (!ao2_container_count(q->members))
+
+		has_members = 0;
+		im  = ast_data_iterator_init(queue, "members/member");
+		while ((member = ast_data_iterator_next(im))) {
+			if (!has_members) {
+				do_print(s, fd, "   Members: ");
+			}
+			has_members++;
+			membername = ast_data_retrieve_string(member, "membername");
+			ast_str_set(&out, 0, "      %s", membername); 
+			interface = ast_data_retrieve_string(member, "interface");
+
+			if (strcasecmp(membername, interface)) {
+				ast_str_append(&out, 0, " (%s)", interface);
+			}
+
+			penalty = ast_data_retrieve_int(member, "penalty");
+			if (penalty) {
+				ast_str_append(&out, 0, " with penalty %d", penalty);
+			}
+
+			ast_str_append(&out, 0, "%s%s%s (%s)",
+				ast_data_retrieve_int(member, "dynamic") ? " (dynamic)" : "",
+				ast_data_retrieve_int(member, "realtime") ? " (realtime)" : "",
+				ast_data_retrieve_int(member, "paused") ? " (paused)" : "",
+				ast_devstate2str(ast_data_retrieve_int(member, "status")));
+			calls = ast_data_retrieve_int(member, "calls");
+
+			if (calls) {
+				ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
+					calls, (long) (time(NULL) -
+					ast_data_retrieve_int(member, "lastcall")));
+			} else {
+				ast_str_append(&out, 0, " has taken no calls yet");
+			}
+			do_print(s, fd, ast_str_buffer(out));
+		}
+		ast_data_iterator_end(im);
+		if (!has_members) {
 			do_print(s, fd, "   No Members");
-		else {
-			struct member *mem;
-
-			do_print(s, fd, "   Members: ");
-			mem_iter = ao2_iterator_init(q->members, 0);
-			while ((mem = ao2_iterator_next(&mem_iter))) {
-				ast_str_set(&out, 0, "      %s", mem->membername);
-				if (strcasecmp(mem->membername, mem->interface)) {
-					ast_str_append(&out, 0, " (%s)", mem->interface);
-				}
-				if (mem->penalty)
-					ast_str_append(&out, 0, " with penalty %d", mem->penalty);
-				ast_str_append(&out, 0, "%s%s%s (%s)",
-					mem->dynamic ? " (dynamic)" : "",
-					mem->realtime ? " (realtime)" : "",
-					mem->paused ? " (paused)" : "",
-					ast_devstate2str(mem->status));
-				if (mem->calls)
-					ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
-						mem->calls, (long) (time(NULL) - mem->lastcall));
-				else
-					ast_str_append(&out, 0, " has taken no calls yet");
-				do_print(s, fd, ast_str_buffer(out));
-				ao2_ref(mem, -1);
-			}
-		}
+		}
+	}
+	ast_data_iterator_end(iq);
+
+#if 0
 		if (!q->head)
 			do_print(s, fd, "   No Callers");
 		else {
@@ -6436,6 +6449,7 @@
 			ast_str_set(&out, 0, "No queues.");
 		do_print(s, fd, ast_str_buffer(out));
 	}
+#endif
 	return CLI_SUCCESS;
 }
 
@@ -7471,6 +7485,31 @@
 
 AST_DATA_STRUCTURE(member, DATA_EXPORT_MEMBER);
 
+#define DATA_EXPORT_QUEUE_ENT(MEMBER)						\
+	MEMBER(queue_ent, moh, AST_DATA_STRING)					\
+	MEMBER(queue_ent, announce, AST_DATA_STRING)				\
+	MEMBER(queue_ent, context, AST_DATA_STRING)				\
+	MEMBER(queue_ent, digits, AST_DATA_STRING)				\
+	MEMBER(queue_ent, valid_digits, AST_DATA_INTEGER)			\
+	MEMBER(queue_ent, pos, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, prio, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, last_pos_said, AST_DATA_INTEGER)			\
+	MEMBER(queue_ent, last_periodic_announce_time, AST_DATA_INTEGER)	\
+	MEMBER(queue_ent, last_periodic_announce_sound, AST_DATA_INTEGER)	\
+	MEMBER(queue_ent, last_pos, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, opos, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, handled, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, pending, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, max_penalty, AST_DATA_INTEGER)			\
+	MEMBER(queue_ent, min_penalty, AST_DATA_INTEGER)			\
+	MEMBER(queue_ent, linpos, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, linwrapped, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, start, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, expire, AST_DATA_INTEGER)				\
+	MEMBER(queue_ent, cancel_answered_elsewhere, AST_DATA_INTEGER)
+
+AST_DATA_STRUCTURE(queue_ent, DATA_EXPORT_QUEUE_ENT);
+
 /*!
  * \internal
  * \brief Add a queue to the data_root node.
@@ -7484,7 +7523,9 @@
 	int member_added = 1;
 	struct ao2_iterator im;
 	struct member *member;
-	struct ast_data *data_queue = NULL, *data_members = NULL, *data_member;
+	struct queue_ent *qe;
+	struct ast_data *data_queue = NULL, *data_members = NULL;
+	struct ast_data *data_member, *data_callers = NULL, *data_caller;
 
 	/* compare the search pattern. */
 	if (ast_data_search_cmp_structure(search, call_queue, queue, "queues/queue")) {
@@ -7492,6 +7533,7 @@
 		return;
 	}
 
+	/* add queue members */
 	if (queue->members) {
 		member_added = 0;
 		im = ao2_iterator_init(queue->members, 0);
@@ -7530,6 +7572,32 @@
 			ast_data_add_structure(member, data_member, member);
 			member_added = 1;
 			ao2_ref(member, -1);
+		}
+	}
+
+	/* include the callers inside the result. */
+	if (queue->head) {
+		for (qe = queue->head; qe; qe = qe->next) {
+			if (!data_queue) {
+				data_queue = ast_data_add_node(data_root, "queue");
+				if (!data_queue) {
+					continue;
+				}
+			}
+
+			if (!data_callers) {
+				data_callers = ast_data_add_node(data_queue, "callers");
+				if (!data_callers) {
+					continue;
+				}
+			}
+
+			data_caller = ast_data_add_node(data_queue, "caller");
+			if (!data_caller) {
+				continue;
+			}
+
+			ast_data_add_structure(queue_ent, data_caller, qe);
 		}
 	}
 

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=207090&r1=207089&r2=207090
==============================================================================
--- team/group/data_api_gsoc2009/include/asterisk/data.h (original)
+++ team/group/data_api_gsoc2009/include/asterisk/data.h Fri Jul 17 13:55:24 2009
@@ -101,7 +101,25 @@
 /*! \brief opaque definition of an ast_data_search structure. */
 struct ast_data_search;
 
-typedef int (*ast_data_get_cb)(const struct ast_data_search *search, struct ast_data *root);
+/*! \brief structure retrieved from a node, with the nodes content. */
+struct ast_data_retrieve {
+	enum ast_data_type type;
+
+	union {
+		char *AST_DATA_STRING;
+		int AST_DATA_INTEGER;
+		double AST_DATA_DOUBLE;
+		unsigned int AST_DATA_UNSIGNED_INTEGER;
+		unsigned int AST_DATA_BOOLEAN;
+		void *AST_DATA_POINTER;
+		struct in_addr AST_DATA_IPADDR;
+		void *AST_DATA_CONTAINER;
+
+	} value;
+};
+
+typedef int (*ast_data_get_cb)(const struct ast_data_search *search,
+	struct ast_data *root);
 typedef int *(*ast_data_put_cb)(void);
 
 /*! \brief The structure of the node handler. */
@@ -539,45 +557,71 @@
 struct ast_data *ast_data_iterator_next(struct ast_data_iterator *iterator);
 
 /*!
- * \brief Retrieve an integer from a node in the tree.
+ * \brief Retrieve a value from a node in the tree.
  * \param[in] tree The structure returned by a call to ast_data_get.
  * \param[in] path The path to the node.
- * \param[out] value The node content.
+ * \param[out] content The node content.
  * \retval 0 on success.
  * \retval <0 on error.
  */
-int ast_data_retrieve_int(struct ast_data *tree, const char *path, const int *value);
-
-/*!
- * \brief Retrieve an ast_ string from a node in the tree.
- * \param[in] tree A pointer to the tree structure returned by a call to ast_data_get.
- * \param[in] path The path to the string node.
- * \param[out] value The node content.
- * \retval 0 on success.
- * \retval <0 on error.
- */
-int ast_data_retrieve_str(struct ast_data *tree, const char *path,
-	const struct ast_str **value);
-
-/*!
- * \brief Retrieve an string from a node in the tree.
- * \param[in] tree A pointer to the tree structure returned by a call to ast_data_get.
- * \param[in] path The path to the string node.
- * \param[out] value The node content.
- * \retval 0 on success.
- * \retval <0 on error.
- */
-int ast_data_retrieve_char(struct ast_data *tree, const char *path, const char **value);
-
-/*!
- * \brief Retrieve the boolean value of a node.
- * \param[in] tree The pointer to the tree structure returned by a call to ast_data_get.
- * \param[in] path The path to the boolean node.
- * \param[out] value The node content.
- * \retval 0 on success.
- * \retval <0 on error.
- */
-int ast_data_retrieve_bool(struct ast_data *tree, const char *path, const char *value);
+int ast_data_retrieve(struct ast_data *tree, const char *path, struct ast_data_retrieve *content); 
+
+/*!
+ * \brief
+ */
+static inline int ast_data_retrieve_int(struct ast_data *tree, const char *path)
+{
+	struct ast_data_retrieve ret;
+
+	ast_data_retrieve(tree, path, &ret);
+
+	return ret.value.AST_DATA_INTEGER;
+}
+
+static inline unsigned int ast_data_retrieve_bool(struct ast_data *tree, const char *path)
+{
+	struct ast_data_retrieve ret;
+
+	ast_data_retrieve(tree, path, &ret);
+
+	return ret.value.AST_DATA_BOOLEAN;
+}
+
+static inline unsigned int ast_data_retrieve_uint(struct ast_data *tree, const char *path)
+{
+	struct ast_data_retrieve ret;
+
+	ast_data_retrieve(tree, path, &ret);
+
+	return ret.value.AST_DATA_UNSIGNED_INTEGER;
+}
+
+static inline const char *ast_data_retrieve_string(struct ast_data *tree, const char *path)
+{
+	struct ast_data_retrieve ret;
+
+	ast_data_retrieve(tree, path, &ret);
+
+	return ret.value.AST_DATA_STRING;
+}
+
+static inline void *ast_data_retrieve_ptr(struct ast_data *tree, const char *path)
+{
+	struct ast_data_retrieve ret;
+
+	ast_data_retrieve(tree, path, &ret);
+
+	return ret.value.AST_DATA_POINTER;
+}
+
+static inline struct in_addr ast_data_retrieve_ipaddr(struct ast_data *tree, const char *path)
+{
+	struct ast_data_retrieve ret;
+
+	ast_data_retrieve(tree, path, &ret);
+
+	return ret.value.AST_DATA_IPADDR;
+}
 
 #if defined(__cplusplus) || defined(c_plusplus)
 }

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=207090&r1=207089&r2=207090
==============================================================================
--- team/group/data_api_gsoc2009/main/data.c (original)
+++ team/group/data_api_gsoc2009/main/data.c Fri Jul 17 13:55:24 2009
@@ -1976,15 +1976,30 @@
 {
 	struct ast_data_iterator *iterator;
 	struct ao2_iterator i;
+	struct ast_data *internal;
+	char *path, *ptr;
+
+	path = ast_strdupa(elements);
+
+	ptr = strrchr(path, '/');
+	if (ptr) {
+		*ptr = '\0';
+		internal = data_result_get_node(tree, path);
+		if (!internal) {
+			return NULL;
+		}
+	} else {
+		internal = tree;
+	}
 
 	iterator = ast_malloc(sizeof(*iterator));
 	if (!iterator) {
 		return NULL;
 	}
 
-	i = ao2_iterator_init(tree->children, 0);
-
-	iterator->pattern = elements;
+	i = ao2_iterator_init(internal->children, 0);
+
+	iterator->pattern = (ptr ? strrchr(elements, '/') + 1 : elements);
 	iterator->last = NULL;
 	iterator->internal_iterator = i;
 
@@ -2029,6 +2044,50 @@
 	return res;
 }
 
+int ast_data_retrieve(struct ast_data *tree, const char *path, struct ast_data_retrieve *content)
+{
+	struct ast_data *node;
+
+	if (!content) {
+		return -1;
+	}
+
+	node = data_result_get_node(tree, path);
+	if (!node) {
+		ast_log(LOG_ERROR, "Invalid internal node %s\n", path);
+		return -1;
+	}
+
+	content->type = node->type;
+	switch (node->type) {
+	case AST_DATA_STRING:
+		content->value.AST_DATA_STRING = node->payload.str;
+		break;
+	case AST_DATA_INTEGER:
+		content->value.AST_DATA_INTEGER = node->payload.sint;
+		break;
+	case AST_DATA_UNSIGNED_INTEGER:
+		content->value.AST_DATA_UNSIGNED_INTEGER = node->payload.uint;
+		break;
+	case AST_DATA_BOOLEAN:
+		content->value.AST_DATA_BOOLEAN = node->payload.boolean;
+		break;
+	case AST_DATA_IPADDR:
+		content->value.AST_DATA_IPADDR = node->payload.ipaddr;
+		break;
+	case AST_DATA_DOUBLE:
+		content->value.AST_DATA_DOUBLE = node->payload.dbl;
+		break;
+	case AST_DATA_CONTAINER:
+		break;
+	case AST_DATA_POINTER:
+		content->value.AST_DATA_POINTER = node->payload.ptr;
+		break;
+	}
+
+	return 0;
+}
+
 int ast_data_init(void)
 {
 	ast_rwlock_init(&root_data_lock);

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=207090&r1=207089&r2=207090
==============================================================================
--- team/group/data_api_gsoc2009/tests/test_data.c (original)
+++ team/group/data_api_gsoc2009/tests/test_data.c Fri Jul 17 13:55:24 2009
@@ -209,8 +209,7 @@
 	FILE *outfile;
 	struct ast_data_query query = {
 		.version = AST_DATA_QUERY_VERSION,
-		.path = "asterisk/application/app_queue",
-		.search = "app_queue/queues/queue/members/member/interface=Agent/1000",
+		.path = "asterisk/application/app_queue/queues",
 	};
 
 	switch (cmd) {




More information about the asterisk-commits mailing list