Hi list:

        I've seen kannel not respect throughput at all, at least with the 
fakesmsc
and looking around find the following bug:

http://redmine.kannel.org/issues/show/332

With the following patch attached:

http://redmine.kannel.org/attachments/104/0000332-emi_patch_ack_v3.txt

Inspired by that one, I've implemented a smsc-independent throughput patch. The
idea is to enforce the throughput from the beaberbox side instead of having to
implement the same login in every smsc. This is possible due to the
bb_smscconn_sent() and bb_smscconn_send_failed() callbacks from the smscs
implementation. They MUST call one of this callbacks after sending a message
either successfully(_sent) or with failure(_failed), so we can make them sleep
there, making sure they NEVER go over the configured throughput.

There's only one downside to this smsc-independent approach which is that we
don't, and can't (without cluttering the interface, AFAIK) know how much time
the smsc takes in actually sending the sms, so we assume it takes nothing, this
would, practically give us a somewhat smaller real throughput, but I though
that's better than the previous behaviour (which for me, flooded the smsc).

I've only tested this with fakesmsc so far, and only commented out the previous
throughput implementation in that smsc, doing the rest is trivial and I can do
it (or anyone else can), but this first iteration is to gather opinions about
this approach. 

Once again the patch is against the current stable release, I can update it if
needed, just let me know.

Again I would love comments, questions, commits, rants, whatever :)

For reference:
diffstat kannel-1.4.3-throughput.patch
 bb_smscconn.c    |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 smsc/smsc_fake.c |    9 +++++++--
 smscconn_p.h     |    2 ++
 3 files changed, 55 insertions(+), 2 deletions(-)

Hope to help.

    Damián Viano(Des).

P.D.: Also there's an info line in smsc_fake.c to count the number of sms,
which should be removed from the final version, is only there for debugging
purposes.
diff -Nura gateway-1.4.3.orig/gw/bb_smscconn.c gateway-1.4.3-des/gw/bb_smscconn.c
--- gateway-1.4.3.orig/gw/bb_smscconn.c	2009-06-03 14:58:43.000000000 -0300
+++ gateway-1.4.3-des/gw/bb_smscconn.c	2009-06-04 16:47:00.000000000 -0300
@@ -250,6 +250,13 @@
 
 void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
 {
+    struct timeval qos_slept;
+    double delay;
+
+    /* update last sent time independently of the reply to ensure QOS*/
+    /* FIXME: split msg should be acoounted for the number of splited msgs?*/
+    gettimeofday(&conn->last_mt_microtime, 0); 
+
     if (sms->sms.split_parts != NULL) {
         handle_split(conn, sms, SMSCCONN_SUCCESS);
         octstr_destroy(reply);
@@ -282,11 +289,34 @@
 
     msg_destroy(sms);
     octstr_destroy(reply);
+
+    if (conn->throughput > 0) { /* enforce QOS */
+        delay = 1.0 / conn->throughput;
+        debug("bb.smscconn", 0, "BB[%s]: QOS: Throughput detected, we need to sleep <%f>sec", octstr_get_cstr(conn->id?conn->id:conn->name), delay);
+
+        do { /* guaranteed sleep to ensure QOS even if we are awaken in during the sleep*/
+            gwthread_sleep(delay);
+            gettimeofday(&qos_slept, 0); 
+        } /* store in delay the amount of time we still need to sleep and if this is > 0 continue sleeping*/
+          while (0 < (delay = conn->last_mt_microtime.tv_sec                             
+                          + (double) conn->last_mt_microtime.tv_usec / 1000000           /* start of function */
+                          + 1.0 / conn->throughput                                       /* + total delay needed */
+                          - (qos_slept.tv_sec + (double) qos_slept.tv_usec / 1000000))); /* - actual time */
+
+        debug("bb.smscconn", 0, "BB[%s]: QOS: Sleep done", octstr_get_cstr(conn->id?conn->id:conn->name));
+    }
 }
 
 
 void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
 {
+    struct timeval qos_slept;
+    double delay;
+
+    /* update last sent time independently of the reply to ensure QOS*/
+    /* FIXME: split msg should be acoounted for the number of splited msgs?*/
+    gettimeofday(&conn->last_mt_microtime, 0); 
+
     if (sms->sms.split_parts != NULL) {
         handle_split(conn, sms, reason);
         octstr_destroy(reply);
@@ -352,6 +382,22 @@
     }
 
     octstr_destroy(reply);
+
+    if (conn->throughput > 0) { /* enforce QOS */
+        delay = 1.0 / conn->throughput;
+        debug("bb.smscconn", 0, "BB[%s]: QOS: Throughput detected, we need to sleep <%f>sec", octstr_get_cstr(conn->id?conn->id:conn->name), delay);
+
+        do { /* guaranteed sleep to ensure QOS even if we are awaken in during the sleep*/
+            gwthread_sleep(delay);
+            gettimeofday(&qos_slept, 0); 
+        } /* store in delay the amount of time we still need to sleep and if this is > 0 continue sleeping*/
+          while (0 < (delay = conn->last_mt_microtime.tv_sec                             
+                          + (double) conn->last_mt_microtime.tv_usec / 1000000           /* start of function */
+                          + 1.0 / conn->throughput                                       /* + total delay needed */
+                          - (qos_slept.tv_sec + (double) qos_slept.tv_usec / 1000000))); /* - actual time */
+
+        debug("bb.smscconn", 0, "BB[%s]: QOS: Sleep done", octstr_get_cstr(conn->id?conn->id:conn->name));
+    }
 }
 
 long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
diff -Nura gateway-1.4.3.orig/gw/smsc/smsc_fake.c gateway-1.4.3-des/gw/smsc/smsc_fake.c
--- gateway-1.4.3.orig/gw/smsc/smsc_fake.c	2009-06-03 14:58:43.000000000 -0300
+++ gateway-1.4.3-des/gw/smsc/smsc_fake.c	2009-06-04 16:21:00.000000000 -0300
@@ -242,6 +242,7 @@
     Octstr *line;
     Msg	*msg;
     double delay = 0;
+    unsigned long int msgid = 0;
 
     if (conn->throughput > 0) {
         delay = 1.0 / conn->throughput;
@@ -264,6 +265,8 @@
          */
 
         while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
+            info(0, "smsc <%s> sent msg id:<%d>", octstr_get_cstr(conn->name), msgid);
+            msgid++;
 
             /* pass msg to fakesmsc daemon */            
             if (sms_to_client(client, msg) == 1) {
@@ -309,9 +312,11 @@
             }
 
             /* obey throughput speed limit, if any */
-            if (conn->throughput > 0) {
+            /*if (conn->throughput > 0) { XXX:handled by bb_smscconn_{sent,send_failed}
+                info(0, "Sleeping <%.3f> sec using gwthread_sleep() for smsc <%s> before sending msg id:<%d>", delay, octstr_get_cstr(conn->name), msgid);
                 gwthread_sleep(delay);
-            }
+                info(0, "Slept    <%.3f> sec using gwthread_sleep() for smsc <%s> before sending msg id:<%d>", delay, octstr_get_cstr(conn->name), msgid);
+            } */
         }
         if (privdata->shutdown) {
             debug("bb.sms", 0, "smsc_fake shutting down, closing client socket");
diff -Nura gateway-1.4.3.orig/gw/smscconn_p.h gateway-1.4.3-des/gw/smscconn_p.h
--- gateway-1.4.3.orig/gw/smscconn_p.h	2009-06-03 14:58:43.000000000 -0300
+++ gateway-1.4.3-des/gw/smscconn_p.h	2009-06-04 15:35:02.000000000 -0300
@@ -153,6 +153,8 @@
 				* shutdown called */
     time_t 	connect_time;	/* When connection to SMSC was established */
 
+    struct timeval last_mt_microtime;  /* the last microtime a MT was sent over the SMSC */
+
     Mutex 	*flow_mutex;	/* used to lock SMSCConn structure (both
 				 *  in smscconn.c and specific driver) */
 

Reply via email to