[asterisk-commits] dlee: branch dlee/stasis-app r384493 - in /team/dlee/stasis-app: ./ apps/ con...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 1 15:18:24 CDT 2013


Author: dlee
Date: Mon Apr  1 15:18:18 2013
New Revision: 384493

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384493
Log:
Merged revisions 384302-384488 from http://svn.asterisk.org/svn/asterisk/trunk

Modified:
    team/dlee/stasis-app/   (props changed)
    team/dlee/stasis-app/Makefile
    team/dlee/stasis-app/apps/app_voicemail.c
    team/dlee/stasis-app/contrib/scripts/install_prereq
    team/dlee/stasis-app/include/asterisk/app.h
    team/dlee/stasis-app/include/asterisk/test.h
    team/dlee/stasis-app/include/asterisk/uuid.h
    team/dlee/stasis-app/main/manager.c
    team/dlee/stasis-app/main/sorcery.c
    team/dlee/stasis-app/main/stasis.c
    team/dlee/stasis-app/main/test.c
    team/dlee/stasis-app/main/uuid.c
    team/dlee/stasis-app/main/xmldoc.c
    team/dlee/stasis-app/res/res_calendar_exchange.c
    team/dlee/stasis-app/res/res_sorcery_config.c
    team/dlee/stasis-app/tests/test_stasis.c
    team/dlee/stasis-app/tests/test_uuid.c

Propchange: team/dlee/stasis-app/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/dlee/stasis-app/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Apr  1 15:18:18 2013
@@ -1,1 +1,1 @@
-/trunk:1-384291
+/trunk:1-384490

Modified: team/dlee/stasis-app/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/Makefile?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/Makefile (original)
+++ team/dlee/stasis-app/Makefile Mon Apr  1 15:18:18 2013
@@ -377,22 +377,22 @@
 $(OTHER_SUBDIRS): makeopts
 	+ at _ASTCFLAGS="$(OTHER_SUBDIR_CFLAGS) $(_ASTCFLAGS)" ASTCFLAGS="$(ASTCFLAGS)" _ASTLDFLAGS="$(_ASTLDFLAGS)" ASTLDFLAGS="$(ASTLDFLAGS)" $(SUBMAKE) --no-builtin-rules -C $@ SUBDIR=$@ all
 
-defaults.h: makeopts build_tools/make_defaults_h
+defaults.h: makeopts cleantest build_tools/make_defaults_h
 	@build_tools/make_defaults_h > $@.tmp
 	@cmp -s $@.tmp $@ || mv $@.tmp $@
 	@rm -f $@.tmp
 
-main/version.c: FORCE
+main/version.c: FORCE cleantest
 	@build_tools/make_version_c > $@.tmp
 	@cmp -s $@.tmp $@ || mv $@.tmp $@
 	@rm -f $@.tmp
 
-include/asterisk/buildopts.h: menuselect.makeopts
+include/asterisk/buildopts.h: menuselect.makeopts cleantest
 	@build_tools/make_buildopts_h > $@.tmp
 	@cmp -s $@.tmp $@ || mv $@.tmp $@
 	@rm -f $@.tmp
 
-include/asterisk/build.h:
+include/asterisk/build.h: cleantest
 	@build_tools/make_build_h > $@.tmp
 	@cmp -s $@.tmp $@ || mv $@.tmp $@
 	@rm -f $@.tmp
@@ -449,7 +449,7 @@
 	done
 	$(MAKE) -C sounds install
 
-doc/core-en_US.xml: makeopts $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
+doc/core-en_US.xml: makeopts cleantest $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
 	@printf "Building Documentation For: "
 	@echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $@
 	@echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> $@
@@ -463,7 +463,7 @@
 	@echo
 	@echo "</docs>" >> $@
 
-doc/full-en_US.xml: makeopts $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
+doc/full-en_US.xml: makeopts cleantest $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
 ifeq ($(PYTHON),:)
 	@echo "--------------------------------------------------------------------------"
 	@echo "---        Please install python to build full documentation           ---"

Modified: team/dlee/stasis-app/apps/app_voicemail.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/apps/app_voicemail.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/apps/app_voicemail.c (original)
+++ team/dlee/stasis-app/apps/app_voicemail.c Mon Apr  1 15:18:18 2013
@@ -5944,7 +5944,10 @@
 		if (inboxcount2(ext_context, &urgentvoicemails, &newvoicemails, &oldvoicemails)) {
 			ast_log(AST_LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
 		} else {
-			snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &", externnotify, context, extension, newvoicemails, oldvoicemails, urgentvoicemails);
+			snprintf(arguments, sizeof(arguments), "%s %s %s %d %d %d &",
+				externnotify, S_OR(context, "\"\""),
+				extension, newvoicemails,
+				oldvoicemails, urgentvoicemails);
 			ast_debug(1, "Executing %s\n", arguments);
 			ast_safe_system(arguments);
 		}
@@ -10950,7 +10953,6 @@
 	/* If ADSI is supported, setup login screen */
 	adsi_begin(chan, &useadsi);
 
-	ast_test_suite_assert(valid);
 	if (!valid) {
 		goto out;
 	}
@@ -14895,8 +14897,8 @@
 
 	AST_LIST_LOCK(&users);
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&users, vmu, list) {
-		if (!strncmp(context, vmu->context, sizeof(context))
-			&& !strncmp(mailbox, vmu->mailbox, sizeof(mailbox))) {
+		if (!strcmp(context, vmu->context)
+			&& !strcmp(mailbox, vmu->mailbox)) {
 			AST_LIST_REMOVE_CURRENT(list);
 			ast_free(vmu);
 			break;

Modified: team/dlee/stasis-app/contrib/scripts/install_prereq
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/contrib/scripts/install_prereq?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/contrib/scripts/install_prereq (original)
+++ team/dlee/stasis-app/contrib/scripts/install_prereq Mon Apr  1 15:18:18 2013
@@ -37,6 +37,8 @@
 PACKAGES_OBSD="popt gmake wget libxml libogg libvorbis curl iksemel spandsp speex iodbc freetds-0.63p1-msdblib mysql-client gmime sqlite sqlite3 jack"
 
 KVERS=`uname -r`
+
+JANSSON_VER=2.4
 
 case "$1" in
 test)    testcmd=echo ;;
@@ -101,11 +103,25 @@
 	make && make install
 	cd ..
 
-	echo "*** Installing libresample ***"
-	svn co http://svn.digium.com/svn/thirdparty/libresample/trunk libresample-trunk
-	cd libresample-trunk
-	./configure && make && make install
-	cd ..
+	# Only install libresample if it wasn't installed via package
+	if ! test -f /usr/include/libresample.h; then
+	    echo "*** Installing libresample ***"
+	    svn co http://svn.digium.com/svn/thirdparty/libresample/trunk libresample-trunk
+	    cd libresample-trunk
+	    ./configure && make && make install
+	    cd ..
+	fi
+
+	# Only install Jansson if it wasn't installed via package
+	if ! test -f /usr/include/jansson.h; then
+		echo "*** Installing jansson ***"
+		wget -O - http://www.digip.org/jansson/releases/jansson-${JANSSON_VER}.tar.gz | zcat | tar -xf -
+		cd jansson-${JANSSON_VER}
+		./configure && make all && make install
+		cd ..
+		echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local.conf
+		/sbin/ldconfig
+	fi
 }
 
 if in_test_mode; then

Modified: team/dlee/stasis-app/include/asterisk/app.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/include/asterisk/app.h?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/include/asterisk/app.h (original)
+++ team/dlee/stasis-app/include/asterisk/app.h Mon Apr  1 15:18:18 2013
@@ -864,13 +864,13 @@
   \param parse A modifiable buffer containing the input to be parsed
 
   This function will separate the input string using the standard argument
-  separator character ',' and fill in the provided structure, including
+  separator character '|' and fill in the provided structure, including
   the argc argument counter field.
  */
 #define AST_STANDARD_APP_ARGS(args, parse) \
-	args.argc = __ast_app_separate_args(parse, ',', 1, args.argv, ((sizeof(args) - offsetof(typeof(args), argv)) / sizeof(args.argv[0])))
+	args.argc = __ast_app_separate_args(parse, '|', 1, args.argv, ((sizeof(args) - offsetof(typeof(args), argv)) / sizeof(args.argv[0])))
 #define AST_STANDARD_RAW_ARGS(args, parse) \
-	args.argc = __ast_app_separate_args(parse, ',', 0, args.argv, ((sizeof(args) - offsetof(typeof(args), argv)) / sizeof(args.argv[0])))
+	args.argc = __ast_app_separate_args(parse, '|', 0, args.argv, ((sizeof(args) - offsetof(typeof(args), argv)) / sizeof(args.argv[0])))
 
 /*!
   \brief Performs the 'nonstandard' argument separation process for an application.

Modified: team/dlee/stasis-app/include/asterisk/test.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/include/asterisk/test.h?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/include/asterisk/test.h (original)
+++ team/dlee/stasis-app/include/asterisk/test.h Mon Apr  1 15:18:18 2013
@@ -134,6 +134,41 @@
 /*! Macros used for the Asterisk Test Suite AMI events */
 #ifdef TEST_FRAMEWORK
 
+struct stasis_topic;
+struct stasis_message_type;
+
+/*!
+ * \since 12
+ * \brief Obtain the \ref stasis_topic for \ref ast_test_suite_event_notify
+ * messages
+ *
+ * \retval A stasis topic
+ */
+struct stasis_topic *ast_test_suite_topic(void);
+
+/*!
+ * \since 12
+ * \brief Obtain the \ref stasis_message_type for \ref ast_test_suite_event_notify
+ * messages
+ *
+ * \retval A stasis message type
+ */
+struct stasis_message_type *ast_test_suite_message_type(void);
+
+/*!
+ * \since 12
+ * \brief The message payload in a \ref ast_test_suite_message_type
+ */
+struct ast_test_suite_message_payload;
+
+/*!
+ * \since 12
+ * \brief Get the JSON for a \ref ast_test_suite_message_payload
+ *
+ * \retval An \ref ast_json object
+ */
+struct ast_json *ast_test_suite_get_blob(struct ast_test_suite_message_payload *payload);
+
 /*!
  * \brief Notifies the test suite of a change in application state
  *
@@ -151,39 +186,14 @@
 	__attribute__((format(printf, 5, 6)));
 
 /*!
- * \brief Notifies the test suite of a failed assert on an expression
- *
- * \details
- * If the expression provided evaluates to true, no action is taken.  If the expression
- * evaluates to a false, a TestEvent manager event is raised with a subtype of Assert, notifying
- * the test suite that the expression failed to evaluate to true.
- *
- * \param exp	The expression to evaluate
- *
- * \return Nothing
- */
-void __ast_test_suite_assert_notify(const char *file, const char *func, int line, const char *exp);
-
-/*!
  * \ref __ast_test_suite_event_notify()
  */
 #define ast_test_suite_event_notify(s, f, ...) \
 	__ast_test_suite_event_notify(__FILE__, __PRETTY_FUNCTION__, __LINE__, (s), (f), ## __VA_ARGS__)
 
-/*!
- * \ref __ast_test_suite_assert_notify()
- */
-#define ast_test_suite_assert(exp)				\
-	do {										\
-		if (__builtin_expect(!(exp), 1)) {		\
-			__ast_test_suite_assert_notify(__FILE__, __PRETTY_FUNCTION__, __LINE__, #exp); \
-		}										\
-	} while (0)
-
 #else
 
 #define ast_test_suite_event_notify(s, f, ...)
-#define ast_test_suite_assert(exp)
 
 #endif
 

Modified: team/dlee/stasis-app/include/asterisk/uuid.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/include/asterisk/uuid.h?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/include/asterisk/uuid.h (original)
+++ team/dlee/stasis-app/include/asterisk/uuid.h Mon Apr  1 15:18:18 2013
@@ -24,7 +24,7 @@
 #define _ASTERISK_UUID_H
 
 /* Size of an RFC 4122 UUID string plus terminating null byte */
-#define AST_UUID_STR_LEN 37
+#define AST_UUID_STR_LEN (36 + 1)
 
 struct ast_uuid;
 
@@ -50,9 +50,20 @@
  * \param uuid The UUID to convert to a string
  * \param[out] buf The buffer where the UUID string will be stored
  * \param size The size of the buffer. Must be at least AST_UUID_STR_LEN.
- * \returns The UUID string (a pointer to buf)
+ * \return The UUID string (a pointer to buf)
  */
 char *ast_uuid_to_str(const struct ast_uuid *uuid, char *buf, size_t size);
+
+/*!
+ * \brief Generate a UUID string.
+ * \since 12.0.0
+ *
+ * \param buf The buffer where the UUID string will be stored
+ * \param size The size of the buffer. Must be at least AST_UUID_STR_LEN.
+ *
+ * \return The UUID string (a pointer to buf)
+ */
+char *ast_uuid_generate_str(char *buf, size_t size);
 
 /*!
  * \brief Convert a string to a UUID

Modified: team/dlee/stasis-app/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/main/manager.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/main/manager.c (original)
+++ team/dlee/stasis-app/main/manager.c Mon Apr  1 15:18:18 2013
@@ -92,6 +92,8 @@
 #include "asterisk/stringfields.h"
 #include "asterisk/presencestate.h"
 #include "asterisk/stasis.h"
+#include "asterisk/test.h"
+#include "asterisk/json.h"
 
 /*** DOCUMENTATION
 	<manager name="Ping" language="en_US">
@@ -7343,6 +7345,50 @@
 	ast_channel_set_manager_vars(args.argc, args.vars);
 }
 
+#ifdef TEST_FRAMEWORK
+
+static void test_suite_event_cb(void *data, struct stasis_subscription *sub,
+		struct stasis_topic *topic,
+		struct stasis_message *message)
+{
+	struct ast_test_suite_message_payload *payload;
+	struct ast_json *blob;
+	const char *type;
+
+	if (stasis_message_type(message) != ast_test_suite_message_type()) {
+		return;
+	}
+
+	payload = stasis_message_data(message);
+	if (!payload) {
+		return;
+	}
+	blob = ast_test_suite_get_blob(payload);
+	if (!blob) {
+		return;
+	}
+
+	type = ast_json_string_get(ast_json_object_get(blob, "type"));
+	if (ast_strlen_zero(type) || strcmp("testevent", type)) {
+		return;
+	}
+
+	manager_event(EVENT_FLAG_TEST, "TestEvent",
+		"Type: StateChange\r\n"
+		"State: %s\r\n"
+		"AppFile: %s\r\n"
+		"AppFunction: %s\r\n"
+		"AppLine: %jd\r\n"
+		"%s\r\n",
+		ast_json_string_get(ast_json_object_get(blob, "state")),
+		ast_json_string_get(ast_json_object_get(blob, "appfile")),
+		ast_json_string_get(ast_json_object_get(blob, "appfunction")),
+		ast_json_integer_get(ast_json_object_get(blob, "line")),
+		ast_json_string_get(ast_json_object_get(blob, "data")));
+}
+
+#endif
+
 /*! \internal \brief Free a user record.  Should already be removed from the list */
 static void manager_free_user(struct ast_manager_user *user)
 {
@@ -7499,6 +7545,10 @@
 		ast_manager_register_xml_core("AOCMessage", EVENT_FLAG_AOC, action_aocmessage);
 		ast_manager_register_xml_core("Filter", EVENT_FLAG_SYSTEM, action_filter);
 
+#ifdef TEST_FRAMEWORK
+		stasis_subscribe(ast_test_suite_topic(), test_suite_event_cb, NULL);
+#endif
+
 		ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager));
 		__ast_custom_function_register(&managerclient_function, NULL);
 		ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);

Modified: team/dlee/stasis-app/main/sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/main/sorcery.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/main/sorcery.c (original)
+++ team/dlee/stasis-app/main/sorcery.c Mon Apr  1 15:18:18 2013
@@ -807,15 +807,7 @@
 	}
 
 	if (ast_strlen_zero(id)) {
-		struct ast_uuid *uuid = ast_uuid_generate();
-
-		if (!uuid) {
-			ao2_ref(details, -1);
-			return NULL;
-		}
-
-		ast_uuid_to_str(uuid, details->id, AST_UUID_STR_LEN);
-		ast_free(uuid);
+		ast_uuid_generate_str(details->id, sizeof(details->id));
 	} else {
 		ast_copy_string(details->id, id, sizeof(details->id));
 	}

Modified: team/dlee/stasis-app/main/stasis.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/main/stasis.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/main/stasis.c (original)
+++ team/dlee/stasis-app/main/stasis.c Mon Apr  1 15:18:18 2013
@@ -61,7 +61,6 @@
 };
 
 /* Forward declarations for the tightly-coupled subscription object */
-struct stasis_subscription;
 static int topic_add_subscription(struct stasis_topic *topic, struct stasis_subscription *sub);
 
 static void topic_dtor(void *obj)
@@ -106,7 +105,7 @@
 /*! \internal */
 struct stasis_subscription {
 	/*! Unique ID for this subscription */
-	char *uniqueid;
+	char uniqueid[AST_UUID_STR_LEN];
 	/*! Topic subscribed to. */
 	struct stasis_topic *topic;
 	/*! Mailbox for processing incoming messages. */
@@ -121,40 +120,53 @@
 {
 	struct stasis_subscription *sub = obj;
 	ast_assert(!stasis_subscription_is_subscribed(sub));
-	ast_free(sub->uniqueid);
-	sub->uniqueid = NULL;
 	ao2_cleanup(sub->topic);
 	sub->topic = NULL;
 	ast_taskprocessor_unreference(sub->mailbox);
 	sub->mailbox = NULL;
 }
 
+/*!
+ * \brief Invoke the subscription's callback.
+ * \param sub Subscription to invoke.
+ * \param topic Topic message was published to.
+ * \param message Message to send.
+ */
+static void subscription_invoke(struct stasis_subscription *sub,
+				  struct stasis_topic *topic,
+				  struct stasis_message *message)
+{
+	/* Since sub->topic doesn't change, no need to lock sub */
+	sub->callback(sub->data,
+		      sub,
+		      topic,
+		      message);
+}
+
 static void send_subscription_change_message(struct stasis_topic *topic, char *uniqueid, char *description);
 
-struct stasis_subscription *stasis_subscribe(struct stasis_topic *topic, stasis_subscription_cb callback, void *data)
+static struct stasis_subscription *__stasis_subscribe(
+	struct stasis_topic *topic,
+	stasis_subscription_cb callback,
+	void *data,
+	int needs_mailbox)
 {
 	RAII_VAR(struct stasis_subscription *, sub, NULL, ao2_cleanup);
-	RAII_VAR(struct ast_uuid *, id, NULL, ast_free);
-	char uniqueid[AST_UUID_STR_LEN];
 
 	sub = ao2_alloc(sizeof(*sub), subscription_dtor);
 	if (!sub) {
 		return NULL;
 	}
 
-	id = ast_uuid_generate();
-	if (!id) {
-		ast_log(LOG_ERROR, "UUID generation failed\n");
-		return NULL;
-	}
-	ast_uuid_to_str(id, uniqueid, sizeof(uniqueid));
-
-	sub->mailbox = ast_threadpool_serializer(uniqueid, pool);
-	if (!sub->mailbox) {
-		return NULL;
-	}
-
-	sub->uniqueid = ast_strdup(uniqueid);
+	ast_uuid_generate_str(sub->uniqueid, sizeof(sub->uniqueid));
+
+	if (needs_mailbox) {
+		sub->mailbox = ast_threadpool_serializer(sub->uniqueid, pool);
+		if (!sub->mailbox) {
+			return NULL;
+		}
+	}
+
 	ao2_ref(topic, +1);
 	sub->topic = topic;
 	sub->callback = callback;
@@ -163,10 +175,18 @@
 	if (topic_add_subscription(topic, sub) != 0) {
 		return NULL;
 	}
-	send_subscription_change_message(topic, uniqueid, "Subscribe");
+	send_subscription_change_message(topic, sub->uniqueid, "Subscribe");
 
 	ao2_ref(sub, +1);
 	return sub;
+}
+
+struct stasis_subscription *stasis_subscribe(
+	struct stasis_topic *topic,
+	stasis_subscription_cb callback,
+	void *data)
+{
+	return __stasis_subscribe(topic, callback, data, 1);
 }
 
 struct stasis_subscription *stasis_unsubscribe(struct stasis_subscription *sub)
@@ -315,17 +335,8 @@
 static int dispatch_exec(void *data)
 {
 	RAII_VAR(struct dispatch *, dispatch, data, ao2_cleanup);
-	RAII_VAR(struct stasis_topic *, sub_topic, NULL, ao2_cleanup);
-
-	/* Since sub->topic doesn't change, no need to lock sub */
-	ast_assert(dispatch->sub->topic != NULL);
-	ao2_ref(dispatch->sub->topic, +1);
-	sub_topic = dispatch->sub->topic;
-
-	dispatch->sub->callback(dispatch->sub->data,
-				dispatch->sub,
-				sub_topic,
-				dispatch->message);
+
+	subscription_invoke(dispatch->sub, dispatch->topic, dispatch->message);
 
 	return 0;
 }
@@ -341,18 +352,28 @@
 
 	for (i = 0; i < topic->num_subscribers_current; ++i) {
 		struct stasis_subscription *sub = topic->subscribers[i];
-		RAII_VAR(struct dispatch *, dispatch, NULL, ao2_cleanup);
 
 		ast_assert(sub != NULL);
 
-		dispatch = dispatch_create(publisher_topic, message, sub);
-		if (!dispatch) {
-			ast_log(LOG_DEBUG, "Dropping dispatch\n");
-			break;
-		}
-
-		if (ast_taskprocessor_push(sub->mailbox, dispatch_exec, dispatch) == 0) {
-			dispatch = NULL; /* Ownership transferred to mailbox */
+		if (sub->mailbox) {
+			RAII_VAR(struct dispatch *, dispatch, NULL, ao2_cleanup);
+
+			dispatch = dispatch_create(publisher_topic, message, sub);
+			if (!dispatch) {
+				ast_log(LOG_DEBUG, "Dropping dispatch\n");
+				break;
+			}
+
+			if (ast_taskprocessor_push(sub->mailbox, dispatch_exec, dispatch) == 0) {
+				/* Ownership transferred to mailbox.
+				 * Don't increment ref, b/c the task processor
+				 * may have already gotten rid of the object.
+				 */
+				dispatch = NULL;
+			}
+		} else {
+			/* Dispatch directly */
+			subscription_invoke(sub, publisher_topic, message);
 		}
 	}
 }
@@ -380,7 +401,11 @@
 		return NULL;
 	}
 
-	sub = stasis_subscribe(from_topic, stasis_forward_cb, to_topic);
+	/* Forwarding subscriptions should dispatch directly instead of having a
+	 * mailbox. Otherwise, messages forwarded to the same topic from
+	 * different topics may get reordered. Which is bad.
+	 */
+	sub = __stasis_subscribe(from_topic, stasis_forward_cb, to_topic, 0);
 	if (sub) {
 		/* hold a ref to to_topic for this forwarding subscription */
 		ao2_ref(to_topic, +1);

Modified: team/dlee/stasis-app/main/test.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/main/test.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/main/test.c (original)
+++ team/dlee/stasis-app/main/test.c Mon Apr  1 15:18:18 2013
@@ -45,7 +45,19 @@
 #include "asterisk/ast_version.h"
 #include "asterisk/paths.h"
 #include "asterisk/time.h"
-#include "asterisk/manager.h"
+#include "asterisk/stasis.h"
+#include "asterisk/json.h"
+#include "asterisk/astobj2.h"
+
+/*! \since 12
+ * \brief The topic for test suite messages
+ */
+struct stasis_topic *test_suite_topic;
+
+/*! \since 12
+ * \brief The message type for test suite messages
+ */
+static struct stasis_message_type *test_suite_type;
 
 /*! This array corresponds to the values defined in the ast_test_state enum */
 static const char * const test_result2str[] = {
@@ -910,49 +922,104 @@
 	AST_CLI_DEFINE(test_cli_generate_results,          "generate test results to file"),
 };
 
+struct stasis_topic *ast_test_suite_topic(void)
+{
+	return test_suite_topic;
+}
+
+struct stasis_message_type *ast_test_suite_message_type(void)
+{
+	return test_suite_type;
+}
+
+/*!
+ * \since 12
+ * \brief A wrapper object that can be ao2 ref counted around an \ref ast_json blob
+ */
+struct ast_test_suite_message_payload {
+	struct ast_json *blob; /*!< The actual blob that we want to deliver */
+};
+
+/*! \internal
+ * \since 12
+ * \brief Destructor for \ref ast_test_suite_message_payload
+ */
+static void test_suite_message_payload_dtor(void *obj)
+{
+	struct ast_test_suite_message_payload *payload = obj;
+
+	if (payload->blob) {
+		ast_json_unref(payload->blob);
+	}
+}
+
+struct ast_json *ast_test_suite_get_blob(struct ast_test_suite_message_payload *payload)
+{
+	return payload->blob;
+}
+
 void __ast_test_suite_event_notify(const char *file, const char *func, int line, const char *state, const char *fmt, ...)
 {
-	struct ast_str *buf = NULL;
+	RAII_VAR(struct ast_test_suite_message_payload *, payload,
+			ao2_alloc(sizeof(*payload), test_suite_message_payload_dtor),
+			ao2_cleanup);
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_str *, buf, ast_str_create(128), ast_free);
 	va_list ap;
 
-	if (!(buf = ast_str_create(128))) {
+	if (!buf) {
+		return;
+	}
+	if (!payload) {
 		return;
 	}
 
 	va_start(ap, fmt);
 	ast_str_set_va(&buf, 0, fmt, ap);
 	va_end(ap);
-
-	manager_event(EVENT_FLAG_TEST, "TestEvent",
-		"Type: StateChange\r\n"
-		"State: %s\r\n"
-		"AppFile: %s\r\n"
-		"AppFunction: %s\r\n"
-		"AppLine: %d\r\n"
-		"%s\r\n",
-		state, file, func, line, ast_str_buffer(buf));
-
-	ast_free(buf);
-}
-
-void __ast_test_suite_assert_notify(const char *file, const char *func, int line, const char *exp)
-{
-	manager_event(EVENT_FLAG_TEST, "TestEvent",
-		"Type: Assert\r\n"
-		"AppFile: %s\r\n"
-		"AppFunction: %s\r\n"
-		"AppLine: %d\r\n"
-		"Expression: %s\r\n",
-		file, func, line, exp);
+	payload->blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: i, s: s}",
+			     "type", "testevent",
+			     "state", state,
+			     "appfile", file,
+			     "appfunction", func,
+			     "line", line,
+			     "data", ast_str_buffer(buf));
+	if (!payload->blob) {
+		return;
+	}
+	msg = stasis_message_create(ast_test_suite_message_type(), payload);
+	if (!msg) {
+		return;
+	}
+	stasis_publish(ast_test_suite_topic(), msg);
 }
 
 #endif /* TEST_FRAMEWORK */
 
+#ifdef TEST_FRAMEWORK
+
+static void test_cleanup(void)
+{
+	ao2_cleanup(test_suite_topic);
+	test_suite_topic = NULL;
+	ao2_cleanup(test_suite_type);
+	test_suite_type = NULL;
+}
+
+#endif
+
 int ast_test_init(void)
 {
 #ifdef TEST_FRAMEWORK
+	/* Create stasis topic */
+	test_suite_topic = stasis_topic_create("test_suite_topic");
+	test_suite_type = stasis_message_type_create("test_suite_type");
+	if (!test_suite_topic || !test_suite_type) {
+		return -1;
+	}
 	/* Register cli commands */
 	ast_cli_register_multiple(test_cli, ARRAY_LEN(test_cli));
+	ast_register_atexit(test_cleanup);
 #endif
 
 	return 0;

Modified: team/dlee/stasis-app/main/uuid.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/main/uuid.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/main/uuid.c (original)
+++ team/dlee/stasis-app/main/uuid.c Mon Apr  1 15:18:18 2013
@@ -38,13 +38,17 @@
 	uuid_t uu;
 };
 
-struct ast_uuid *ast_uuid_generate(void)
-{
-	struct ast_uuid *uuid = ast_malloc(sizeof(*uuid));
-
-	if (!uuid) {
-		return NULL;
-	}
+/*!
+ * \internal
+ * \brief Generate a UUID.
+ * \since 12.0.0
+ *
+ * \param uuid Fill this with a generated UUID.
+ *
+ * \return Nothing
+ */
+static void generate_uuid(struct ast_uuid *uuid)
+{
 	/* libuuid provides three methods of generating uuids,
 	 * uuid_generate(), uuid_generate_random(), and uuid_generate_time().
 	 *
@@ -114,6 +118,16 @@
 	if (!has_dev_urandom) {
 		ast_mutex_unlock(&uuid_lock);
 	}
+}
+
+struct ast_uuid *ast_uuid_generate(void)
+{
+	struct ast_uuid *uuid = ast_malloc(sizeof(*uuid));
+
+	if (!uuid) {
+		return NULL;
+	}
+	generate_uuid(uuid);
 	return uuid;
 }
 
@@ -124,10 +138,19 @@
 	return buf;
 }
 
+char *ast_uuid_generate_str(char *buf, size_t size)
+{
+	struct ast_uuid uuid;
+
+	generate_uuid(&uuid);
+	return ast_uuid_to_str(&uuid, buf, size);
+}
+
 struct ast_uuid *ast_str_to_uuid(const char *str)
 {
 	struct ast_uuid *uuid = ast_malloc(sizeof(*uuid));
 	int res;
+
 	if (!uuid) {
 		return NULL;
 	}
@@ -143,6 +166,7 @@
 struct ast_uuid *ast_uuid_copy(const struct ast_uuid *src)
 {
 	struct ast_uuid *dst = ast_malloc(sizeof(*dst));
+
 	if (!dst) {
 		return NULL;
 	}
@@ -202,5 +226,4 @@
 	uuid_generate_random(uu);
 
 	ast_debug(1, "UUID system initiated\n");
-	return;
-}
+}

Modified: team/dlee/stasis-app/main/xmldoc.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/main/xmldoc.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/main/xmldoc.c (original)
+++ team/dlee/stasis-app/main/xmldoc.c Mon Apr  1 15:18:18 2013
@@ -709,13 +709,13 @@
 	}
 
 	/* Get the argument separator from the root node attribute name 'argsep', if not found
-	defaults to ','. */
+	defaults to '|'. */
 	attrargsep = ast_xml_get_attribute(rootnode, "argsep");
 	if (attrargsep) {
 		argsep = ast_strdupa(attrargsep);
 		ast_xml_free_attr(attrargsep);
 	} else {
-		argsep = ast_strdupa(",");
+		argsep = ast_strdupa("|");
 	}
 
 	/* Get order of evaluation. */

Modified: team/dlee/stasis-app/res/res_calendar_exchange.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/res/res_calendar_exchange.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/res/res_calendar_exchange.c (original)
+++ team/dlee/stasis-app/res/res_calendar_exchange.c Mon Apr  1 15:18:18 2013
@@ -243,17 +243,9 @@
 static struct ast_str *generate_exchange_uuid(struct ast_str *uid)
 {
 	char buffer[AST_UUID_STR_LEN];
-	struct ast_uuid *uuid = ast_uuid_generate();
-
-	if (!uuid) {
-		ast_str_set(&uid, 0, "%s", "");
-		return uid;
-	}
-
-	ast_str_set(&uid, 0, "%s", ast_uuid_to_str(uuid, buffer, AST_UUID_STR_LEN));
-
-	ast_free(uuid);
-
+
+	ast_uuid_generate_str(buffer, sizeof(buffer));
+	ast_str_set(&uid, 0, "%s", buffer);
 	return uid;
 }
 
@@ -414,9 +406,17 @@
 
 static int exchangecal_write_event(struct ast_calendar_event *event)
 {
-	struct ast_str *body = NULL, *response = NULL, *subdir = NULL;
-	struct ast_str *uid = NULL, *summary = NULL, *description = NULL, *organizer = NULL,
-	               *location = NULL, *start = NULL, *end = NULL, *busystate = NULL;
+	struct ast_str *body = NULL;
+	struct ast_str *response = NULL;
+	struct ast_str *subdir = NULL;
+	struct ast_str *uid = NULL;
+	struct ast_str *summary = NULL;
+	struct ast_str *description = NULL;
+	struct ast_str *organizer = NULL;
+	struct ast_str *location = NULL;
+	struct ast_str *start = NULL;
+	struct ast_str *end = NULL;
+	struct ast_str *busystate = NULL;
 	int ret = -1;
 
 	if (!event) {
@@ -434,7 +434,7 @@
 		goto write_cleanup;
 	}
 
-	if (!(uid = ast_str_create(32)) ||
+	if (!(uid = ast_str_create(AST_UUID_STR_LEN)) ||
 		!(summary = ast_str_create(32)) ||
 		!(description = ast_str_create(32)) ||
 		!(organizer = ast_str_create(32)) ||
@@ -449,7 +449,7 @@
 	if (ast_strlen_zero(event->uid)) {
 		uid = generate_exchange_uuid(uid);
 	} else {
-		ast_str_set(&uid, 36, "%s", event->uid);
+		ast_str_set(&uid, AST_UUID_STR_LEN, "%s", event->uid);
 	}
 
 	if (!is_valid_uuid(uid)) {
@@ -496,7 +496,14 @@
 		"      </a:prop>\n"
 		"    </a:set>\n"
 		"</a:propertyupdate>\n",
-		ast_str_buffer(uid), ast_str_buffer(summary), ast_str_buffer(description), ast_str_buffer(organizer), ast_str_buffer(location), ast_str_buffer(start), ast_str_buffer(end), ast_str_buffer(busystate));
+		ast_str_buffer(uid),
+		ast_str_buffer(summary),
+		ast_str_buffer(description),
+		ast_str_buffer(organizer),
+		ast_str_buffer(location),
+		ast_str_buffer(start),
+		ast_str_buffer(end),
+		ast_str_buffer(busystate));
 	ast_verb(0, "\n\n%s\n\n", ast_str_buffer(body));
 	ast_str_set(&subdir, 0, "/Calendar/%s.eml", ast_str_buffer(uid));
 
@@ -505,39 +512,17 @@
 	}
 
 write_cleanup:
-	if (uid) {
-		ast_free(uid);
-	}
-	if (summary) {
-		ast_free(summary);
-	}
-	if (description) {
-		ast_free(description);
-	}
-	if (organizer) {
-		ast_free(organizer);
-	}
-	if (location) {
-		ast_free(location);
-	}
-	if (start) {
-		ast_free(start);
-	}
-	if (end) {
-		ast_free(end);
-	}
-	if (busystate) {
-		ast_free(busystate);
-	}
-	if (body) {
-		ast_free(body);
-	}
-	if (response) {
-		ast_free(response);
-	}
-	if (subdir) {
-		ast_free(subdir);
-	}
+	ast_free(uid);
+	ast_free(summary);
+	ast_free(description);
+	ast_free(organizer);
+	ast_free(location);
+	ast_free(start);
+	ast_free(end);
+	ast_free(busystate);
+	ast_free(body);
+	ast_free(response);
+	ast_free(subdir);
 
 	return ret;
 }

Modified: team/dlee/stasis-app/res/res_sorcery_config.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/res/res_sorcery_config.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/res/res_sorcery_config.c (original)
+++ team/dlee/stasis-app/res/res_sorcery_config.c Mon Apr  1 15:18:18 2013
@@ -305,19 +305,12 @@
 {
 	char *tmp = ast_strdupa(data), *filename = strsep(&tmp, ","), *option;
 	struct sorcery_config *config;
-	struct ast_uuid *uuid;
 
 	if (ast_strlen_zero(filename) || !(config = ao2_alloc_options(sizeof(*config) + strlen(filename) + 1, sorcery_config_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK))) {
 		return NULL;
 	}
 
-	if (!(uuid = ast_uuid_generate())) {
-		ao2_ref(config, -1);
-		return NULL;
-	}
-
-	ast_uuid_to_str(uuid, config->uuid, AST_UUID_STR_LEN);
-	ast_free(uuid);
+	ast_uuid_generate_str(config->uuid, sizeof(config->uuid));
 
 	ast_rwlock_init(&config->objects.lock);
 	config->buckets = DEFAULT_OBJECT_BUCKETS;

Modified: team/dlee/stasis-app/tests/test_stasis.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/tests/test_stasis.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/tests/test_stasis.c (original)
+++ team/dlee/stasis-app/tests/test_stasis.c Mon Apr  1 15:18:18 2013
@@ -391,7 +391,6 @@
 	return AST_TEST_PASS;
 }
 
-
 AST_TEST_DEFINE(forward)
 {
 	RAII_VAR(struct stasis_topic *, parent_topic, NULL, ao2_cleanup);
@@ -454,6 +453,89 @@
 	ast_test_validate(test, 1 == actual_len);
 	actual_len = consumer_wait_for(parent_consumer, 1);
 	ast_test_validate(test, 1 == actual_len);
+
+	return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(interleaving)
+{
+	RAII_VAR(struct stasis_topic *, parent_topic, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_topic *, topic1, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_topic *, topic2, NULL, ao2_cleanup);
+
+	RAII_VAR(struct stasis_message_type *, test_message_type, NULL, ao2_cleanup);
+
+	RAII_VAR(char *, test_data, NULL, ao2_cleanup);
+
+	RAII_VAR(struct stasis_message *, test_message1, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, test_message2, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, test_message3, NULL, ao2_cleanup);
+
+	RAII_VAR(struct stasis_subscription *, forward_sub1, NULL, stasis_unsubscribe);
+	RAII_VAR(struct stasis_subscription *, forward_sub2, NULL, stasis_unsubscribe);
+	RAII_VAR(struct stasis_subscription *, sub, NULL, stasis_unsubscribe);
+
+	RAII_VAR(struct consumer *, consumer, NULL, ao2_cleanup);
+
+	int actual_len;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = __func__;
+		info->category = test_category;
+		info->summary = "Test sending interleaved events to a parent topic";
+		info->description = "Test sending events to a parent topic.\n"
+			"This test creates three topics (one parent, two children)\n"
+			"and publishes messages alternately between the children.\n"
+			"It verifies that the messages are received in the expected\n"
+			"order.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	test_message_type = stasis_message_type_create("test");
+	ast_test_validate(test, NULL != test_message_type);
+
+	test_data = ao2_alloc(1, NULL);
+	ast_test_validate(test, NULL != test_data);
+
+	test_message1 = stasis_message_create(test_message_type, test_data);
+	ast_test_validate(test, NULL != test_message1);
+	test_message2 = stasis_message_create(test_message_type, test_data);
+	ast_test_validate(test, NULL != test_message2);
+	test_message3 = stasis_message_create(test_message_type, test_data);
+	ast_test_validate(test, NULL != test_message3);
+
+	parent_topic = stasis_topic_create("ParentTestTopic");
+	ast_test_validate(test, NULL != parent_topic);
+	topic1 = stasis_topic_create("Topic1");
+	ast_test_validate(test, NULL != topic1);
+	topic2 = stasis_topic_create("Topic2");
+	ast_test_validate(test, NULL != topic2);
+
+	forward_sub1 = stasis_forward_all(topic1, parent_topic);
+	ast_test_validate(test, NULL != forward_sub1);
+	forward_sub2 = stasis_forward_all(topic2, parent_topic);
+	ast_test_validate(test, NULL != forward_sub2);
+
+	consumer = consumer_create(1);
+	ast_test_validate(test, NULL != consumer);
+
+	sub = stasis_subscribe(parent_topic, consumer_exec, consumer);
+	ast_test_validate(test, NULL != sub);
+	ao2_ref(consumer, +1);
+
+	stasis_publish(topic1, test_message1);
+	stasis_publish(topic2, test_message2);
+	stasis_publish(topic1, test_message3);
+
+	actual_len = consumer_wait_for(consumer, 3);
+	ast_test_validate(test, 3 == actual_len);
+
+	ast_test_validate(test, test_message1 == consumer->messages_rxed[0]);
+	ast_test_validate(test, test_message2 == consumer->messages_rxed[1]);
+	ast_test_validate(test, test_message3 == consumer->messages_rxed[2]);
 
 	return AST_TEST_PASS;
 }
@@ -829,6 +911,7 @@
 	AST_TEST_UNREGISTER(cache);
 	AST_TEST_UNREGISTER(route_conflicts);
 	AST_TEST_UNREGISTER(router);
+	AST_TEST_UNREGISTER(interleaving);
 	return 0;
 }
 
@@ -844,6 +927,7 @@
 	AST_TEST_REGISTER(cache);
 	AST_TEST_REGISTER(route_conflicts);
 	AST_TEST_REGISTER(router);
+	AST_TEST_REGISTER(interleaving);
 	return AST_MODULE_LOAD_SUCCESS;
 }
 

Modified: team/dlee/stasis-app/tests/test_uuid.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/tests/test_uuid.c?view=diff&rev=384493&r1=384492&r2=384493
==============================================================================
--- team/dlee/stasis-app/tests/test_uuid.c (original)
+++ team/dlee/stasis-app/tests/test_uuid.c Mon Apr  1 15:18:18 2013
@@ -50,7 +50,23 @@
 		break;
 	}
 
-	/* First, make sure that we can generate a UUID */
+	/* Use method of generating UUID directly as a string. */
+	ast_uuid_generate_str(uuid_str, sizeof(uuid_str));
+	if (strlen(uuid_str) != (AST_UUID_STR_LEN - 1)) {
+		ast_test_status_update(test, "Failed to directly generate UUID string\n");
+		goto end;
+	}
+	ast_test_status_update(test, "Generate UUID direct to string, got %s\n", uuid_str);
+
+	/* Now convert the direct UUID string to a UUID */
+	uuid1 = ast_str_to_uuid(uuid_str);
+	if (!uuid1) {
+		ast_test_status_update(test, "Unable to convert direct UUID string %s to UUID\n", uuid_str);
+		goto end;
+	}
+	ast_free(uuid1);
+
+	/* Make sure that we can generate a UUID */
 	uuid1 = ast_uuid_generate();
 	if (!uuid1) {
 		ast_test_status_update(test, "Unable to generate a UUID\n");
@@ -71,7 +87,7 @@
 		goto end;
 	}
 
-	ast_test_status_update(test, "Converted uuid to string, got %s\n", uuid_str);
+	ast_test_status_update(test, "Second generated UUID converted to string, got %s\n", uuid_str);
 
 	/* Now convert the string back to a UUID */
 	uuid2 = ast_str_to_uuid(uuid_str);




More information about the asterisk-commits mailing list