[asterisk-commits] file: branch file/sorceryx3 r386189 - in /team/file/sorceryx3: include/asteri...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Apr 21 17:22:59 CDT 2013


Author: file
Date: Sun Apr 21 17:22:57 2013
New Revision: 386189

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386189
Log:
Add an observer callback for when an object type is loaded/reloaded.

Modified:
    team/file/sorceryx3/include/asterisk/sorcery.h
    team/file/sorceryx3/main/sorcery.c
    team/file/sorceryx3/tests/test_sorcery.c

Modified: team/file/sorceryx3/include/asterisk/sorcery.h
URL: http://svnview.digium.com/svn/asterisk/team/file/sorceryx3/include/asterisk/sorcery.h?view=diff&rev=386189&r1=386188&r2=386189
==============================================================================
--- team/file/sorceryx3/include/asterisk/sorcery.h (original)
+++ team/file/sorceryx3/include/asterisk/sorcery.h Sun Apr 21 17:22:57 2013
@@ -237,6 +237,9 @@
 
 	/*! \brief Callback for when an object is deleted */
 	void (*deleted)(const void *object);
+
+	/*! \brief Callback for when an object type is loaded/reloaded */
+	void (*loaded)(const char *object_type);
 };
 
 /*! \brief Structure which contains details about a sorcery object */

Modified: team/file/sorceryx3/main/sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/file/sorceryx3/main/sorcery.c?view=diff&rev=386189&r1=386188&r2=386189
==============================================================================
--- team/file/sorceryx3/main/sorcery.c (original)
+++ team/file/sorceryx3/main/sorcery.c Sun Apr 21 17:22:57 2013
@@ -105,8 +105,8 @@
 
 /*! \brief Structure used for observer invocations */
 struct sorcery_observer_invocation {
-	/*! \brief Pointer to the observers */
-	struct ao2_container *observers;
+	/*! \brief Pointer to the object type */
+	struct ast_sorcery_object_type *object_type;
 
 	/*! \brief Pointer to the object */
 	void *object;
@@ -655,6 +655,58 @@
 	return 0;
 }
 
+/*! \brief Destructor for observer invocation */
+static void sorcery_observer_invocation_destroy(void *obj)
+{
+	struct sorcery_observer_invocation *invocation = obj;
+
+	ao2_cleanup(invocation->object_type);
+	ao2_cleanup(invocation->object);
+}
+
+/*! \brief Allocator function for observer invocation */
+static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
+{
+	struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
+
+	if (!invocation) {
+		return NULL;
+	}
+
+	ao2_ref(object_type, +1);
+	invocation->object_type = object_type;
+
+	if (object) {
+		ao2_ref(object, +1);
+		invocation->object = object;
+	}
+
+	return invocation;
+}
+
+/*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
+static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
+{
+	const struct ast_sorcery_object_type_observer *observer = obj;
+
+	if (observer->callbacks->loaded) {
+		observer->callbacks->loaded(arg);
+	}
+
+	return 0;
+}
+
+/*! \brief Internal callback function which notifies observers that an object type has been loaded */
+static int sorcery_observers_notify_loaded(void *data)
+{
+	struct sorcery_observer_invocation *invocation = data;
+
+	ao2_callback(invocation->object_type->observers, OBJ_NODATA | OBJ_MULTIPLE, sorcery_observer_notify_loaded, invocation->object_type->name);
+	ao2_cleanup(invocation);
+
+	return 0;
+}
+
 static int sorcery_object_load(void *obj, void *arg, int flags)
 {
 	struct ast_sorcery_object_type *type = obj;
@@ -662,6 +714,14 @@
 
 	details->type = type->name;
 	ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
+
+	if (ao2_container_count(type->observers)) {
+		struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(type, NULL);
+
+		if (invocation && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded, invocation)) {
+			ao2_cleanup(invocation);
+		}
+	}
 
 	return 0;
 }
@@ -1135,32 +1195,6 @@
 	return (!object_wizard->caching && !object_wizard->wizard->create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
 }
 
-/*! \brief Destructor for observer invocation */
-static void sorcery_observer_invocation_destroy(void *obj)
-{
-	struct sorcery_observer_invocation *invocation = obj;
-
-	ao2_cleanup(invocation->observers);
-	ao2_cleanup(invocation->object);
-}
-
-/*! \brief Allocator function for observer invocation */
-static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ao2_container *observers, void *object)
-{
-	struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
-
-	if (!invocation) {
-		return NULL;
-	}
-
-	ao2_ref(observers, +1);
-	invocation->observers = observers;
-	ao2_ref(object, +1);
-	invocation->object = object;
-
-	return invocation;
-}
-
 /*! \brief Internal callback function which notifies an individual observer that an object has been created */
 static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
 {
@@ -1178,7 +1212,7 @@
 {
 	struct sorcery_observer_invocation *invocation = data;
 
-	ao2_callback(invocation->observers, OBJ_NODATA | OBJ_MULTIPLE, sorcery_observer_notify_create, invocation->object);
+	ao2_callback(invocation->object_type->observers, OBJ_NODATA | OBJ_MULTIPLE, sorcery_observer_notify_create, invocation->object);
 	ao2_cleanup(invocation);
 
 	return 0;
@@ -1199,8 +1233,8 @@
 	}
 
 	if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_create, &sdetails)) &&
-	    ao2_container_count(object_type->observers)) {
-		struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type->observers, object);
+		ao2_container_count(object_type->observers)) {
+		struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
 
 		if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
 			ao2_cleanup(invocation);
@@ -1227,7 +1261,7 @@
 {
 	struct sorcery_observer_invocation *invocation = data;
 
-	ao2_callback(invocation->observers, OBJ_NODATA | OBJ_MULTIPLE, sorcery_observer_notify_update, invocation->object);
+	ao2_callback(invocation->object_type->observers, OBJ_NODATA | OBJ_MULTIPLE, sorcery_observer_notify_update, invocation->object);
 	ao2_cleanup(invocation);
 
 	return 0;
@@ -1258,8 +1292,8 @@
 	}
 
 	if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_update, &sdetails)) &&
-	    ao2_container_count(object_type->observers)) {
-		struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type->observers, object);
+		ao2_container_count(object_type->observers)) {
+		struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
 
 		if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
 			ao2_cleanup(invocation);
@@ -1286,7 +1320,7 @@
 {
 	struct sorcery_observer_invocation *invocation = data;
 
-	ao2_callback(invocation->observers, OBJ_NODATA | OBJ_MULTIPLE, sorcery_observer_notify_delete, invocation->object);
+	ao2_callback(invocation->object_type->observers, OBJ_NODATA | OBJ_MULTIPLE, sorcery_observer_notify_delete, invocation->object);
 	ao2_cleanup(invocation);
 
 	return 0;
@@ -1317,8 +1351,8 @@
 	}
 
 	if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_delete, &sdetails)) &&
-	    ao2_container_count(object_type->observers)) {
-		struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type->observers, object);
+		ao2_container_count(object_type->observers)) {
+		struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
 
 		if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
 			ao2_cleanup(invocation);

Modified: team/file/sorceryx3/tests/test_sorcery.c
URL: http://svnview.digium.com/svn/asterisk/team/file/sorceryx3/tests/test_sorcery.c?view=diff&rev=386189&r1=386188&r2=386189
==============================================================================
--- team/file/sorceryx3/tests/test_sorcery.c (original)
+++ team/file/sorceryx3/tests/test_sorcery.c Sun Apr 21 17:22:57 2013
@@ -143,6 +143,9 @@
 
 	/*! \brief Pointer to the deleted object */
 	const void *deleted;
+
+	/*! \brief Whether the type has been loaded */
+	unsigned int loaded:1;
 };
 
 /*! \brief Global scope apply handler integer to make sure it executed */
@@ -215,11 +218,19 @@
 	ast_cond_signal(&observer.cond);
 }
 
+static void sorcery_observer_loaded(const char *object_type)
+{
+	SCOPED_MUTEX(lock, &observer.lock);
+	observer.loaded = 1;
+	ast_cond_signal(&observer.cond);
+}
+
 /*! \brief Test sorcery observer implementation */
 static struct ast_sorcery_observer test_observer = {
 	.created = sorcery_observer_created,
 	.updated = sorcery_observer_updated,
 	.deleted = sorcery_observer_deleted,
+	.loaded = sorcery_observer_loaded,
 };
 
 static struct ast_sorcery *alloc_and_initialize_sorcery(void)
@@ -2166,6 +2177,26 @@
 
 	if (!observer.deleted) {
 		ast_test_status_update(test, "Failed to receive observer notification for object deletion within suitable timeframe\n");
+		goto end;
+	}
+
+	ast_sorcery_reload(sorcery);
+
+	ast_mutex_lock(&observer.lock);
+	while (!observer.loaded) {
+        struct timeval start = ast_tvnow();
+        struct timespec end = {
+                .tv_sec = start.tv_sec + 10,
+                .tv_nsec = start.tv_usec * 1000,
+        };
+		if (ast_cond_timedwait(&observer.cond, &observer.lock, &end) == ETIMEDOUT) {
+			break;
+		}
+	}
+	ast_mutex_unlock(&observer.lock);
+
+	if (!observer.loaded) {
+		ast_test_status_update(test, "Failed to receive observer notification for object type load within suitable timeframe\n");
 		goto end;
 	}
 




More information about the asterisk-commits mailing list