From 1f433a4495da25f8fed1fc66e364a6858643ec82 Mon Sep 17 00:00:00 2001 From: Eric Bollengier Date: Wed, 24 Nov 2010 21:44:23 +0100 Subject: [PATCH] Add function to limit the bandwidth of a BSOCK --- bacula/src/lib/bnet.c | 6 ++++++ bacula/src/lib/bsock.c | 43 ++++++++++++++++++++++++++++++++++++++++++ bacula/src/lib/bsock.h | 7 +++++++ 3 files changed, 56 insertions(+) diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 49fda5b144..851197a981 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -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; } diff --git a/bacula/src/lib/bsock.c b/bacula/src/lib/bsock.c index 94efd6bfe4..9a8d03cf5f 100644 --- a/bacula/src/lib/bsock.c +++ b/bacula/src/lib/bsock.c @@ -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; + } +} diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h index 9b9f40c440..4776d0daa2 100644 --- a/bacula/src/lib/bsock.h +++ b/bacula/src/lib/bsock.h @@ -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; }; -- 2.39.5