Hi,
attached you can find a patch that make it possible to start/stop/restart of
_all_ smscconn's that have equals smsc-id's instead of only one. This patch
maybe need some discussion, due to a behaviour change.
Comments/votes are highly welcome!
Thanks,
Alex
Index: gw/bb_smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn.c,v
retrieving revision 1.76
diff -a -u -p -r1.76 bb_smscconn.c
--- gw/bb_smscconn.c 28 Jun 2004 15:18:35 -0000 1.76
+++ gw/bb_smscconn.c 2 Aug 2004 00:05:21 -0000
@@ -100,12 +100,12 @@ extern Counter *outgoing_sms_counter;
extern List *flow_threads;
extern List *suspended;
extern List *isolated;
-extern Dict *smsbox_routes;
/* our own thingies */
static volatile sig_atomic_t smsc_running;
static List *smsc_list;
+static RWLock smsc_list_lock = GW_RWLOCK_INITIALIZER;
static List *smsc_groups;
static Octstr *unified_prefix;
@@ -191,8 +191,6 @@ void bb_smscconn_sent(SMSCConn *conn, Ms
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
{
- Msg *mnack;
-
switch (reason) {
case SMSCCONN_FAILED_SHUTDOWN:
@@ -202,14 +200,7 @@ void bb_smscconn_send_failed(SMSCConn *c
default:
/* write NACK to store file */
-
- mnack = msg_create(ack);
- mnack->ack.nack = ack_failed;
- mnack->ack.time = sms->sms.time;
- uuid_copy(mnack->ack.id, sms->sms.id);
-
- (void) store_save(mnack);
- msg_destroy(mnack);
+ store_save_ack(sms, ack_failed);
if (conn) counter_increase(conn->failed);
if (reason == SMSCCONN_FAILED_DISCARDED)
@@ -315,13 +306,10 @@ long bb_smscconn_receive(SMSCConn *conn,
bb_alog_sms(conn, sms, "DROPPED Received DLR");
else
bb_alog_sms(conn, sms, "DROPPED Received SMS");
- msg_destroy(copy);
+
/* put nack into store-file */
- copy = msg_create(ack);
- uuid_copy(copy->ack.id, sms->sms.id);
- copy->ack.time = sms->sms.time;
- copy->ack.nack = ack_failed;
- store_save(copy);
+ store_save_ack(sms, ack_failed);
+
msg_destroy(copy);
msg_destroy(sms);
@@ -477,19 +465,24 @@ int smsc2_start(Cfg *cfg)
return 0;
}
-static int smsc2_find(Octstr *id)
+/*
+ * Find a matching smsc-id in the smsc list starting at position start.
+ * NOTE: Caller must ensure that smsc_list is properly locked!
+ */
+static long smsc2_find(Octstr *id, long start)
{
SMSCConn *conn = NULL;
- int i;
+ long i;
- list_lock(smsc_list);
- for (i = 0; i < list_len(smsc_list); i++) {
+ if (start > list_len(smsc_list) || start < 0)
+ return -1;
+
+ for (i = start; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
if (conn != NULL && octstr_compare(conn->id, id) == 0) {
break;
}
}
- list_unlock(smsc_list);
if (i >= list_len(smsc_list))
i = -1;
return i;
@@ -498,87 +491,103 @@ static int smsc2_find(Octstr *id)
int smsc2_stop_smsc(Octstr *id)
{
SMSCConn *conn;
- int i;
+ long i = -1;
+ gw_rwlock_rdlock(&smsc_list_lock);
/* find the specific smsc via id */
- if ((i = smsc2_find(id)) == -1) {
- error(0, "HTTP: Could not shutdown smsc-id `%s'", octstr_get_cstr(id));
- return -1;
- }
- conn = list_get(smsc_list, i);
- if (conn != NULL && conn->status == SMSCCONN_DEAD) {
- error(0, "HTTP: Could not shutdown already dead smsc-id `%s'",
- octstr_get_cstr(id));
- return -1;
+ while((i = smsc2_find(id, ++i)) != -1) {
+ conn = list_get(smsc_list, i);
+ if (conn != NULL && smscconn_status(conn) == SMSCCONN_DEAD) {
+ info(0, "HTTP: Could not shutdown already dead smsc-id `%s'",
+ octstr_get_cstr(id));
+ } else {
+ info(0,"HTTP: Shutting down smsc-id `%s'", octstr_get_cstr(id));
+ smscconn_shutdown(conn, 1); /* shutdown the smsc */
+ }
}
- info(0,"HTTP: Shutting down smsc-id `%s'", octstr_get_cstr(id));
- smscconn_shutdown(conn, 1); /* shutdown the smsc */
+ gw_rwlock_unlock(&smsc_list_lock);
return 0;
}
int smsc2_restart_smsc(Octstr *id)
{
CfgGroup *grp;
- SMSCConn *conn;
+ SMSCConn *conn, *new_conn;
Octstr *smscid = NULL;
- int i;
+ long i = -1;
+ int num = 0;
+ gw_rwlock_wrlock(&smsc_list_lock);
/* find the specific smsc via id */
- if ((i = smsc2_find(id)) == -1) {
- error(0, "HTTP: Could not re-start non defined smsc-id `%s'",
- octstr_get_cstr(id));
- return -1;
- }
-
- /* check if smsc is online status already */
- conn = list_get(smsc_list, i);
- if (conn != NULL && conn->status != SMSCCONN_DEAD) {
- error(0, "HTTP: Could not re-start already running smsc-id `%s'",
- octstr_get_cstr(id));
- return -1;
- }
-
- list_delete(smsc_list, i, 1); /* drop it from the active smsc list */
- smscconn_destroy(conn); /* destroy the connection */
-
- /* find the group with smsc id */
- grp = NULL;
- list_lock(smsc_groups);
- for (i = 0; i < list_len(smsc_groups) &&
- (grp = list_get(smsc_groups, i)) != NULL; i++) {
- smscid = cfg_get(grp, octstr_imm("smsc-id"));
- if (smscid != NULL && octstr_compare(smscid, id) == 0) {
+ while((i = smsc2_find(id, ++i)) != -1) {
+ int hit;
+ long group_index;
+ /* check if smsc has online status already */
+ conn = list_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 id */
+ hit = 0;
+ grp = NULL;
+ for (group_index = 0; group_index < list_len(smsc_groups) &&
+ (grp = list_get(smsc_groups, group_index)) != NULL; group_index++) {
+ smscid = cfg_get(grp, octstr_imm("smsc-id"));
+ if (smscid != NULL && octstr_compare(smscid, id) == 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;
}
+
+ 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 */
+ }
+
+ /* drop old connection from the active smsc list */
+ list_delete(smsc_list, i, 1);
+ /* destroy the connection */
+ smscconn_destroy(conn);
+ list_insert(smsc_list, i, new_conn);
+ smscconn_start(new_conn);
+ num++;
}
- list_unlock(smsc_groups);
- octstr_destroy(smscid);
- if (i > list_len(smsc_groups))
- return -1;
+ gw_rwlock_unlock(&smsc_list_lock);
- info(0,"HTTP: Re-starting smsc-id `%s'", octstr_get_cstr(id));
-
- conn = smscconn_create(grp, 1);
- if (conn == NULL)
- error(0, "Cannot start with SMSC connection failing");
- list_append(smsc_list, conn);
-
- smscconn_start(conn);
+ /* wake-up the router */
if (router_thread >= 0)
gwthread_wakeup(router_thread);
+
return 0;
}
void smsc2_resume(void)
{
SMSCConn *conn;
- int i;
-
+ long i;
+
+ gw_rwlock_rdlock(&smsc_list_lock);
for (i = 0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
smscconn_start(conn);
}
+ gw_rwlock_unlock(&smsc_list_lock);
if (router_thread >= 0)
gwthread_wakeup(router_thread);
}
@@ -587,33 +596,34 @@ void smsc2_resume(void)
void smsc2_suspend(void)
{
SMSCConn *conn;
- int i;
-
- list_lock(smsc_list);
+ long i;
+
+ gw_rwlock_rdlock(&smsc_list_lock);
for (i = 0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
smscconn_stop(conn);
}
- list_unlock(smsc_list);
+ gw_rwlock_unlock(&smsc_list_lock);
}
int smsc2_shutdown(void)
{
SMSCConn *conn;
- int i;
+ long i;
- if (!smsc_running) return -1;
+ if (!smsc_running)
+ return -1;
/* Call shutdown for all SMSC Connections; they should
* handle that they quit, by emptying queues and then dying off
*/
- list_lock(smsc_list);
+ gw_rwlock_rdlock(&smsc_list_lock);
for(i=0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
smscconn_shutdown(conn, 1);
}
- list_unlock(smsc_list);
+ gw_rwlock_unlock(&smsc_list_lock);
if (router_thread >= 0)
gwthread_wakeup(router_thread);
@@ -631,26 +641,26 @@ int smsc2_shutdown(void)
void smsc2_cleanup(void)
{
SMSCConn *conn;
- int i;
+ long i;
debug("smscconn", 0, "final clean-up for SMSCConn");
- /* do only cleanup if any smsc-ids have been defined */
- if (smsc_list != NULL) {
- list_lock(smsc_list);
- for (i = 0; i < list_len(smsc_list); i++) {
- conn = list_get(smsc_list, i);
- smscconn_destroy(conn);
- }
- list_unlock(smsc_list);
+ gw_rwlock_wrlock(&smsc_list_lock);
+ for (i = 0; i < list_len(smsc_list); i++) {
+ conn = list_get(smsc_list, i);
+ smscconn_destroy(conn);
}
list_destroy(smsc_list, NULL);
+ smsc_list = NULL;
+ gw_rwlock_unlock(&smsc_list_lock);
list_destroy(smsc_groups, NULL);
octstr_destroy(unified_prefix);
numhash_destroy(white_list);
numhash_destroy(black_list);
- if (white_list_regex != NULL) gw_regex_destroy(white_list_regex);
- if (black_list_regex != NULL) gw_regex_destroy(black_list_regex);
+ if (white_list_regex != NULL)
+ gw_regex_destroy(white_list_regex);
+ if (black_list_regex != NULL)
+ gw_regex_destroy(black_list_regex);
}
@@ -659,7 +669,8 @@ Octstr *smsc2_status(int status_type)
Octstr *tmp;
char tmp3[64];
char *lb;
- int i, para = 0;
+ long i;
+ int para = 0;
SMSCConn *conn;
StatusInfo info;
const Octstr *conn_id = NULL;
@@ -683,8 +694,8 @@ Octstr *smsc2_status(int status_type)
tmp = octstr_format("%sSMSC connections:%s", para ? "<p>" : "", lb);
else
tmp = octstr_format("<smscs><count>%d</count>\n\t", list_len(smsc_list));
-
- list_lock(smsc_list);
+
+ gw_rwlock_rdlock(&smsc_list_lock);
for (i = 0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
@@ -752,7 +763,7 @@ Octstr *smsc2_status(int status_type)
info.received, info.sent, info.failed,
info.queued, lb);
}
- list_unlock(smsc_list);
+ gw_rwlock_unlock(&smsc_list_lock);
if (para)
octstr_append_cstr(tmp, "</p>");
@@ -786,11 +797,6 @@ int smsc2_rout(Msg *msg)
if (msg_type(msg) != sms)
return -1;
- if (list_len(smsc_list) == 0) {
- warning(0, "No SMSCes to receive message");
- return -1;
- }
-
/* unify prefix of receiver, in case of it has not been
* already done */
@@ -800,8 +806,12 @@ int smsc2_rout(Msg *msg)
/* select in which list to add this
* start - from random SMSCConn, as they are all 'equal'
*/
-
- list_lock(smsc_list);
+ gw_rwlock_rdlock(&smsc_list_lock);
+ if (list_len(smsc_list) == 0) {
+ warning(0, "No SMSCes to receive message");
+ gw_rwlock_unlock(&smsc_list_lock);
+ return SMSCCONN_FAILED_DISCARDED;
+ }
s = gw_rand() % list_len(smsc_list);
best_preferred = best_ok = NULL;
@@ -837,7 +847,7 @@ int smsc2_rout(Msg *msg)
bo_load = info.load;
}
}
- list_unlock(smsc_list);
+ gw_rwlock_unlock(&smsc_list_lock);
if (best_preferred)
ret = smscconn_send(best_preferred, msg);