Hi,

too much time passed since this post, but thanks to Stipe who pointed me to this post.

Attached is a patch that implements simple bandwidth meter with heuristic and needed changes to bearerbox status.

Bearerbox status show now 3 speeds: 1 minute sample, 5 minute sample, and over livetime.

Example:
SMS: inbound (0.00,0.00,0.00) msg/sec, outbound (0.00,0.00,0.00) msg/sec

Comments please...

Thanks,
Alex

Alexander Malysh schrieb:
Hi,

I already implemented this in my tree, just give me some time to extract
this...

Rafael Alfaro wrote:

Hello Alex,

First of all, thanks  for your time,
Could you explain me a little bit about: "Simple bandwidth meter should do
it"? How is the best way to implement this?

Thanks in advance.

Rafael Alfaro.

On Tue, Mar 25, 2008 at 4:06 AM, Alexander Malysh <[EMAIL PROTECTED]>
wrote:
Hi Rafael,

 -1 for this patch. You don't need yet another thread to do this. Simple
 bandwidth meter should do it...


 Rafael Alfaro wrote:

 > Hello Everybody,
 >
 > I did this patch with the following purpose:
 > Provide the bearerbox status web page with an online incoming and
 > outgoing sms rate display (msg/sec).
 >
 > For example, if you take a look to the current bearerbox status web
 > page, you will see that the sms rate is the average since the
 > bearerbox is online, because the current code is:
 >
 >         (float) counter_value(incoming_sms_counter)/t,
 >         (float) counter_value(outgoing_sms_counter)/t,
 >
 > So, I added a new feature to the core group cfg: "sms-rate-refresh".
 > This will launch a thread that will be sampling the
 > "counter_value(incoming_sms_counter)" and
 > "counter_value(outgoing_sms_counter)" every "sms_rate_refresh"
 > seconds, and with this information we can calculate the current sms
 > rate (msg/sec).
 >
 > If the "sms-rate-refresh" feature is not used at the configuration
 > file, by default, the average since bearerbox is online will be
 > displayed (like right now is coded).
 >
 > Best Regards,

 --
 Thanks,
 Alex





Index: gw/load.c
===================================================================
RCS file: gw/load.c
diff -N gw/load.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gw/load.c   12 Sep 2008 12:32:28 -0000
@@ -0,0 +1,215 @@
+/* ==================================================================== 
+ * The Kannel Software License, Version 1.0 
+ * 
+ * Copyright (c) 2001-2008 Kannel Group  
+ * Copyright (c) 1998-2001 WapIT Ltd.   
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in 
+ *    the documentation and/or other materials provided with the 
+ *    distribution. 
+ * 
+ * 3. The end-user documentation included with the redistribution, 
+ *    if any, must include the following acknowledgment: 
+ *       "This product includes software developed by the 
+ *        Kannel Group (http://www.kannel.org/)." 
+ *    Alternately, this acknowledgment may appear in the software itself, 
+ *    if and wherever such third-party acknowledgments normally appear. 
+ * 
+ * 4. The names "Kannel" and "Kannel Group" must not be used to 
+ *    endorse or promote products derived from this software without 
+ *    prior written permission. For written permission, please  
+ *    contact [EMAIL PROTECTED] 
+ * 
+ * 5. Products derived from this software may not be called "Kannel", 
+ *    nor may "Kannel" appear in their name, without prior written 
+ *    permission of the Kannel Group. 
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * ==================================================================== 
+ * 
+ * This software consists of voluntary contributions made by many 
+ * individuals on behalf of the Kannel Group.  For more information on  
+ * the Kannel Group, please see <http://www.kannel.org/>. 
+ * 
+ * Portions of this software are based upon software originally written at  
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.  
+ */ 
+
+/**
+ * load.c
+ *
+ * Alexander Malysh <amalysh at kannel.org> 2008 for project Kannel
+ */
+
+#include "gwlib/gwlib.h"
+#include "load.h"
+
+
+struct load_entry {
+    float prev;
+    float curr;
+    time_t last;
+    int interval;
+    int dirty;
+};
+
+
+struct load {
+    struct load_entry **entries;
+    int len;
+    int heuristic;
+    RWLock *lock;
+};
+
+
+Load* load_create_real(int heuristic)
+{
+    struct load *load;
+    
+    load = gw_malloc(sizeof(*load));
+    load->len = 0;
+    load->entries = NULL;
+    load->heuristic = heuristic;
+    load->lock = gw_rwlock_create();
+    
+    return load;
+}
+
+
+int load_add_interval(Load *load, int interval)
+{
+    int i;
+    struct load_entry *entry;
+    
+    if (load == NULL)
+        return -1;
+    
+    gw_rwlock_wrlock(load->lock);
+    
+    /* first look if we have equal interval added already */
+    for (i = 0; i < load->len; i++) {
+        if (load->entries[i]->interval == interval) {
+            gw_rwlock_unlock(load->lock);
+            return -1;
+        }
+    }
+    /* so no equal interval there, add new one */
+    entry = gw_malloc(sizeof(struct load_entry));
+    entry->prev = entry->curr = 0.0;
+    entry->interval = interval;
+    entry->dirty = 1;
+    time(&entry->last);
+    
+    load->entries = gw_realloc(load->entries, sizeof(struct load*) * 
(load->len + 1));
+    load->entries[load->len] = entry;
+    load->len++;
+    
+    gw_rwlock_unlock(load->lock);
+    
+    return 0;
+}
+
+    
+void load_destroy(Load *load)
+{
+    int i;
+
+    if (load == NULL)
+        return;
+
+    for (i = 0; i < load->len; i++) {
+        gw_free(load->entries[i]);
+    }
+    gw_free(load->entries);
+    gw_rwlock_destroy(load->lock);
+    gw_free(load);
+}
+
+
+void load_increase_with(Load *load, unsigned long value)
+{
+    time_t now;
+    int i;
+    
+    if (load == NULL)
+        return;
+    gw_rwlock_wrlock(load->lock);
+    time(&now);
+    for (i = 0; i < load->len; i++) {
+        struct load_entry *entry = load->entries[i];
+        /* check for special case, load over whole live time */
+        if (entry->interval != -1 && now >= entry->last + entry->interval) {
+            /* rotate */
+            entry->curr /= entry->interval;
+            if (entry->prev > 0)
+                entry->prev = (2*entry->curr + entry->prev)/3;
+            else
+                entry->prev = entry->curr;
+            entry->last = now;
+            entry->curr = 0.0;
+            entry->dirty = 0;
+        }
+        entry->curr += value;
+    }
+    gw_rwlock_unlock(load->lock);
+}
+
+
+float load_get(Load *load, int pos)
+{
+    float ret;
+    time_t now;
+    struct load_entry *entry;
+
+    if (load == NULL || pos >= load->len) {
+        return -1.0;
+    }
+
+    /* first maybe rotate load */
+    load_increase_with(load, 0);
+    
+    time(&now);
+    gw_rwlock_rdlock(load->lock);
+    entry = load->entries[pos];
+    if (load->heuristic && !entry->dirty) {
+        ret = entry->prev;
+    } else {
+        time_t diff = (now - entry->last);
+        if (diff == 0) diff = 1;
+        ret = entry->curr/diff;
+    }
+    gw_rwlock_unlock(load->lock);
+
+    return ret;
+}
+
+
+int load_len(Load *load)
+{
+    int ret;
+    if (load == NULL)
+        return 0;
+    gw_rwlock_rdlock(load->lock);
+    ret = load->len;
+    gw_rwlock_unlock(load->lock);
+    return ret;
+}
Index: gw/load.h
===================================================================
RCS file: gw/load.h
diff -N gw/load.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gw/load.h   12 Sep 2008 12:32:28 -0000
@@ -0,0 +1,112 @@
+/* ==================================================================== 
+ * The Kannel Software License, Version 1.0 
+ * 
+ * Copyright (c) 2001-2008 Kannel Group  
+ * Copyright (c) 1998-2001 WapIT Ltd.   
+ * All rights reserved. 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in 
+ *    the documentation and/or other materials provided with the 
+ *    distribution. 
+ * 
+ * 3. The end-user documentation included with the redistribution, 
+ *    if any, must include the following acknowledgment: 
+ *       "This product includes software developed by the 
+ *        Kannel Group (http://www.kannel.org/)." 
+ *    Alternately, this acknowledgment may appear in the software itself, 
+ *    if and wherever such third-party acknowledgments normally appear. 
+ * 
+ * 4. The names "Kannel" and "Kannel Group" must not be used to 
+ *    endorse or promote products derived from this software without 
+ *    prior written permission. For written permission, please  
+ *    contact [EMAIL PROTECTED] 
+ * 
+ * 5. Products derived from this software may not be called "Kannel", 
+ *    nor may "Kannel" appear in their name, without prior written 
+ *    permission of the Kannel Group. 
+ * 
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * ==================================================================== 
+ * 
+ * This software consists of voluntary contributions made by many 
+ * individuals on behalf of the Kannel Group.  For more information on  
+ * the Kannel Group, please see <http://www.kannel.org/>. 
+ * 
+ * Portions of this software are based upon software originally written at  
+ * WapIT Ltd., Helsinki, Finland for the Kannel project.  
+ */ 
+
+/**
+ * load.h
+ *
+ * Alexander Malysh <amalysh at kannel.org> 2008 for project Kannel
+ */
+
+#ifndef LOAD_H
+#define LOAD_H 1
+
+#include <time.h>
+ 
+/**
+ * Anonymos Load typedef.
+ */
+typedef struct load Load;
+
+/**
+ * Create new Load object.
+ * @heuristic - 0 disable heuristic (means get always current load); 1 enable
+ */
+Load* load_create_real(int heuristic);
+#define load_create() load_create_real(1)
+
+/**
+ * Add load measure interval.
+ * @load - load object
+ * @interval - measure interval in seconds
+ * @return -1 if error occurs (e.g. interval already exists); 0 if all was fine
+ */
+int load_add_interval(Load *load, int interval);
+
+/**
+ * Increase load values with @value.
+ * @load - load object
+ * @valu - how much to increase
+ */
+void load_increase_with(Load *load, unsigned long value);
+#define load_increase(load) load_increase_with(load, 1)
+
+/**
+ * Destroy load object.
+ * @load - load object
+ */
+void load_destroy(Load *load);
+
+/**
+ * Get measured load value at position @pos.
+ */
+float load_get(Load *load, int pos);
+
+/**
+ * Get length of intervals.
+ */
+int load_len(Load *load);
+
+#endif
Index: gw/bb_smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn.c,v
retrieving revision 1.96
diff -a -u -p -r1.96 bb_smscconn.c
--- gw/bb_smscconn.c    9 Jan 2008 20:06:56 -0000       1.96
+++ gw/bb_smscconn.c    12 Sep 2008 12:32:28 -0000
@@ -87,6 +87,7 @@
 #include "numhash.h"
 #include "smscconn.h"
 #include "dlr.h"
+#include "load.h"
 
 #include "bb_smscconn_cb.h"    /* callback functions for connections */
 #include "smscconn_p.h"        /* to access counters */
@@ -100,6 +101,9 @@ extern List *outgoing_sms;
 extern Counter *incoming_sms_counter;
 extern Counter *outgoing_sms_counter;
 
+extern Load *outgoing_sms_load;
+extern Load *incoming_sms_load;
+
 extern List *flow_threads;
 extern List *suspended;
 extern List *isolated;
@@ -251,6 +255,7 @@ void bb_smscconn_sent(SMSCConn *conn, Ms
     }
     
     counter_increase(outgoing_sms_counter);
+    load_increase(outgoing_sms_load);
     if (conn) counter_increase(conn->sent);
 
     /* write ACK to store file */
@@ -424,6 +429,7 @@ long bb_smscconn_receive(SMSCConn *conn,
             switch(ret) {
             case concat_pending:
                 counter_increase(incoming_sms_counter); /* ?? */
+                load_increase(incoming_sms_load);
                 if (conn != NULL)
                     counter_increase(conn->received);
                 msg_destroy(sms);
@@ -476,6 +482,7 @@ long bb_smscconn_receive(SMSCConn *conn,
        bb_alog_sms(conn, sms, "Receive DLR");
 
     counter_increase(incoming_sms_counter);
+    load_increase(incoming_sms_load);
     if (conn != NULL) counter_increase(conn->received);
 
     msg_destroy(sms);
Index: gw/bearerbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/bearerbox.c,v
retrieving revision 1.167
diff -a -u -p -r1.167 bearerbox.c
--- gw/bearerbox.c      24 Apr 2008 14:44:59 -0000      1.167
+++ gw/bearerbox.c      12 Sep 2008 12:32:28 -0000
@@ -77,6 +77,7 @@
 #include "bearerbox.h"
 #include "shared.h"
 #include "dlr.h"
+#include "load.h"
 
 /* global variables; included to other modules as needed */
 
@@ -96,6 +97,10 @@ long max_incoming_sms_qlength;
 long max_outgoing_sms_qlength;
 
 
+Load *outgoing_sms_load;
+Load *incoming_sms_load;
+
+
 /* this is not a list of items; instead it is used as
  * indicator to note how many threads we have.
  * ALL flow threads must exit before we may safely change
@@ -454,6 +459,17 @@ static Cfg *init_bearerbox(Cfg *cfg)
 
     status_mutex = mutex_create();
 
+    outgoing_sms_load = load_create();
+    /* add 60,300,-1 entries */
+    load_add_interval(outgoing_sms_load, 60);
+    load_add_interval(outgoing_sms_load, 300);
+    load_add_interval(outgoing_sms_load, -1);
+    incoming_sms_load = load_create();
+    /* add 60,300,-1 entries */
+    load_add_interval(incoming_sms_load, 60);
+    load_add_interval(incoming_sms_load, 300);
+    load_add_interval(incoming_sms_load, -1);
+
     setup_signal_handlers();
     
     /* http-admin is REQUIRED */
@@ -544,6 +560,9 @@ static void empty_msg_lists(void)
     
     counter_destroy(incoming_sms_counter);
     counter_destroy(outgoing_sms_counter);
+
+    load_destroy(incoming_sms_load);
+    load_destroy(outgoing_sms_load);
 }
 
 
@@ -816,7 +835,6 @@ Octstr *bb_print_status(int status_type)
 {
     char *s, *lb;
     char *frmt, *footer;
-    char buf[1024];
     Octstr *ret, *str, *version;
     time_t t;
 
@@ -845,7 +863,7 @@ Octstr *bb_print_status(int status_type)
                "(%ld queued)</p>\n\n"
                " <p>SMS: received %ld (%ld queued), sent %ld "
                "(%ld queued), store size %ld</p>\n"
-               " <p>SMS: inbound %.2f msg/sec, outbound %.2f msg/sec</p>\n\n"
+               " <p>SMS: inbound (%.2f,%.2f,%.2f) msg/sec, outbound 
(%.2f,%.2f,%.2f) msg/sec</p>\n\n"
                " <p>DLR: %ld queued, using %s storage</p>\n\n";
         footer = "<p>";
     } else if (status_type == BBSTATUS_WML) {
@@ -856,8 +874,8 @@ Octstr *bb_print_status(int status_type)
                "   <p>SMS: received %ld (%ld queued)<br/>\n"
                "      SMS: sent %ld (%ld queued)<br/>\n"
                "      SMS: store size %ld<br/>\n"
-               "      SMS: inbound %.2f msg/sec<br/>\n"
-               "      SMS: outbound %.2f msg/sec</p>\n\n"
+               "      SMS: inbound (%.2f,%.2f,%.2f) msg/sec<br/>\n"
+               "      SMS: outbound (%.2f,%.2f,%.2f) msg/sec</p>\n\n"
                "   <p>DLR: %ld queued<br/>\n"
                "      DLR: using %s storage</p>\n\n";
         footer = "<p>";
@@ -870,19 +888,19 @@ Octstr *bb_print_status(int status_type)
                "\t<sms>\n\t\t<received><total>%ld</total><queued>%ld</queued>"
                "</received>\n\t\t<sent><total>%ld</total><queued>%ld</queued>"
                "</sent>\n\t\t<storesize>%ld</storesize>\n\t\t"
-               
"<inbound>%.2f</inbound>\n\t\t<outbound>%.2f</outbound>\n\t</sms>\n"
+               
"<inbound>%.2f,%.2f,%.2f</inbound>\n\t\t<outbound>%.2f,%.2f,%.2f</outbound>\n\t</sms>\n"
                
"\t<dlr>\n\t\t<queued>%ld</queued>\n\t\t<storage>%s</storage>\n\t</dlr>\n";
         footer = "";
     } else {
         frmt = "%s\n\nStatus: %s, uptime %ldd %ldh %ldm %lds\n\n"
                "WDP: received %ld (%ld queued), sent %ld (%ld queued)\n\n"
                "SMS: received %ld (%ld queued), sent %ld (%ld queued), store 
size %ld\n"
-               "SMS: inbound %.2f msg/sec, outbound %.2f msg/sec\n\n"
+               "SMS: inbound (%.2f,%.2f,%.2f) msg/sec, outbound 
(%.2f,%.2f,%.2f) msg/sec\n\n"
                "DLR: %ld queued, using %s storage\n\n";
         footer = "";
     }
     
-    sprintf(buf, frmt,
+    ret = octstr_format(frmt,
         octstr_get_cstr(version),
         s, t/3600/24, t/3600%24, t/60%60, t%60,
         counter_value(incoming_wdp_counter),
@@ -891,12 +909,11 @@ Octstr *bb_print_status(int status_type)
         counter_value(incoming_sms_counter), gwlist_len(incoming_sms),
         counter_value(outgoing_sms_counter), gwlist_len(outgoing_sms),
         store_messages(),
-        (float) counter_value(incoming_sms_counter)/t,
-        (float) counter_value(outgoing_sms_counter)/t,
+        load_get(incoming_sms_load,0), load_get(incoming_sms_load,1), 
load_get(incoming_sms_load,2),
+        load_get(outgoing_sms_load,0), load_get(outgoing_sms_load,1), 
load_get(outgoing_sms_load,2),
         dlr_messages(), dlr_type());
 
     octstr_destroy(version);
-    ret = octstr_create(buf);
     
     append_status(ret, str, boxc_status, status_type);
     append_status(ret, str, smsc2_status, status_type);

Reply via email to