[Freeswitch-branches] [commit] r10752 - freeswitch/branches/cseket/src/mod/applications/mod_voicemail
Author: cseket Date: Sat Dec 13 10:22:36 2008 New Revision: 10752 Log: load profiles on the fly. add loading functions (MODAPP-177) Modified: freeswitch/branches/cseket/src/mod/applications/mod_voicemail/mod_voicemail.c Modified: freeswitch/branches/cseket/src/mod/applications/mod_voicemail/mod_voicemail.c ============================================================================== --- freeswitch/branches/cseket/src/mod/applications/mod_voicemail/mod_voicemail.c (original) +++ freeswitch/branches/cseket/src/mod/applications/mod_voicemail/mod_voicemail.c Sat Dec 13 10:22:36 2008 @@ -51,6 +51,7 @@ static switch_status_t voicemail_inject(const char *data); +const char *global_cf = "voicemail.conf"; static struct { switch_hash_t *profile_hash; int debug; @@ -235,8 +236,24 @@ " password VARCHAR(255)\n" ");\n"; -static void destroy_profile(vm_profile_t *profile) + +static void destroy_profile(const char *profile_name) { + vm_profile_t *profile = NULL; + switch_mutex_lock(globals.mutex); + if ((profile = switch_core_hash_find(globals.profile_hash, profile_name))) { + switch_core_hash_delete(globals.profile_hash, profile_name); + } + switch_mutex_unlock(globals.mutex); + + if (!profile) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile %s\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) { @@ -247,84 +264,22 @@ switch_core_destroy_memory_pool(&profile->pool); } -static vm_profile_t *create_profile(char *name) +static vm_profile_t * load_profile(const char *profile_name) { vm_profile_t *profile = NULL; - switch_memory_pool_t *pool; - - switch_core_new_memory_pool(&pool); - - profile = switch_core_alloc(pool, sizeof(*profile)); - profile->pool = pool; - switch_thread_rwlock_create(&profile->rwlock, pool); - profile->name = switch_core_strdup(pool, name); - - return profile; -} - + switch_xml_t x_profiles, x_profile, x_email, param, cfg, xml; -static switch_status_t load_config(void) -{ - char *cf = "voicemail.conf"; - vm_profile_t *profile = NULL; - switch_xml_t cfg, xml, settings, param, x_profile, x_profiles, x_email; - switch_hash_index_t *hi; - void *val; - - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); - return SWITCH_STATUS_TERM; + if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); + return profile; } - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "debug")) { - globals.debug = atoi(val); - } - } - } - + if (!(x_profiles = switch_xml_child(cfg, "profiles"))) { goto end; } - - /* destroy old profiles */ - destroy: - for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { - switch_hash_this(hi, NULL, NULL, &val); - profile = (vm_profile_t *) val; - int found = 0; - - for (x_profile = switch_xml_child(x_profiles, "profile"); x_profile; x_profile = x_profile->next) { - char *name = (char *) switch_xml_attr_soft(x_profile, "name"); - if (!(strcasecmp(profile->name, name))) { - found = 1; - break; - } - } - if (found) { - continue; - } - - /* delete from hash, so new comers can't find it */ - switch_mutex_lock(globals.mutex); - switch_core_hash_delete(globals.profile_hash, profile->name); - switch_mutex_unlock(globals.mutex); - - /* wait for readers */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleting profile %s, when readers are left\n", profile->name); - switch_thread_rwlock_wrlock(profile->rwlock); - - destroy_profile(profile); - goto destroy; - } - - for (x_profile = switch_xml_child(x_profiles, "profile"); x_profile; x_profile = x_profile->next) { - char *name = (char *) switch_xml_attr_soft(x_profile, "name"); + if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile_name))) { + switch_memory_pool_t *pool; char *odbc_dsn = NULL, *odbc_user = NULL, *odbc_pass = NULL; char *terminator_key = "#"; char *play_new_messages_key = "1"; @@ -376,7 +331,6 @@ char *record_title = "FreeSWITCH Voicemail"; char *record_comment = "FreeSWITCH Voicemail"; char *record_copyright = "http://www.freeswitch.org"; - int change_profile = 0; switch_bool_t auto_playback_recordings = SWITCH_TRUE; @@ -385,18 +339,21 @@ db = NULL; - if (switch_strlen_zero(name)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No name specified.\n"); - continue; + if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n"); + goto end; } - if (!(profile = switch_core_hash_find(globals.profile_hash, name))) { - profile = create_profile(name); - } else { - change_profile = 1; - switch_thread_rwlock_wrlock(profile->rwlock); + if (!(profile = switch_core_alloc(pool, sizeof(*profile)))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n"); + switch_core_destroy_memory_pool(&pool); + goto end; } + profile->pool = pool; + switch_thread_rwlock_create(&profile->rwlock, pool); + profile->name = switch_core_strdup(pool, profile_name); + if ((x_email = switch_xml_child(x_profile, "email"))) { if ((param = switch_xml_child(x_email, "body"))) { email_body = switch_core_strdup(profile->pool, param->txt); @@ -677,33 +634,23 @@ } } -#ifdef SWITCH_HAVE_ODBC - if (profile->odbc_dsn && profile->master_odbc) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Closing ODBC Database! %s\n", profile->name); - switch_odbc_handle_destroy(&profile->master_odbc); - profile->odbc_dsn = NULL; - profile->odbc_user = NULL; - profile->odbc_pass = NULL; - } -#endif - if (!switch_strlen_zero(odbc_dsn) && !switch_strlen_zero(odbc_user) && !switch_strlen_zero(odbc_pass)) { profile->odbc_dsn = odbc_dsn; profile->odbc_user = odbc_user; profile->odbc_pass = odbc_pass; } else { - profile->dbname = switch_core_sprintf(profile->pool, "voicemail_%s", name); + profile->dbname = switch_core_sprintf(profile->pool, "voicemail_%s", profile_name); } if (profile->odbc_dsn) { #ifdef SWITCH_HAVE_ODBC if (!(profile->master_odbc = switch_odbc_handle_new(profile->odbc_dsn, profile->odbc_user, profile->odbc_pass))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n"); - continue; + goto end; } if (switch_odbc_handle_connect(profile->master_odbc) != SWITCH_ODBC_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n"); - continue; + goto end; } if (switch_odbc_handle_exec(profile->master_odbc, "select count(message_len) from voicemail_msgs", NULL) != SWITCH_ODBC_SUCCESS) { @@ -728,7 +675,7 @@ "cid_name, cid_number, in_folder, file_path, message_len, flags, read_flags from voicemail_data", NULL) != SWITCH_ODBC_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to migrate old voicemail_data to voicemail_msgs!\n"); - continue; + goto end; } switch_odbc_handle_exec(profile->master_odbc, "drop table voicemail_data", NULL); } @@ -766,7 +713,7 @@ "alter table voicemail_prefs add password varchar(255)"); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n"); - continue; + goto end; } switch_core_db_close(db); } @@ -832,18 +779,65 @@ switch_copy_string(profile->file_ext, file_ext, sizeof(profile->file_ext)); switch_mutex_init(&profile->mutex, SWITCH_MUTEX_NESTED, profile->pool); - if (change_profile) { - switch_thread_rwlock_unlock(profile->rwlock); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added Profile %s\n", profile->name); - switch_mutex_lock(globals.mutex); - switch_core_hash_insert(globals.profile_hash, profile->name, profile); - switch_mutex_unlock(globals.mutex); - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added Profile %s\n", profile->name); + switch_core_hash_insert(globals.profile_hash, profile->name, profile); } end: + if (xml) { + switch_xml_free(xml); + } + return profile; + +} + + +static vm_profile_t * get_profile(const char *profile_name) +{ + vm_profile_t *profile; + + switch_mutex_lock(globals.mutex); + if (!(profile = switch_core_hash_find(globals.profile_hash, profile_name))) { + profile = load_profile(profile_name); + } + if (profile) { + switch_thread_rwlock_rdlock(profile->rwlock); + } + switch_mutex_unlock(globals.mutex); + + return profile; +} + + +static switch_status_t load_config(void) +{ + switch_xml_t cfg, xml, settings, param, x_profiles, x_profile; + + if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf); + return SWITCH_STATUS_TERM; + } + + switch_mutex_lock(globals.mutex); + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "debug")) { + globals.debug = atoi(val); + } + } + } + + if ((x_profiles = switch_xml_child(cfg, "profiles"))) { + for (x_profile = switch_xml_child(x_profiles, "profile"); x_profile; x_profile = x_profile->next) { + load_profile(switch_xml_attr_soft(x_profile, "name")); + } + } + switch_mutex_unlock(globals.mutex); + switch_xml_free(xml); return SWITCH_STATUS_SUCCESS; } @@ -1707,16 +1701,11 @@ caller_id_number = caller_profile->caller_id_number; } - switch_mutex_lock(globals.mutex); - - if (!(profile = switch_core_hash_find(globals.profile_hash, profile_name))) { + if (!(profile = get_profile(profile_name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error invalid profile %s\n", profile_name); - switch_mutex_unlock(globals.mutex); return; } - switch_thread_rwlock_rdlock(profile->rwlock); - switch_mutex_unlock(globals.mutex); - + timeout = profile->digit_timeout; attempts = profile->max_login_attempts; status = switch_ivr_phrase_macro(session, VM_HELLO_MACRO, NULL, NULL, &args); @@ -2087,8 +2076,6 @@ } - - thepass = thehash = NULL; switch_snprintf(sql, sizeof(sql), "select * from voicemail_prefs where username='%s' and domain='%s'", myid, domain_name); vm_execute_sql_callback(profile, profile->mutex, sql, prefs_callback, &cbt); @@ -2134,7 +2121,6 @@ } } - if (!mypass) { if (auth) { @@ -2153,8 +2139,6 @@ } } - - if (vmhash) { thehash = vmhash; } @@ -2636,23 +2620,18 @@ goto end; } - switch_mutex_lock(globals.mutex); - if (!(profile = switch_core_hash_find(globals.profile_hash, domain))) { - profile = switch_core_hash_find(globals.profile_hash, "default"); + if (!(profile = get_profile(domain))) { + profile = get_profile("default"); } if (!profile) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find profile\n"); status = SWITCH_STATUS_FALSE; - switch_mutex_unlock(globals.mutex); } else { switch_xml_t x_domain, xml_root; switch_event_t *my_params = NULL; switch_xml_t ut; - switch_thread_rwlock_rdlock(profile->rwlock); - switch_mutex_unlock(globals.mutex); - switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS); switch_assert(my_params); switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain); @@ -2753,17 +2732,11 @@ memset(&cbt, 0, sizeof(cbt)); - switch_mutex_lock(globals.mutex); - - if (!(profile = switch_core_hash_find(globals.profile_hash, profile_name))) { + if (!(profile = get_profile(profile_name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error invalid profile %s\n", profile_name); - switch_mutex_unlock(globals.mutex); return SWITCH_STATUS_FALSE;; } - switch_thread_rwlock_rdlock(profile->rwlock); - switch_mutex_unlock(globals.mutex); - if (id) { int ok = 1; switch_event_t *params = NULL; @@ -3668,7 +3641,7 @@ return SWITCH_STATUS_SUCCESS; } -#define VOICEMAIL_SYNTAX "rss [<host> <port> <uri> <user> <domain>] | rescan [reloadxml]" +#define VOICEMAIL_SYNTAX "rss [<host> <port> <uri> <user> <domain>] | [load|unload|reload] <profile> [reloadxml]" SWITCH_STANDARD_API(voicemail_api_function) { int argc = 0; @@ -3681,6 +3654,9 @@ int rss = 0, xarg = 0; switch_hash_index_t *hi; void *val = NULL; + switch_xml_t xml_root; + const char *err; + if (session) { return SWITCH_STATUS_FALSE; @@ -3705,27 +3681,40 @@ if (!strcasecmp(argv[0], "rss")) { rss++; xarg++; - } else if (!strcasecmp(argv[0], "rescan")) { - switch_xml_t xml_root; - const char *err; - if (argc > 1 && !strcasecmp(argv[1], "reloadxml")) { + } else if (argc > 1 && !strcasecmp(argv[0], "load")) { + if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) { if ((xml_root = switch_xml_open_root(1, &err))) { switch_xml_free(xml_root); } stream->write_function(stream, "Reload XML [%s]\n", err); } - if (load_config() == SWITCH_STATUS_SUCCESS) { - stream->write_function(stream, "+OK scan complete\n"); - } else { - stream->write_function(stream, "-ERR scan failed\n"); - goto error; + if ((profile = get_profile(argv[1]))) { + switch_thread_rwlock_unlock(profile->rwlock); } + stream->write_function(stream, "+OK load complete\n"); goto done; + } else if (argc > 1 && !strcasecmp(argv[0], "unload")) { + destroy_profile(argv[1]); + stream->write_function(stream, "+OK unload complete\n"); + goto done; + } else if (argc > 1 && !strcasecmp(argv[0], "reload")) { + destroy_profile(argv[1]); + if (argc > 2 && !strcasecmp(argv[2], "reloadxml")) { + if ((xml_root = switch_xml_open_root(1, &err))) { + switch_xml_free(xml_root); + } + stream->write_function(stream, "Reload XML [%s]\n", err); + } + if ((profile = get_profile(argv[1]))) { + switch_thread_rwlock_unlock(profile->rwlock); + } + stream->write_function(stream, "+OK reload complete\n"); + goto done; + } else if (!strcasecmp(argv[0], "status")) { stream->write_function(stream, "============================\n"); switch_mutex_lock(globals.mutex); for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { - vm_profile_t * profile = NULL; switch_hash_this(hi, NULL, NULL, &val); profile = (vm_profile_t *) val; stream->write_function(stream, "Profile: %s\n", profile->name); @@ -3751,35 +3740,31 @@ goto error; } - switch_mutex_lock(globals.mutex); - profile = switch_core_hash_find(globals.profile_hash, domain); - - if (!profile) { - profile = switch_core_hash_find(globals.profile_hash, "default"); + if (!(profile = get_profile(domain))) { + profile = get_profile("default"); } if (!profile) { switch_hash_index_t *hi; void *val; + switch_mutex_lock(globals.mutex); for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, NULL, NULL, &val); profile = (vm_profile_t *) val; if (profile) { + switch_thread_rwlock_rdlock(profile->rwlock); break; } } + switch_mutex_unlock(globals.mutex); } if (!profile) { stream->write_function(stream, "Can't find profile.\n"); - switch_mutex_unlock(globals.mutex); goto error; } - switch_thread_rwlock_rdlock(profile->rwlock); - switch_mutex_unlock(globals.mutex); - if (path_info) { if (!strncasecmp(path_info, "get/", 4)) { do_play(profile, user, domain, path_info + 4, stream); @@ -3793,8 +3778,8 @@ if (rss || (path_info && !strncasecmp(path_info, "rss", 3))) { do_rss(profile, user, domain, host, port, uri, stream); } - switch_thread_rwlock_unlock(profile->rwlock); + switch_thread_rwlock_unlock(profile->rwlock); goto done; error:
participants (1)
-
FreeSWITCH SVN