Index: gw/bb_smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn.c,v
retrieving revision 1.103
diff -b -u -r1.103 bb_smscconn.c
--- gw/bb_smscconn.c	8 Jul 2009 17:37:36 -0000	1.103
+++ gw/bb_smscconn.c	16 Jul 2009 15:58:31 -0000
@@ -748,91 +748,124 @@
     return 0;
 }
 
+
+int smsc2_add_to_list(Octstr *id, List *smsc_group, List *list) {
+    CfgGroup *grp = NULL;
+    SMSCConn *conn;
+    Octstr *smscid;
+    long i;
+    int ret = 0;
+
+    for (i = 0; i < gwlist_len(smsc_group) && (grp = gwlist_get(smsc_group, i)) != NULL; i++) {
+        smscid = cfg_get(grp, octstr_imm("smsc-admin-id"));
+        if (smscid == NULL)
+            smscid = cfg_get(grp, octstr_imm("smsc-id"));
+        if (smscid != NULL && octstr_compare(smscid, id) == 0) {
+            conn = smscconn_create(grp, 1);
+            if (conn != NULL) {
+                gwlist_append(list, conn);
+                ret = 1;
+            }
+        }
+    }
+    return ret;
+}
+
+
 int smsc2_restart_smsc(Octstr *id)
 {
-    CfgGroup *grp;
-    SMSCConn *conn, *new_conn;
-    Octstr *smscid = NULL;
+    SMSCConn *conn;
     long i = -1;
-    int hit;
-    int num = 0;
     int success = 0;
+    List *toremove, *toadd;
+    List *smsc_groups_copy;
+    void *item;
+
+#define CLEANUP_AND_UNLOCK() { \
+    gwlist_destroy(toremove, (void(*)(void*))smscconn_destroy); \
+    gwlist_destroy(toadd, (void(*)(void*))smscconn_destroy); \
+    gw_rwlock_unlock(&smsc_list_lock); \
+}
+
+#define ADD_CONNECTIONS(a, b) { \
+    while ((a = gwlist_extract_first(b)) != NULL) { \
+        smscconn_start(a); \
+        gwlist_append(smsc_list, a); \
+    } \
+}
 
     if (!smsc_running)
         return -1;
 
     gw_rwlock_wrlock(&smsc_list_lock);
+    toremove = gwlist_create();
+    toadd = gwlist_create();
 
-    if (bb_reload_smsc_groups() != 0) {
-        gw_rwlock_unlock(&smsc_list_lock);
-        return -1;
-    }
-    /* find the specific smsc via id */
+    /* stop the connections and move them to a temporary list */
     while((i = smsc2_find(id, ++i)) != -1) {
-        long group_index;
-        /* check if smsc has online status already */
         conn = gwlist_get(smsc_list, i);
-        if (conn != NULL && smscconn_status(conn) != SMSCCONN_DEAD) {
-            warning(0, "HTTP: Could not re-start already running smsc-id `%s'",
-                octstr_get_cstr(id));
-            continue;
-        }
-        /* find the group with equal smsc (admin-)id */
-        hit = -1;
-        grp = NULL;
-        for (group_index = 0; group_index < gwlist_len(smsc_groups) && 
-             (grp = gwlist_get(smsc_groups, group_index)) != NULL; group_index++) {
-            smscid = cfg_get(grp, octstr_imm("smsc-admin-id"));
-            if (smscid == NULL)
-            smscid = cfg_get(grp, octstr_imm("smsc-id"));
-            if (smscid != NULL && octstr_compare(smscid, id) == 0) {
-                if (hit < 0)
-                    hit = 0;
-                if (hit == num)
-                    break;
-                else
-                    hit++;
-            }
-            octstr_destroy(smscid);
-            smscid = NULL;
-        }
-        octstr_destroy(smscid);
-        if (hit != num) {
-            /* config group not found */
-            error(0, "HTTP: Could not find config for smsc-id `%s'", octstr_get_cstr(id));
-            break;
+        gwlist_delete(smsc_list, i, 1);
+        smscconn_shutdown(conn, 0);
+        smscconn_destroy(conn);
+        success = 1;
+        i--;
         }
         
-        info(0,"HTTP: Re-starting smsc-id `%s'", octstr_get_cstr(id));
-
-        new_conn = smscconn_create(grp, 1);
-        if (new_conn == NULL) {
-            error(0, "Start of SMSC connection failed, smsc-id `%s'", octstr_get_cstr(id));
-            continue; /* keep old connection on the list */
+    if (success == 0) {
+        error(0, "Cannot reload SMSC %s: not found", octstr_get_cstr(id));
+        CLEANUP_AND_UNLOCK();
+        return -1;
         }
         
-        /* drop old connection from the active smsc list */
-        gwlist_delete(smsc_list, i, 1);
-        /* destroy the connection */
-        smscconn_destroy(conn);
-        gwlist_insert(smsc_list, i, new_conn);
-        smscconn_start(new_conn);
-        success = 1;
-        num++;
+    /* keep a copy of the smsc groups to restore them later if the new ones fail */
+    smsc_groups_copy = gwlist_create();
+    for (i = 0; i < gwlist_len(smsc_groups); i++) {
+        if ((item = gwlist_get(smsc_groups, i)) != NULL) {
+            gwlist_append(smsc_groups_copy, item);
+        }
     }
 
-    gw_rwlock_unlock(&smsc_list_lock);
+    /* reload the groups from the config file */
+    if (bb_reload_smsc_groups() != 0) {
+        /* if it failed, readd the removed items */
+        success = smsc2_add_to_list(id, smsc_groups, toremove);
+        gwlist_destroy(smsc_groups_copy, NULL);
+        ADD_CONNECTIONS(conn, toremove);
+        CLEANUP_AND_UNLOCK();
+        return -1;
+    }
     
-    if (success == 0) {
+    /* add the new group entries */
+    if (smsc2_add_to_list(id, smsc_groups, toadd) == 0) {
         error(0, "SMSC %s not found", octstr_get_cstr(id));
+        /* if it failed, reload the original groups and re-add the removed connections */
+        smsc_groups = NULL;
+        smsc_groups = gwlist_create();
+        for (i = 0; i < gwlist_len(smsc_groups_copy); i++) {
+            if ((item = gwlist_get(smsc_groups_copy, i)) != NULL) {
+                gwlist_append(smsc_groups, item);
+            }
+        }
+        success = smsc2_add_to_list(id, smsc_groups, toremove);
+        gwlist_destroy(smsc_groups_copy, NULL);
+        ADD_CONNECTIONS(conn, toremove);
+        CLEANUP_AND_UNLOCK();
         return -1;
     }
+
+    gwlist_destroy(smsc_groups_copy, NULL);
+    ADD_CONNECTIONS(conn, toadd);
+    CLEANUP_AND_UNLOCK();
+
     /* wake-up the router */
     if (router_thread >= 0)
         gwthread_wakeup(router_thread);
     return 0;
+#undef CLEANUP_AND_UNLOCK;
+#undef ADD_CONNECTIONS;
 }
 
+
 int smsc2_remove_smsc(Octstr *id)
 {
     SMSCConn *conn;
@@ -844,15 +877,14 @@
 
     gw_rwlock_wrlock(&smsc_list_lock);
 
-    gwlist_add_producer(smsc_list);
     while((i = smsc2_find(id, ++i)) != -1) {
         conn = gwlist_get(smsc_list, i);
         gwlist_delete(smsc_list, i, 1);
         smscconn_shutdown(conn, 0);
         smscconn_destroy(conn);
         success = 1;
+        i--;
     }
-    gwlist_remove_producer(smsc_list);
 
     gw_rwlock_unlock(&smsc_list_lock);
     if (success == 0) {
@@ -885,7 +917,6 @@
         return -1;
     }
 
-    gwlist_add_producer(smsc_list);
     grp = NULL;
     for (i = 0; i < gwlist_len(smsc_groups) &&
         (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
@@ -902,7 +933,6 @@
             }
         }
     }
-    gwlist_remove_producer(smsc_list);
     gw_rwlock_unlock(&smsc_list_lock);
     if (success == 0) {
         error(0, "SMSC %s not found", octstr_get_cstr(id));
Index: gw/bearerbox.h
===================================================================
RCS file: /home/cvs/gateway/gw/bearerbox.h,v
retrieving revision 1.36
diff -b -u -r1.36 bearerbox.h
--- gw/bearerbox.h	8 Jul 2009 14:29:39 -0000	1.36
+++ gw/bearerbox.h	16 Jul 2009 15:58:31 -0000
@@ -169,6 +169,7 @@
 long smsc2_rout(Msg *msg, int resend);
 
 int smsc2_stop_smsc(Octstr *id);   /* shutdown a specific smsc */
+int smsc2_add_to_list(Octstr *id, List *smsc_group, List *list);   /* add an id from a group to a list */
 int smsc2_restart_smsc(Octstr *id);  /* re-start a specific smsc */
 int smsc2_add_smsc(Octstr *id);   /* add a new smsc */
 int smsc2_remove_smsc(Octstr *id);   /* remove a specific smsc */
