* The peer rates are now only updated when data transfer is enabled in the corresponding direction. They are also computed differently from before. The rates are computed in the bw callback once a second. This facilitates later improvements in the choke algorithm.master
@@ -118,7 +118,6 @@ static int longval = 0; | |||
static struct option longopts[] = { | |||
{ "port", required_argument, NULL, 'p' }, | |||
{ "bw-hz", required_argument, &longval, 6 }, | |||
{ "bw-in", required_argument, &longval, 1 }, | |||
{ "bw-out", required_argument, &longval, 2 }, | |||
{ "help", no_argument, &longval, 5 }, | |||
@@ -150,9 +149,6 @@ main(int argc, char **argv) | |||
case 2: | |||
net_bw_limit_out = atoi(optarg) * 1024; | |||
break; | |||
case 6: | |||
net_bw_hz = atoi(optarg); | |||
break; | |||
default: | |||
usage(); | |||
} | |||
@@ -101,7 +101,7 @@ net_write(struct peer *p, unsigned long wmax) | |||
peer_sent(p, nl->nb); | |||
if (nl->nb->type == NB_TORRENTDATA) { | |||
p->tp->uploaded += bufdelta; | |||
p->rate_from_me[btpd_seconds % RATEHISTORY] += bufdelta; | |||
p->count_up += bufdelta; | |||
} | |||
bcount -= bufdelta; | |||
BTPDQ_REMOVE(&p->outq, nl, entry); | |||
@@ -112,7 +112,7 @@ net_write(struct peer *p, unsigned long wmax) | |||
} else { | |||
if (nl->nb->type == NB_TORRENTDATA) { | |||
p->tp->uploaded += bcount; | |||
p->rate_from_me[btpd_seconds % RATEHISTORY] += bcount; | |||
p->count_up += bcount; | |||
} | |||
p->outq_off += bcount; | |||
bcount = 0; | |||
@@ -221,7 +221,7 @@ net_progress(struct peer *p, size_t length) | |||
{ | |||
if (p->net.state == BTP_MSGBODY && p->net.msg_num == MSG_PIECE) { | |||
p->tp->downloaded += length; | |||
p->rate_to_me[btpd_seconds % RATEHISTORY] += length; | |||
p->count_dwn += length; | |||
} | |||
} | |||
@@ -435,14 +435,37 @@ net_connection_cb(int sd, short type, void *arg) | |||
btpd_log(BTPD_L_CONN, "got connection.\n"); | |||
} | |||
void | |||
add_bw_timer(void) | |||
#define RATEHISTORY 20 | |||
long | |||
compute_rate_sub(long rate) | |||
{ | |||
long wait = 1000000 / net_bw_hz; | |||
struct timeval now; | |||
gettimeofday(&now, NULL); | |||
wait = wait - now.tv_usec % wait; | |||
evtimer_add(&m_bw_timer, (& (struct timeval) { 0, wait})); | |||
if (rate > 256 * RATEHISTORY) | |||
return rate / RATEHISTORY; | |||
else | |||
return 256; | |||
} | |||
static void | |||
compute_peer_rates(void) { | |||
struct torrent *tp; | |||
BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) { | |||
struct peer *p; | |||
BTPDQ_FOREACH(p, &tp->peers, p_entry) { | |||
if (p->count_up > 0 || peer_active_up(p)) { | |||
p->rate_up += p->count_up - compute_rate_sub(p->rate_up); | |||
if (p->rate_up < 0) | |||
p->rate_up = 0; | |||
p->count_up = 0; | |||
} | |||
if (p->count_dwn > 0 || peer_active_down(p)) { | |||
p->rate_dwn += p->count_dwn - compute_rate_sub(p->rate_dwn); | |||
if (p->rate_dwn < 0) | |||
p->rate_dwn = 0; | |||
p->count_dwn = 0; | |||
} | |||
} | |||
} | |||
} | |||
void | |||
@@ -450,8 +473,12 @@ net_bw_cb(int sd, short type, void *arg) | |||
{ | |||
struct peer *p; | |||
m_bw_bytes_out = net_bw_limit_out / net_bw_hz; | |||
m_bw_bytes_in = net_bw_limit_in / net_bw_hz; | |||
evtimer_add(&m_bw_timer, (& (struct timeval) { 1, 0 })); | |||
compute_peer_rates(); | |||
m_bw_bytes_out = net_bw_limit_out; | |||
m_bw_bytes_in = net_bw_limit_in; | |||
if (net_bw_limit_in > 0) { | |||
while ((p = BTPDQ_FIRST(&net_bw_readq)) != NULL && m_bw_bytes_in > 0) { | |||
@@ -480,7 +507,6 @@ net_bw_cb(int sd, short type, void *arg) | |||
net_write(p, 0); | |||
} | |||
} | |||
add_bw_timer(); | |||
} | |||
void | |||
@@ -519,8 +545,8 @@ net_write_cb(int sd, short type, void *arg) | |||
void | |||
net_init(void) | |||
{ | |||
m_bw_bytes_out = net_bw_limit_out / net_bw_hz; | |||
m_bw_bytes_in = net_bw_limit_in / net_bw_hz; | |||
m_bw_bytes_out = net_bw_limit_out; | |||
m_bw_bytes_in = net_bw_limit_in; | |||
int nfiles = getdtablesize(); | |||
if (nfiles <= 20) | |||
@@ -553,6 +579,5 @@ net_init(void) | |||
event_add(&m_net_incoming, NULL); | |||
evtimer_set(&m_bw_timer, net_bw_cb, NULL); | |||
if (net_bw_limit_out > 0 || net_bw_limit_in > 0) | |||
add_bw_timer(); | |||
evtimer_add(&m_bw_timer, (& (struct timeval) { 1, 0 })); | |||
} |
@@ -10,5 +10,4 @@ uint32_t btpd_logmask = BTPD_L_BTPD | BTPD_L_ERROR; | |||
unsigned net_max_peers; | |||
unsigned net_bw_limit_in; | |||
unsigned net_bw_limit_out; | |||
short net_bw_hz = 8; | |||
int net_port = 6881; |
@@ -4,5 +4,4 @@ extern uint32_t btpd_logmask; | |||
extern unsigned net_max_peers; | |||
extern unsigned net_bw_limit_in; | |||
extern unsigned net_bw_limit_out; | |||
extern short net_bw_hz; | |||
extern int net_port; |
@@ -9,15 +9,6 @@ | |||
#include "btpd.h" | |||
unsigned long | |||
peer_get_rate(unsigned long *rates) | |||
{ | |||
unsigned long ret = 0; | |||
for (int i = 0; i < RATEHISTORY; i++) | |||
ret += rates[i]; | |||
return ret; | |||
} | |||
void | |||
peer_kill(struct peer *p) | |||
{ | |||
@@ -525,3 +516,16 @@ peer_leech_ok(struct peer *p) | |||
{ | |||
return (p->flags & (PF_I_WANT|PF_P_CHOKE)) == PF_I_WANT; | |||
} | |||
int | |||
peer_active_down(struct peer *p) | |||
{ | |||
return peer_leech_ok(p) || p->nreqs_out > 0; | |||
} | |||
int | |||
peer_active_up(struct peer *p) | |||
{ | |||
return (p->flags & (PF_P_WANT|PF_I_CHOKE)) == PF_P_WANT | |||
|| p->npiece_msgs > 0; | |||
} |
@@ -12,7 +12,6 @@ | |||
#define PF_INCOMING 0x100 | |||
#define PF_DO_UNWANT 0x200 | |||
#define RATEHISTORY 20 | |||
#define MAXPIECEMSGS 128 | |||
#define MAXPIPEDREQUESTS 10 | |||
@@ -47,8 +46,8 @@ struct peer { | |||
struct event in_ev; | |||
struct event out_ev; | |||
unsigned long rate_to_me[RATEHISTORY]; | |||
unsigned long rate_from_me[RATEHISTORY]; | |||
long rate_up, rate_dwn; | |||
long count_up, count_dwn; | |||
struct { | |||
uint32_t msg_len; | |||
@@ -83,8 +82,6 @@ void peer_cancel(struct peer *p, struct block_request *req, | |||
int peer_requested(struct peer *p, struct block *blk); | |||
unsigned long peer_get_rate(unsigned long *rates); | |||
void peer_create_in(int sd); | |||
void peer_create_out(struct torrent *tp, const uint8_t *id, | |||
const char *ip, int port); | |||
@@ -107,6 +104,8 @@ void peer_on_request(struct peer *p, uint32_t index, uint32_t begin, | |||
void peer_on_cancel(struct peer *p, uint32_t index, uint32_t begin, | |||
uint32_t length); | |||
int peer_active_down(struct peer *p); | |||
int peer_active_up(struct peer *p); | |||
int peer_chokes(struct peer *p); | |||
int peer_wanted(struct peer *p); | |||
int peer_laden(struct peer *p); | |||
@@ -1,7 +1,7 @@ | |||
#include "btpd.h" | |||
static int | |||
rate_cmp(unsigned long rate1, unsigned long rate2) | |||
rate_cmp(long rate1, long rate2) | |||
{ | |||
if (rate1 < rate2) | |||
return -1; | |||
@@ -14,16 +14,16 @@ rate_cmp(unsigned long rate1, unsigned long rate2) | |||
static int | |||
dwnrate_cmp(const void *p1, const void *p2) | |||
{ | |||
unsigned long rate1 = peer_get_rate((*(struct peer **)p1)->rate_to_me); | |||
unsigned long rate2 = peer_get_rate((*(struct peer **)p2)->rate_to_me); | |||
long rate1 = (*(struct peer **)p1)->rate_dwn; | |||
long rate2 = (*(struct peer **)p2)->rate_dwn; | |||
return rate_cmp(rate1, rate2); | |||
} | |||
static int | |||
uprate_cmp(const void *p1, const void *p2) | |||
{ | |||
unsigned long rate1 = peer_get_rate((*(struct peer **)p1)->rate_from_me); | |||
unsigned long rate2 = peer_get_rate((*(struct peer **)p2)->rate_from_me); | |||
long rate1 = (*(struct peer **)p1)->rate_up; | |||
long rate2 = (*(struct peer **)p2)->rate_up; | |||
return rate_cmp(rate1, rate2); | |||
} | |||
@@ -15,14 +15,6 @@ dl_by_second(struct torrent *tp) | |||
if (btpd_seconds == tp->choke_time) | |||
choke_alg(tp); | |||
struct peer *p; | |||
int ri = btpd_seconds % RATEHISTORY; | |||
BTPDQ_FOREACH(p, &tp->peers, p_entry) { | |||
p->rate_to_me[ri] = 0; | |||
p->rate_from_me[ri] = 0; | |||
} | |||
} | |||
/* | |||