]> git.sur5r.net Git - bacula/bacula/commitdiff
Add function to limit the bandwidth of a BSOCK
authorEric Bollengier <eric@eb.homelinux.org>
Wed, 24 Nov 2010 20:44:23 +0000 (21:44 +0100)
committerEric Bollengier <eric@eb.homelinux.org>
Thu, 25 Nov 2010 14:21:20 +0000 (15:21 +0100)
bacula/src/lib/bnet.c
bacula/src/lib/bsock.c
bacula/src/lib/bsock.h

index 49fda5b144cbbd54312d950cd4998be342103351..851197a981138eb4c2e31bdd45778c0ae685c364 100644 (file)
@@ -95,6 +95,9 @@ int32_t read_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
       }
       nleft -= nread;
       ptr += nread;
+      if (bsock->use_bwlimit()) {
+         bsock->control_bwlimit(nread);
+      }
    }
    return nbytes - nleft;          /* return >= 0 */
 }
@@ -159,6 +162,9 @@ int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
       }
       nleft -= nwritten;
       ptr += nwritten;
+      if (bsock->use_bwlimit()) {
+         bsock->control_bwlimit(nwritten);
+      }
    }
    return nbytes - nleft;
 }
index 94efd6bfe407d5cbe88a4b789fc93343b78840f9..9a8d03cf5f1013f4563842b17e53513125d8a454 100644 (file)
@@ -1056,3 +1056,46 @@ bail_out:
              dir->host(), dir->port());
    return false;
 }
+
+/* Try to limit the bandwidth of a network connection
+ */
+void BSOCK::control_bwlimit(int bytes)
+{
+   btime_t now, temp;
+   if (bytes == 0) {
+      return;
+   }
+
+   now = get_current_btime();          /* microseconds */
+   temp = now - m_last_tick;           /* microseconds */
+
+   m_nb_bytes += bytes;
+
+   /* Less than 0.1ms since the last call, see the next time */
+   if (temp < 100) {
+      return;
+   }
+
+   if (temp > 10000000) { /* Take care of clock problems (>10s) */
+      m_nb_bytes = bytes;
+      m_last_tick = now;
+      return;
+   }
+
+   /* Remove what was authorised to be written in temp us */
+   m_nb_bytes -= temp * ((double)m_bwlimit / 1000000.0);
+
+   if (m_nb_bytes < 0) {
+      m_nb_bytes = 0;
+   }
+
+   /* What exceed should be converted in sleep time */
+   int64_t usec_sleep = m_nb_bytes / ((double)m_bwlimit / 1000000.0);
+   if (usec_sleep > 100) {
+      bmicrosleep(0, usec_sleep);
+      m_last_tick = get_current_btime();
+      m_nb_bytes = 0;
+   } else {
+      m_last_tick = now;
+   }
+}
index 9b9f40c4403fc5329ec4a18328ffe20331bbe23c..4776d0daa2c8f7b7c8d3bf04a17b3972e5be9a26 100644 (file)
@@ -92,6 +92,10 @@ private:
    bool m_spool: 1;                   /* set for spooling */
    bool m_use_locking: 1;             /* set to use locking */
 
+   int64_t m_bwlimit;                 /* set to limit bandwidth */
+   int64_t m_nb_bytes;                /* bytes sent/recv since the last tick */
+   btime_t m_last_tick;               /* last tick used by bwlimit */
+
    void fin_init(JCR * jcr, int sockfd, const char *who, const char *host, int port,
                struct sockaddr *lclient_addr);
    bool open(JCR *jcr, const char *name, char *host, char *service,
@@ -125,6 +129,7 @@ public:
    bool set_locking();                /* in bsock.c */
    void clear_locking();              /* in bsock.c */
    void set_source_address(dlist *src_addr_list);
+   void control_bwlimit(int bytes);   /* in bsock.c */
 
    /* Inline functions */
    void set_jcr(JCR *jcr) { m_jcr = jcr; };
@@ -143,6 +148,8 @@ public:
    bool is_stop() { return errors || is_terminated(); }
    bool is_error() { errno = b_errno; return errors; }
    void set_data_end() { if (m_spool) m_data_end = ftello(m_spool_fd); };
+   void set_bwlimit(int64_t maxspeed) { m_bwlimit = maxspeed; };
+   bool use_bwlimit() { return m_bwlimit > 0;};
    void set_spooling() { m_spool = true; };
    void clear_spooling() { m_spool = false; };
    void set_duped() { m_duped = true; };