[Freeswitch-svn] [commit] r13884 - freeswitch/trunk/src/mod/applications/mod_voicemail

FreeSWITCH SVN mrene at freeswitch.org
Sat Jun 20 12:55:30 PDT 2009


Author: mrene
Date: Sat Jun 20 14:55:30 2009
New Revision: 13884

Log:
mod_voicemail: implement reload in non-blocking way

Modified:
   freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c

Modified: freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_voicemail/mod_voicemail.c	Sat Jun 20 14:55:30 2009
@@ -67,6 +67,9 @@
 	VM_DATE_NEVER
 } date_location_t;
 
+typedef enum {
+	PFLAG_DESTROY = 1 << 0
+} vm_flags_t;
 
 #define VM_PROFILE_CONFIGITEM_COUNT 100
 
@@ -137,6 +140,7 @@
 	switch_bool_t auto_playback_recordings;
 	switch_thread_rwlock_t *rwlock;
 	switch_memory_pool_t *pool;
+	uint32_t flags;
 	
 	switch_xml_config_item_t config[VM_PROFILE_CONFIGITEM_COUNT];
 	switch_xml_config_string_options_t config_str_pool;
@@ -259,8 +263,19 @@
 	NULL
 };
 
+static void free_profile(vm_profile_t *profile)
+{
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroying Profile %s\n", profile->name);
+#ifdef SWITCH_HAVE_ODBC
+	if (profile->odbc_dsn && profile->master_odbc) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Closing ODBC Database! %s\n", profile->name);
+		switch_odbc_handle_destroy(&profile->master_odbc);
+	}
+#endif
+	switch_core_destroy_memory_pool(&profile->pool);
+}
 
-static void destroy_profile(const char *profile_name) 
+static void destroy_profile(const char *profile_name, switch_bool_t block) 
 {
 	vm_profile_t *profile = NULL;
 	switch_mutex_lock(globals.mutex);
@@ -270,21 +285,23 @@
 	switch_mutex_unlock(globals.mutex);
 
 	if (!profile) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\n", profile_name);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[%s] Invalid Profile\n", profile_name);
 		return;
 	}
-	/* wait readers */
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for write lock (Profile %s)\n", profile->name);	
-	switch_thread_rwlock_wrlock(profile->rwlock);
 
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroying Profile %s\n", profile->name);
-#ifdef SWITCH_HAVE_ODBC
-	if (profile->odbc_dsn && profile->master_odbc) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Closing ODBC Database! %s\n", profile->name);
-		switch_odbc_handle_destroy(&profile->master_odbc);
+	if (block) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] Waiting for write lock\n", profile->name);	
+		switch_thread_rwlock_wrlock(profile->rwlock);
+	} else {
+		if (switch_thread_rwlock_trywrlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) {
+			/* Lock failed, set the destroy flag so it'll be destroyed whenever its not in use anymore */
+			switch_set_flag(profile, PFLAG_DESTROY);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] Profile is in use, memory will be freed whenever its not longer in use\n", profile->name);
+			return;
+		}
 	}
-#endif
-	switch_core_destroy_memory_pool(&profile->pool);
+	
+	free_profile(profile);
 }
 
 
@@ -312,8 +329,6 @@
 	
 	switch_assert(profile);
 	
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "In %s newvalue=%s\n", __SWITCH_FUNC__, newvalue);
-	
 	if (callback_type == CONFIG_LOAD || callback_type == CONFIG_RELOAD)
 	{
 		char *email_headers = NULL, *email_body = NULL;
@@ -350,8 +365,6 @@
 	vm_profile_t *profile = (vm_profile_t*)item->data;
 	
 	switch_assert(profile);
-	
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "In %s newvalue=%s\n", __SWITCH_FUNC__, newvalue);
 		
 	if (callback_type == CONFIG_LOAD || callback_type == CONFIG_RELOAD)
 	{
@@ -389,8 +402,6 @@
 	vm_profile_t *profile = (vm_profile_t*)item->data;
 	
 	switch_assert(profile);
-	
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "In %s newvalue=%s\n", __SWITCH_FUNC__, newvalue);
 		
 	if (callback_type == CONFIG_LOAD || callback_type == CONFIG_RELOAD)
 	{
@@ -756,7 +767,6 @@
 		switch_core_hash_insert(globals.profile_hash, profile->name, profile);
 	}
 
-
   end:
 	if (xml) {
 		switch_xml_free(xml);
@@ -775,6 +785,8 @@
     	profile = load_profile(profile_name);
 	}
 	if (profile) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%s] rwlock\n", profile->name);
+		
 		switch_thread_rwlock_rdlock(profile->rwlock);
 	}
 	switch_mutex_unlock(globals.mutex);
@@ -782,6 +794,16 @@
 	return profile;
 }
 
+static void profile_rwunlock(vm_profile_t *profile)
+{
+	switch_thread_rwlock_unlock(profile->rwlock);
+	if (switch_test_flag(profile, PFLAG_DESTROY)) {
+		if (switch_thread_rwlock_tryrdlock(profile->rwlock) == SWITCH_STATUS_SUCCESS) {
+			free_profile(profile);
+		}
+	}
+}
+
 
 static switch_status_t load_config(void)
 {
@@ -2713,7 +2735,7 @@
 				status = SWITCH_STATUS_FALSE;
 			}
 		}
-		switch_thread_rwlock_unlock(profile->rwlock);
+		profile_rwunlock(profile);
 		
 		switch_core_destroy_memory_pool(&pool);
 
@@ -3147,7 +3169,7 @@
 		voicemail_leave_main(session, profile, domain_name, id);
 	}
 
-	switch_thread_rwlock_unlock(profile->rwlock);
+	profile_rwunlock(profile);
 	
 }
 
@@ -3196,7 +3218,7 @@
 			if ((profile = get_profile(profilename))) {
 				message_count(profile, id, domain, "inbox", &total_new_messages, &total_saved_messages,
 							  &total_new_urgent_messages, &total_saved_urgent_messages);
-				switch_thread_rwlock_unlock(profile->rwlock);
+				profile_rwunlock(profile);
 			} else {
 				stream->write_function(stream, "-ERR No such profile\n");
 				goto done;
@@ -3815,16 +3837,16 @@
 				stream->write_function(stream, "Reload XML [%s]\n", err);
 			}
 			if ((profile = get_profile(argv[1]))) {
-				switch_thread_rwlock_unlock(profile->rwlock);
+				profile_rwunlock(profile);
 			}
 			stream->write_function(stream, "+OK load complete\n");
 			goto done;
 		} else if (argc > 1 && !strcasecmp(argv[0], "unload")) {
-			destroy_profile(argv[1]);
+			destroy_profile(argv[1], SWITCH_FALSE);
 			stream->write_function(stream, "+OK unload complete\n");
 			goto done;
 		} else if (argc > 1 && !strcasecmp(argv[0], "reload")) {
-			destroy_profile(argv[1]);
+			destroy_profile(argv[1], SWITCH_FALSE);
 			if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) {
 				if ((xml_root = switch_xml_open_root(1, &err))) {
 					switch_xml_free(xml_root);
@@ -3832,7 +3854,7 @@
 				stream->write_function(stream, "Reload XML [%s]\n", err);
 			}
 			if ((profile = get_profile(argv[1]))) {
-				switch_thread_rwlock_unlock(profile->rwlock);
+				profile_rwunlock(profile);
 			}
 			stream->write_function(stream, "+OK reload complete\n");
 			goto done;
@@ -3905,7 +3927,7 @@
 		do_rss(profile, user, domain, host, port, uri, stream);
 	}
 
-	switch_thread_rwlock_unlock(profile->rwlock);
+	profile_rwunlock(profile);
 	goto done;
 
   error:



More information about the Freeswitch-svn mailing list