Dear all,

SMPP module has hardcoded 1 second sleep time when receiving a throttling error from SMSC. This setting is adequate for low latency networks but considerably limits performance when SMPP connection is using a high latency network for example 100ms. In this case the sleep time should be set at msec and not 1 sec. The attached patch maintains the default 1 sec. sleep time and is introducing a new configuration directive "throttling-sleep-time" which allows the user to define sleep time in msec.

BR,

Michael Zervakis
Index: gw/smsc/smsc_smpp.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_smpp.c,v
retrieving revision 1.123
diff -u -r1.123 smsc_smpp.c
--- gw/smsc/smsc_smpp.c 2 Sep 2009 13:10:50 -0000       1.123
+++ gw/smsc/smsc_smpp.c 14 Mar 2010 18:13:21 -0000
@@ -80,6 +80,8 @@
 #include "bearerbox.h"
 #include "meta_data.h"
 #include "load.h"
+#include <sys/time.h>
+#include <limits.h>
 
 #define SMPP_DEFAULT_CHARSET "UTF-8"
 
@@ -112,7 +114,7 @@
 #define SMPP_MAX_PENDING_SUBMITS    10
 #define SMPP_DEFAULT_VERSION        0x34
 #define SMPP_DEFAULT_PRIORITY       0
-#define SMPP_THROTTLING_SLEEP_TIME  1
+#define SMPP_THROTTLING_SLEEP_TIME  1000
 #define SMPP_DEFAULT_CONNECTION_TIMEOUT  10 * SMPP_ENQUIRE_LINK_INTERVAL
 #define SMPP_DEFAULT_WAITACK        60
 #define SMPP_DEFAULT_SHUTDOWN_TIMEOUT 30
@@ -160,7 +162,8 @@
     int version;
     int priority;       /* set default priority for messages */
     int validityperiod;
-    time_t throttling_err_time;
+    long throttling_sleep_time;
+    struct timeval throttling_err_time;
     int smpp_msg_id_type;  /* msg id in C string, hex or decimal */
     int autodetect_addr;
     Octstr *alt_charset;
@@ -221,7 +224,7 @@
                          Octstr *my_number, int smpp_msg_id_type,
                          int autodetect_addr, Octstr *alt_charset, Octstr 
*alt_addr_charset,
                          Octstr *service_type, long connection_timeout,
-                         long wait_ack, int wait_ack_action)
+                         long wait_ack, int wait_ack_action, int 
throttling_sleep_time)
 {
     SMPP *smpp;
 
@@ -254,7 +257,9 @@
     smpp->priority = priority;
     smpp->validityperiod = validity;
     smpp->conn = conn;
-    smpp->throttling_err_time = 0;
+    smpp->throttling_sleep_time = throttling_sleep_time * 1000;
+    smpp->throttling_err_time.tv_sec = 0;
+    smpp->throttling_err_time.tv_usec = 0;
     smpp->smpp_msg_id_type = smpp_msg_id_type;
     smpp->autodetect_addr = autodetect_addr;
     smpp->alt_charset = octstr_duplicate(alt_charset);
@@ -1606,10 +1611,12 @@
                  * check to see if we got a "throttling error", in which case 
we'll just
                  * sleep for a while
                  */
-                if (pdu->u.submit_sm_resp.command_status == 
SMPP_ESME_RTHROTTLED)
-                    time(&(smpp->throttling_err_time));
-                else
-                    smpp->throttling_err_time = 0;
+                if (pdu->u.submit_sm_resp.command_status == 
SMPP_ESME_RTHROTTLED) {
+                    gettimeofday(&(smpp->throttling_err_time), NULL);
+                } else {
+                    smpp->throttling_err_time.tv_sec = 0;
+                    smpp->throttling_err_time.tv_usec = 0;
+                }
 
                 bb_smscconn_send_failed(smpp->conn, msg, reason, 
octstr_format("0x%08lx/%s", pdu->u.submit_sm_resp.command_status,
                                         
smpp_error_to_string(pdu->u.submit_sm_resp.command_status)));
@@ -1755,10 +1762,12 @@
                  * check to see if we got a "throttling error", in which case 
we'll just
                  * sleep for a while
                  */
-                if (cmd_stat == SMPP_ESME_RTHROTTLED)
-                    time(&(smpp->throttling_err_time));
-                else
-                    smpp->throttling_err_time = 0;
+                if (cmd_stat == SMPP_ESME_RTHROTTLED) {
+                    gettimeofday(&(smpp->throttling_err_time), NULL);
+                } else {
+                    smpp->throttling_err_time.tv_sec = 0;
+                    smpp->throttling_err_time.tv_usec = 0;
+                }
 
                 reason = smpp_status_to_smscconn_failure_reason(cmd_stat);
                 bb_smscconn_send_failed(smpp->conn, msg, reason,
@@ -1884,6 +1893,7 @@
     SMPP_PDU *pdu;
     double timeout;
     time_t last_cleanup, last_enquire_sent, last_response, now;
+    struct timeval eval_time;
 
     io_arg = arg;
     smpp = io_arg->smpp;
@@ -1971,8 +1981,8 @@
                 if (!IS_ACTIVE && timeout <= 0)
                     timeout = smpp->enquire_link_interval;
                 if (transmitter && gw_prioqueue_len(smpp->msgs_to_send) > 0 &&
-                    smpp->throttling_err_time > 0 && pending_submits < 
smpp->max_pending_submits) {
-                    time_t tr_timeout = smpp->throttling_err_time + 
SMPP_THROTTLING_SLEEP_TIME - now;
+                    smpp->throttling_err_time.tv_sec > 0 && pending_submits < 
smpp->max_pending_submits) {
+                    time_t tr_timeout = smpp->throttling_err_time.tv_sec + 
(int) (smpp->throttling_sleep_time / 1000000 + 0.5) - now;
                     timeout = timeout > tr_timeout ? tr_timeout : timeout;
                 } else if (transmitter && gw_prioqueue_len(smpp->msgs_to_send) 
> 0 && smpp->conn->throughput > 0 &&
                            smpp->max_pending_submits > pending_submits) {
@@ -1996,10 +2006,24 @@
             }
             
             /* make sure we send */
-            if (transmitter && difftime(time(NULL), smpp->throttling_err_time) 
> SMPP_THROTTLING_SLEEP_TIME) {
-                smpp->throttling_err_time = 0;
-                if (send_messages(smpp, conn, &pending_submits) == -1)
-                    break;
+            if (transmitter) {
+                if (smpp->throttling_err_time.tv_sec == 0) {
+                    if (send_messages(smpp, conn, &pending_submits) == -1)
+                        break;
+                } else {
+                    gettimeofday(&eval_time, NULL);
+                    if (eval_time.tv_sec >= smpp->throttling_err_time.tv_sec 
&& eval_time.tv_sec - smpp->throttling_err_time.tv_sec < (unsigned 
long)(ULONG_MAX / 1000000 - 0.5)) {
+                        if ((eval_time.tv_sec - 
smpp->throttling_err_time.tv_sec) * 1000000 + eval_time.tv_usec - 
smpp->throttling_err_time.tv_usec > smpp->throttling_sleep_time) {
+                             smpp->throttling_err_time.tv_sec = 0;
+                             smpp->throttling_err_time.tv_usec = 0;
+                             if (send_messages(smpp, conn, &pending_submits) 
== -1)
+                                 break;
+                        }
+                    } else {
+                        if (send_messages(smpp, conn, &pending_submits) == -1)
+                            break;
+                    }
+                }
             }
             
             /* unbind
@@ -2190,6 +2214,7 @@
     Octstr *alt_charset;
     Octstr *alt_addr_charset;
     long connection_timeout, wait_ack, wait_ack_action;
+    long throttling_sleep_time;
 
     my_number = alt_addr_charset = alt_charset = NULL;
     transceiver_mode = 0;
@@ -2229,6 +2254,9 @@
     if (cfg_get_integer(&max_pending_submits, grp,
                         octstr_imm("max-pending-submits")) == -1)
         max_pending_submits = SMPP_MAX_PENDING_SUBMITS;
+    if (cfg_get_integer(&throttling_sleep_time, grp,
+                        octstr_imm("throttling-sleep-time")) == -1)
+        throttling_sleep_time = SMPP_THROTTLING_SLEEP_TIME;
 
     /* Check that config is OK */
     ok = 1;
@@ -2328,7 +2356,7 @@
                        dest_addr_npi, enquire_link_interval,
                        max_pending_submits, version, priority, validity, 
my_number,
                        smpp_msg_id_type, autodetect_addr, alt_charset, 
alt_addr_charset,
-                       service_type, connection_timeout, wait_ack, 
wait_ack_action);
+                       service_type, connection_timeout, wait_ack, 
wait_ack_action, throttling_sleep_time);
 
     cfg_get_integer(&smpp->bind_addr_ton, grp, octstr_imm("bind-addr-ton"));
     cfg_get_integer(&smpp->bind_addr_npi, grp, octstr_imm("bind-addr-npi"));
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.142
diff -u -r1.142 cfg.def
--- gwlib/cfg.def       6 Dec 2009 17:24:14 -0000       1.142
+++ gwlib/cfg.def       14 Mar 2010 18:13:21 -0000
@@ -366,6 +366,7 @@
     OCTSTR(source-addr-autodetect)
     OCTSTR(enquire-link-interval)
     OCTSTR(max-pending-submits)
+    OCTSTR(throttling-sleep-time)
     OCTSTR(reconnect-delay)
     OCTSTR(transceiver-mode)
     OCTSTR(interface-version)

Reply via email to