<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][14917] </title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=14917">14917</a></dd>
<dt>Author</dt> <dd>brian</dd>
<dt>Date</dt> <dd>2009-09-18 09:37:43 -0500 (Fri, 18 Sep 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre> <a href="http://jira.freeswitch.org/browse/LBDING-15">LBDING-15</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunksrcmodendpointsmod_dingalingmod_dingalingc">freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunksrcmodendpointsmod_dingalingmod_dingalingc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c (14916 => 14917)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c        2009-09-18 09:02:45 UTC (rev 14916)
+++ freeswitch/trunk/src/mod/endpoints/mod_dingaling/mod_dingaling.c        2009-09-18 14:37:43 UTC (rev 14917)
</span><span class="lines">@@ -128,6 +128,8 @@
</span><span class="cx">         char *odbc_dsn;
</span><span class="cx">         char *odbc_user;
</span><span class="cx">         char *odbc_pass;
</span><ins>+        switch_bool_t purge;
+        switch_thread_rwlock_t *rwlock;
</ins><span class="cx">         switch_odbc_handle_t *master_odbc;
</span><span class="cx">         switch_mutex_t *mutex;
</span><span class="cx">         ldl_handle_t *handle;
</span><span class="lines">@@ -215,6 +217,8 @@
</span><span class="cx"> static switch_status_t load_config(void);
</span><span class="cx"> static int sin_callback(void *pArg, int argc, char **argv, char **columnNames);
</span><span class="cx"> 
</span><ins>+static switch_status_t soft_reload(void);
+
</ins><span class="cx"> #define is_special(s) (s &amp;&amp; (strstr(s, &quot;ext+&quot;) || strstr(s, &quot;user+&quot;)))
</span><span class="cx"> 
</span><span class="cx"> static char *translate_rpid(char *in, char *ext)
</span><span class="lines">@@ -1241,6 +1245,15 @@
</span><span class="cx">                 if (switch_core_codec_ready(&amp;tech_pvt-&gt;write_codec)) {
</span><span class="cx">                         switch_core_codec_destroy(&amp;tech_pvt-&gt;write_codec);
</span><span class="cx">                 }
</span><ins>+
+                switch_thread_rwlock_unlock(tech_pvt-&gt;profile-&gt;rwlock);
+
+                if(tech_pvt-&gt;profile-&gt;purge) {
+                        mdl_profile_t *profile = tech_pvt-&gt;profile;
+                        if(switch_core_hash_delete(globals.profile_hash, profile-&gt;name) == SWITCH_STATUS_SUCCESS) {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Profile %s deleted successfully\n&quot;, profile-&gt;name);
+                        }
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return SWITCH_STATUS_SUCCESS;
</span><span class="lines">@@ -1673,6 +1686,18 @@
</span><span class="cx">                                 }
</span><span class="cx">                         }
</span><span class="cx"> 
</span><ins>+                        if(mdl_profile-&gt;purge) {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Profile '%s' is marked for deletion, disallowing outgoing call\n&quot;, mdl_profile-&gt;name);
+                                terminate_session(new_session, __LINE__, SWITCH_CAUSE_NORMAL_UNSPECIFIED);
+                                return SWITCH_CAUSE_NORMAL_UNSPECIFIED;
+                        }
+
+                        if(switch_thread_rwlock_tryrdlock(mdl_profile-&gt;rwlock) != SWITCH_STATUS_SUCCESS) {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Can't do read lock on profile '%s'\n&quot;, mdl_profile-&gt;name);
+                                terminate_session(new_session, __LINE__, SWITCH_CAUSE_NORMAL_UNSPECIFIED);
+                                return SWITCH_CAUSE_NORMAL_UNSPECIFIED;
+                        }
+
</ins><span class="cx">                         if (!ldl_handle_ready(mdl_profile-&gt;handle)) {
</span><span class="cx">                                 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG, &quot;Doh! we are not logged in yet!\n&quot;);
</span><span class="cx">                                 terminate_session(new_session, __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
</span><span class="lines">@@ -1845,7 +1870,7 @@
</span><span class="cx"> #define LOGOUT_SYNTAX &quot;dl_logout &lt;profile_name&gt;&quot;
</span><span class="cx"> #define LOGIN_SYNTAX &quot;Existing Profile:\ndl_login profile=&lt;profile_name&gt;\nDynamic Profile:\ndl_login var1=val1;var2=val2;varN=valN\n&quot;
</span><span class="cx"> #define DEBUG_SYNTAX &quot;dl_debug [true|false]&quot;
</span><del>-#define DINGALING_SYNTAX &quot;dingaling [status]&quot;
</del><ins>+#define DINGALING_SYNTAX &quot;dingaling [status|reload]&quot;
</ins><span class="cx"> 
</span><span class="cx">         SWITCH_ADD_API(api_interface, &quot;dl_debug&quot;, &quot;DingaLing Debug&quot;, dl_debug, DEBUG_SYNTAX);
</span><span class="cx">         SWITCH_ADD_API(api_interface, &quot;dl_pres&quot;, &quot;DingaLing Presence&quot;, dl_pres, PRES_SYNTAX);
</span><span class="lines">@@ -1905,6 +1930,9 @@
</span><span class="cx">                                                 profile-&gt;password,
</span><span class="cx">                                                 profile-&gt;server,
</span><span class="cx">                                                 profile-&gt;user_flags, profile-&gt;message, handle_loop, handle_signalling, handle_response, profile) == LDL_STATUS_SUCCESS) {
</span><ins>+                profile-&gt;purge = SWITCH_FALSE;
+                switch_thread_rwlock_create(&amp;profile-&gt;rwlock, module_pool);
+
</ins><span class="cx">                 profile-&gt;handle = handle;
</span><span class="cx">                 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Started Thread for %s@%s\n&quot;, profile-&gt;login, profile-&gt;dialplan);
</span><span class="cx">                 switch_core_hash_insert(globals.profile_hash, profile-&gt;name, profile);
</span><span class="lines">@@ -2161,6 +2189,9 @@
</span><span class="cx">                         }
</span><span class="cx">                         stream-&gt;write_function(stream, &quot;\n&quot;);
</span><span class="cx">                 }
</span><ins>+        } else if (argv[0] &amp;&amp; !strncasecmp(argv[0], &quot;reload&quot;, 6)) {
+                soft_reload();
+                stream-&gt;write_function(stream, &quot;OK\n&quot;);
</ins><span class="cx">         } else {
</span><span class="cx">                 stream-&gt;write_function(stream, &quot;USAGE: %s\n&quot;, DINGALING_SYNTAX);
</span><span class="cx">         }
</span><span class="lines">@@ -2237,6 +2268,229 @@
</span><span class="cx">         return status;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+static switch_bool_t match_profile(mdl_profile_t *profile, mdl_profile_t *new_profile)
+{
+        if(profile == new_profile) {
+                return SWITCH_TRUE;
+        }
+
+        if(
+        ((!new_profile-&gt;name &amp;&amp; !profile-&gt;name) || 
+         (new_profile-&gt;name &amp;&amp; profile-&gt;name &amp;&amp; !strcasecmp(new_profile-&gt;name, profile-&gt;name))) &amp;&amp;
+        ((!new_profile-&gt;login &amp;&amp; !profile-&gt;login) || 
+         (new_profile-&gt;login &amp;&amp; profile-&gt;login &amp;&amp; !strcasecmp(new_profile-&gt;login, profile-&gt;login))) &amp;&amp;
+        ((!new_profile-&gt;password &amp;&amp; !profile-&gt;password) || 
+         (new_profile-&gt;password &amp;&amp; profile-&gt;password &amp;&amp; !strcasecmp(new_profile-&gt;password, profile-&gt;password))) &amp;&amp;
+        ((!new_profile-&gt;message &amp;&amp; !profile-&gt;message) || 
+         (new_profile-&gt;message &amp;&amp; profile-&gt;message &amp;&amp; !strcasecmp(new_profile-&gt;message, profile-&gt;message))) &amp;&amp;
+        ((!new_profile-&gt;avatar &amp;&amp; !profile-&gt;avatar) || 
+         (new_profile-&gt;avatar &amp;&amp; profile-&gt;avatar &amp;&amp; !strcasecmp(new_profile-&gt;avatar, profile-&gt;avatar))) &amp;&amp;
+#ifdef AUTO_REPLY
+        ((!new_profile-&gt;auto_reply &amp;&amp; !profile-&gt;auto_reply) || 
+         (new_profile-&gt;auto_reply &amp;&amp; profile-&gt;auto_reply &amp;&amp; !strcasecmp(new_profile-&gt;auto_reply, profile-&gt;auto_reply))) &amp;&amp;
+#endif
+        ((!new_profile-&gt;dialplan &amp;&amp; !profile-&gt;dialplan) || 
+         (new_profile-&gt;dialplan &amp;&amp; profile-&gt;dialplan &amp;&amp; !strcasecmp(new_profile-&gt;dialplan, profile-&gt;dialplan))) &amp;&amp;
+        ((!new_profile-&gt;local_network &amp;&amp; !profile-&gt;local_network) || 
+         (new_profile-&gt;local_network &amp;&amp; profile-&gt;local_network &amp;&amp; !strcasecmp(new_profile-&gt;local_network, profile-&gt;local_network))) &amp;&amp;
+        ((!new_profile-&gt;ip &amp;&amp; !profile-&gt;ip) || 
+         (new_profile-&gt;ip &amp;&amp; profile-&gt;ip &amp;&amp; !strcasecmp(new_profile-&gt;ip, profile-&gt;ip))) &amp;&amp;
+        ((!new_profile-&gt;extip &amp;&amp; !profile-&gt;extip) || 
+         (new_profile-&gt;extip &amp;&amp; profile-&gt;extip &amp;&amp; !strcasecmp(new_profile-&gt;extip, profile-&gt;extip))) &amp;&amp;
+        ((!new_profile-&gt;server &amp;&amp; !profile-&gt;server) || 
+         (new_profile-&gt;server &amp;&amp; profile-&gt;server &amp;&amp; !strcasecmp(new_profile-&gt;server, profile-&gt;server))) &amp;&amp;
+        ((!new_profile-&gt;timer_name &amp;&amp; !profile-&gt;timer_name) || 
+         (new_profile-&gt;timer_name &amp;&amp; profile-&gt;timer_name &amp;&amp; !strcasecmp(new_profile-&gt;timer_name, profile-&gt;timer_name))) &amp;&amp;
+        ((!new_profile-&gt;lanaddr &amp;&amp; !profile-&gt;lanaddr) || 
+         (new_profile-&gt;lanaddr &amp;&amp; profile-&gt;lanaddr &amp;&amp; !strcasecmp(new_profile-&gt;lanaddr, profile-&gt;lanaddr))) &amp;&amp;
+        ((!new_profile-&gt;exten &amp;&amp; !profile-&gt;exten) || 
+         (new_profile-&gt;exten &amp;&amp; profile-&gt;exten &amp;&amp; !strcasecmp(new_profile-&gt;exten, profile-&gt;exten))) &amp;&amp;
+        ((!new_profile-&gt;context &amp;&amp; !profile-&gt;context) || 
+         (new_profile-&gt;context &amp;&amp; profile-&gt;context &amp;&amp; !strcasecmp(new_profile-&gt;context, profile-&gt;context))) &amp;&amp;
+        (new_profile-&gt;user_flags == profile-&gt;user_flags) &amp;&amp; (new_profile-&gt;acl_count == profile-&gt;acl_count)
+        ) {
+                if (switch_odbc_available()) {
+                        if(!(
+                        ((!new_profile-&gt;odbc_dsn &amp;&amp; !profile-&gt;odbc_dsn) || 
+                         (new_profile-&gt;odbc_dsn &amp;&amp; profile-&gt;odbc_dsn &amp;&amp; !strcasecmp(new_profile-&gt;odbc_dsn, profile-&gt;odbc_dsn))) &amp;&amp;
+                        ((!new_profile-&gt;odbc_user &amp;&amp; !profile-&gt;odbc_user) || 
+                         (new_profile-&gt;odbc_user &amp;&amp; profile-&gt;odbc_user &amp;&amp; !strcasecmp(new_profile-&gt;odbc_user, profile-&gt;odbc_user))) &amp;&amp;
+                        ((!new_profile-&gt;odbc_pass &amp;&amp; !profile-&gt;odbc_pass) || 
+                         (new_profile-&gt;odbc_pass &amp;&amp; profile-&gt;odbc_pass &amp;&amp; !strcasecmp(new_profile-&gt;odbc_pass, profile-&gt;odbc_pass)))
+                        )) {
+                                return SWITCH_FALSE;
+                        }
+                }
+
+                for(int i=0; i&lt;new_profile-&gt;acl_count; i++) {
+                        if(strcasecmp(new_profile-&gt;acl[i], profile-&gt;acl[i]) != 0) {
+                                return SWITCH_FALSE;
+                        }
+                }
+        }
+
+        return SWITCH_TRUE;
+}
+
+static switch_status_t destroy_profile(char *name) 
+{
+        mdl_profile_t *profile = NULL;
+
+        if((profile = switch_core_hash_find(globals.profile_hash, name))) {
+                if (profile-&gt;user_flags &amp; LDL_FLAG_COMPONENT) {
+                        if (switch_odbc_available() &amp;&amp; profile-&gt;odbc_dsn &amp;&amp; profile-&gt;master_odbc) {
+                                switch_odbc_handle_disconnect(profile-&gt;master_odbc);
+                                switch_odbc_handle_destroy(&amp;profile-&gt;master_odbc);
+                        }
+
+                        switch_mutex_destroy(profile-&gt;mutex);
+                }
+
+                if(switch_thread_rwlock_trywrlock(profile-&gt;rwlock) != SWITCH_STATUS_SUCCESS) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Profile %s is busy\n&quot;, profile-&gt;name);
+                        profile-&gt;purge = SWITCH_TRUE;
+                        if(profile-&gt;handle) {
+                                ldl_handle_stop(profile-&gt;handle);
+                        }
+                } else {
+                        switch_thread_rwlock_unlock(profile-&gt;rwlock);
+                        profile-&gt;purge = SWITCH_TRUE;
+
+                        if(profile-&gt;handle) {
+                                ldl_handle_stop(profile-&gt;handle);
+                        }
+
+                        if(switch_core_hash_delete(globals.profile_hash, profile-&gt;name) == SWITCH_STATUS_SUCCESS) {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Profile %s deleted successfully\n&quot;, profile-&gt;name);
+                        }
+                }
+        }
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t soft_reload(void)
+{
+        char *cf = &quot;dingaling.conf&quot;;
+        mdl_profile_t *profile = NULL, *old_profile = NULL;
+        switch_xml_t cfg, xml, /*settings,*/ param, xmlint;
+
+        void *data = NULL;
+        switch_hash_t *name_hash;
+        switch_core_hash_init(&amp;name_hash, module_pool);
+
+        if (!(xml = switch_xml_open_cfg(cf, &amp;cfg, NULL))) {
+                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Open of %s failed\n&quot;, cf);
+                return SWITCH_STATUS_TERM;
+        }
+
+        if (!(xmlint = switch_xml_child(cfg, &quot;profile&quot;))) {
+                if ((xmlint = switch_xml_child(cfg, &quot;interface&quot;))) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, &quot;!!!!!!! DEPRICATION WARNING 'interface' is now 'profile' !!!!!!!\n&quot;);
+                }
+        }
+
+        for (; xmlint; xmlint = xmlint-&gt;next) {
+                char *type = (char *) switch_xml_attr_soft(xmlint, &quot;type&quot;);
+                for (param = switch_xml_child(xmlint, &quot;param&quot;); param; param = param-&gt;next) {
+                        char *var = (char *) switch_xml_attr_soft(param, &quot;name&quot;);
+                        char *val = (char *) switch_xml_attr_soft(param, &quot;value&quot;);
+
+                        if (!profile) {
+                                profile = switch_core_alloc(module_pool, sizeof(*profile));
+                        }
+
+                        set_profile_val(profile, var, val);
+                }
+
+                if (profile &amp;&amp; type &amp;&amp; !strcasecmp(type, &quot;component&quot;)) {
+                        char dbname[256];
+                        switch_core_db_t *db;
+
+                        if (!profile-&gt;login &amp;&amp; profile-&gt;name) {
+                                profile-&gt;login = switch_core_strdup(module_pool, profile-&gt;name);
+                        }
+
+                        switch_set_flag(profile, TFLAG_AUTO);
+                        profile-&gt;message = &quot;&quot;;
+                        profile-&gt;user_flags |= LDL_FLAG_COMPONENT;
+                        switch_mutex_init(&amp;profile-&gt;mutex, SWITCH_MUTEX_NESTED, module_pool);
+                        switch_snprintf(dbname, sizeof(dbname), &quot;dingaling_%s&quot;, profile-&gt;name);
+                        profile-&gt;dbname = switch_core_strdup(module_pool, dbname);
+
+                        if (switch_odbc_available() &amp;&amp; profile-&gt;odbc_dsn) {
+                                if (!(profile-&gt;master_odbc = switch_odbc_handle_new(profile-&gt;odbc_dsn, profile-&gt;odbc_user, profile-&gt;odbc_pass))) {
+                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Cannot Open ODBC Database!\n&quot;);
+                                        continue;
+
+                                }
+                                if (switch_odbc_handle_connect(profile-&gt;master_odbc) != SWITCH_ODBC_SUCCESS) {
+                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Cannot Open ODBC Database!\n&quot;);
+                                        continue;
+                                }
+
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, &quot;Connected ODBC DSN: %s\n&quot;, profile-&gt;odbc_dsn);
+                                switch_odbc_handle_exec(profile-&gt;master_odbc, sub_sql, NULL);
+                                //mdl_execute_sql(profile, sub_sql, NULL);
+                        } else {
+                                if ((db = switch_core_db_open_file(profile-&gt;dbname))) {
+                                        switch_core_db_test_reactive(db, &quot;select * from jabber_subscriptions&quot;, NULL, sub_sql);
+                                } else {
+                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, &quot;Cannot Open SQL Database!\n&quot;);
+                                        continue;
+                                }
+                                switch_core_db_close(db);
+                        }
+                }
+
+                if (profile) {
+                        switch_core_hash_insert(name_hash, profile-&gt;name, profile-&gt;login);
+
+                        if((old_profile = switch_core_hash_find(globals.profile_hash, profile-&gt;name))) {
+                                if(match_profile(old_profile, profile)) {
+                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Found pre-existing profile %s [%s]\n&quot;, profile-&gt;name, profile-&gt;login);
+                                } else {
+                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Overwriting pre-existing profile %s [%s]\n&quot;, profile-&gt;name, profile-&gt;login);
+                                        destroy_profile(old_profile-&gt;name);
+                                        init_profile(profile, switch_test_flag(profile, TFLAG_AUTO) ? 1 : 0);
+                                }
+                        } else {
+                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Found new profile %s [%s]\n&quot;, profile-&gt;name, profile-&gt;login);
+                                init_profile(profile, switch_test_flag(profile, TFLAG_AUTO) ? 1 : 0);
+                        }
+
+                        profile = NULL;
+                }
+        }
+
+        switch_xml_free(xml);
+
+        for (switch_hash_index_t *hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+                switch_hash_this(hi, NULL, NULL, &amp;data);
+                profile = (mdl_profile_t *) data;
+
+                if(switch_core_hash_find(name_hash, profile-&gt;name)) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;New profile %s [%s] activated\n&quot;, profile-&gt;name, profile-&gt;login);
+                } else {
+                        switch_core_hash_insert(name_hash, profile-&gt;name, profile-&gt;name);
+                }
+        }
+
+        for (switch_hash_index_t *hi = switch_hash_first(NULL, name_hash); hi; hi = switch_hash_next(hi)) {
+                switch_hash_this(hi, NULL, NULL, &amp;data);
+
+                if((profile = switch_core_hash_find(globals.profile_hash, (char*)data))) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, &quot;Deleting unused profile %s [%s]\n&quot;, profile-&gt;name, profile-&gt;login);
+                        destroy_profile(profile-&gt;name);
+                }
+        }
+
+        switch_core_hash_destroy(&amp;name_hash);
+
+        return SWITCH_STATUS_SUCCESS;
+}
+
</ins><span class="cx"> static switch_status_t load_config(void)
</span><span class="cx"> {
</span><span class="cx">         char *cf = &quot;dingaling.conf&quot;;
</span><span class="lines">@@ -2672,6 +2926,19 @@
</span><span class="cx">                         status = LDL_STATUS_FALSE;
</span><span class="cx">                         goto done;
</span><span class="cx">                 }
</span><ins>+
+                if(profile-&gt;purge) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Profile '%s' is marked for deletion, disallowing incoming call\n&quot;, profile-&gt;name);
+                        status = LDL_STATUS_FALSE;
+                        goto done;
+                }
+
+                if(switch_thread_rwlock_tryrdlock(profile-&gt;rwlock) != SWITCH_STATUS_SUCCESS) {
+                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, &quot;Can't do read lock on profile '%s'\n&quot;, profile-&gt;name);
+                        status = LDL_STATUS_FALSE;
+                        goto done;
+                }
+
</ins><span class="cx">                 if ((session = switch_core_session_request(dingaling_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL)) != 0) {
</span><span class="cx">                         switch_core_session_add_stream(session, NULL);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>