running. * Added --downloaders and --max-peers options and hopefully usefull defaults. Because curl uses fd_sets it's important to keep the numbers of fds used below FD_SETSIZE. I will probably move the curl stuff to it's own process to get rid of that limitation. * Added to the help text.master
@@ -1,7 +1,7 @@ | |||
bin_PROGRAMS=btpd | |||
btpd_SOURCES=\ | |||
btpd.c btpd.h\ | |||
content.c content.h\ | |||
cli_if.c content.c content.h\ | |||
download.c download_subr.c download.h\ | |||
http.c http.h\ | |||
main.c\ | |||
@@ -216,7 +216,7 @@ btpd_init(void) | |||
td_init(); | |||
http_init(); | |||
net_init(); | |||
//ipc_init(); | |||
ipc_init(); | |||
ul_init(); | |||
cm_init(); | |||
@@ -36,20 +36,27 @@ cmd_stat(int argc, const char *args, FILE *fp) | |||
errdie(buf_print(&iob, "9:ntorrentsi%ue", btpd_get_ntorrents())); | |||
errdie(buf_swrite(&iob, "8:torrentsl")); | |||
BTPDQ_FOREACH(tp, btpd_get_torrents(), entry) { | |||
if (tp->state != T_ACTIVE) | |||
continue; | |||
uint32_t seen_npieces = 0; | |||
for (uint32_t i = 0; i < tp->meta.npieces; i++) | |||
if (tp->piece_count[i] > 0) | |||
if (tp->net->piece_count[i] > 0) | |||
seen_npieces++; | |||
errdie(buf_print(&iob, "d4:downi%jue", (intmax_t)tp->downloaded)); | |||
errdie(buf_print(&iob, "d4:downi%jue", (intmax_t)tp->net->downloaded)); | |||
errdie(buf_swrite(&iob, "4:hash20:")); | |||
errdie(buf_write(&iob, tp->meta.info_hash, 20)); | |||
errdie(buf_print(&iob, "12:have npiecesi%ue", tp->have_npieces)); | |||
errdie(buf_print(&iob, "6:npeersi%ue", tp->npeers)); | |||
errdie(buf_print(&iob, "4:havei%jde", (intmax_t)cm_get_size(tp))); | |||
errdie(buf_print(&iob, "6:npeersi%ue", tp->net->npeers)); | |||
errdie(buf_print(&iob, "7:npiecesi%ue", tp->meta.npieces)); | |||
errdie(buf_print(&iob, "4:path%d:%s", | |||
(int)strlen(tp->relpath), tp->relpath)); | |||
errdie(buf_print(&iob, "2:rdi%lue", tp->net->rate_dwn)); | |||
errdie(buf_print(&iob, "2:rui%lue", tp->net->rate_up)); | |||
errdie(buf_print(&iob, "12:seen npiecesi%ue", seen_npieces)); | |||
errdie(buf_print(&iob, "2:upi%juee", (intmax_t)tp->uploaded)); | |||
errdie(buf_print(&iob, "5:totali%jde", | |||
(intmax_t)tp->meta.total_length)); | |||
errdie(buf_print(&iob, "2:upi%juee", (intmax_t)tp->net->uploaded)); | |||
} | |||
errdie(buf_swrite(&iob, "ee")); | |||
@@ -59,6 +66,7 @@ cmd_stat(int argc, const char *args, FILE *fp) | |||
free(iob.buf); | |||
} | |||
#if 0 | |||
static void | |||
cmd_add(int argc, const char *args, FILE *fp) | |||
{ | |||
@@ -144,15 +152,18 @@ cmd_die(int argc, const char *args, FILE *fp) | |||
btpd_log(BTPD_L_BTPD, "Someone wants me dead.\n"); | |||
btpd_shutdown(); | |||
} | |||
#endif | |||
static struct { | |||
const char *name; | |||
int nlen; | |||
void (*fun)(int, const char *, FILE *); | |||
} cmd_table[] = { | |||
#if 0 | |||
{ "add", 3, cmd_add }, | |||
{ "del", 3, cmd_del }, | |||
{ "die", 3, cmd_die }, | |||
#endif | |||
{ "stat", 4, cmd_stat } | |||
}; | |||
@@ -61,8 +61,13 @@ setup_daemon(const char *dir) | |||
err(1, "Couldn't create library"); | |||
pidfd = open("pid", O_CREAT|O_WRONLY|O_NONBLOCK|O_EXLOCK, 0666); | |||
if (pidfd == -1) | |||
err(1, "Couldn't open 'pid'"); | |||
if (pidfd == -1) { | |||
if (errno == EAGAIN) | |||
errx(1, "Another instance of btpd is probably running in %s.", | |||
dir); | |||
else | |||
err(1, "Couldn't open 'pid'"); | |||
} | |||
if (btpd_daemon) { | |||
if (daemon(1, 1) != 0) | |||
@@ -82,6 +87,10 @@ static void | |||
usage(void) | |||
{ | |||
printf("Usage: btpd [options] [dir]\n" | |||
"\n" | |||
"dir:\n" | |||
"\tThe directory in which to run btpd.\n" | |||
"\tDefault is '$HOME/.btpd'.\n" | |||
"\n" | |||
"Options:\n" | |||
"\n" | |||
@@ -97,11 +106,22 @@ usage(void) | |||
"\tKeep the btpd process in the foregorund and log to std{out,err}.\n" | |||
"\tThis option is intended for debugging purposes.\n" | |||
"\n" | |||
"--downloaders n\n" | |||
"\tControls the number of simultaneous uploads.\n" | |||
"\tThe possible values are:\n" | |||
"\t\tn < -1 : Choose n >= 2 based on --bw-out (default).\n" | |||
"\t\tn = -1 : Upload to every interested peer.\n" | |||
"\t\tn = 0 : Dont't upload to anyone.\n" | |||
"\t\tn > 0 : Upload to at most n peers simultaneosly.\n" | |||
"\n" | |||
"--max-peers n\n" | |||
"\tLimit the amount of peers to n.\n" | |||
"\n" | |||
"-p n, --port n\n" | |||
"\tListen at port n. Default is 6881.\n" | |||
"\n" | |||
"--prealloc n\n" | |||
"\tPreallocate disk space in chunks n kB. Default is 1.\n" | |||
"\tPreallocate disk space in chunks of n kB. Default is 1.\n" | |||
"\tNote that n will be rounded up to the closest multiple of the\n" | |||
"\ttorrent piece size. If n is zero no preallocation will be done.\n" | |||
"\n" | |||
@@ -118,7 +138,9 @@ static struct option longopts[] = { | |||
{ "bw-in", required_argument, &longval, 1 }, | |||
{ "bw-out", required_argument, &longval, 2 }, | |||
{ "prealloc", required_argument, &longval, 3 }, | |||
{ "help", no_argument, &longval, 5 }, | |||
{ "downloaders", required_argument, &longval, 4 }, | |||
{ "max-peers", required_argument, &longval, 5 }, | |||
{ "help", no_argument, &longval, 128 }, | |||
{ NULL, 0, NULL, 0 } | |||
}; | |||
@@ -150,6 +172,12 @@ main(int argc, char **argv) | |||
case 3: | |||
cm_alloc_size = atoi(optarg) * 1024; | |||
break; | |||
case 4: | |||
net_max_downloaders = atoi(optarg); | |||
break; | |||
case 5: | |||
net_max_peers = atoi(optarg); | |||
break; | |||
default: | |||
usage(); | |||
} | |||
@@ -626,16 +626,9 @@ net_init(void) | |||
m_bw_bytes_out = net_bw_limit_out; | |||
m_bw_bytes_in = net_bw_limit_in; | |||
int nfiles = getdtablesize(); | |||
if (nfiles <= 20) | |||
btpd_err("Too few open files allowed (%d). " | |||
"Check \"ulimit -n\"\n", nfiles); | |||
else if (nfiles < 64) | |||
btpd_log(BTPD_L_BTPD, | |||
"You have restricted the number of open files to %d. " | |||
"More could be beneficial to the download performance.\n", | |||
nfiles); | |||
net_max_peers = nfiles - 20; | |||
int safe_fds = min(getdtablesize(), FD_SETSIZE) * 4 / 5; | |||
if (net_max_peers == 0 || net_max_peers > safe_fds) | |||
net_max_peers = safe_fds; | |||
int sd; | |||
int flag = 1; | |||
@@ -7,6 +7,7 @@ uint32_t btpd_logmask = BTPD_L_ALL; | |||
#else | |||
uint32_t btpd_logmask = BTPD_L_BTPD | BTPD_L_ERROR; | |||
#endif | |||
int net_max_downloaders = -2; | |||
unsigned net_max_peers; | |||
unsigned net_bw_limit_in; | |||
unsigned net_bw_limit_out; | |||
@@ -4,6 +4,7 @@ | |||
extern short btpd_daemon; | |||
extern const char *btpd_dir; | |||
extern uint32_t btpd_logmask; | |||
extern int net_max_downloaders; | |||
extern unsigned net_max_peers; | |||
extern unsigned net_bw_limit_in; | |||
extern unsigned net_bw_limit_out; | |||
@@ -7,7 +7,7 @@ | |||
static struct event m_choke_timer; | |||
static unsigned m_npeers; | |||
static struct peer_tq m_peerq = BTPDQ_HEAD_INITIALIZER(m_peerq); | |||
static int m_max_downloaders = 4; | |||
static int m_max_downloaders; | |||
struct peer_sort { | |||
struct peer *p; | |||
@@ -32,7 +32,7 @@ rate_cmp(const void *arg1, const void *arg2) | |||
static void | |||
choke_do(void) | |||
{ | |||
if (m_max_downloaders == -1) { | |||
if (m_max_downloaders < 0) { | |||
struct peer *p; | |||
BTPDQ_FOREACH(p, &m_peerq, ul_entry) | |||
if (p->flags & PF_I_CHOKE) | |||
@@ -42,7 +42,7 @@ choke_do(void) | |||
BTPDQ_FOREACH(p, &m_peerq, ul_entry) | |||
if ((p->flags & PF_I_CHOKE) == 0) | |||
peer_choke(p); | |||
} else if (m_npeers > 0) { | |||
} else { | |||
struct peer_sort worthy[m_npeers]; | |||
int nworthy = 0; | |||
int i = 0; | |||
@@ -171,6 +171,21 @@ ul_on_uninterest(struct peer *p) | |||
void | |||
ul_init(void) | |||
{ | |||
if (net_max_downloaders >= -1) | |||
m_max_downloaders = net_max_downloaders; | |||
else { | |||
if (net_bw_limit_out == 0) | |||
m_max_downloaders = 8; | |||
else if (net_bw_limit_out < (10 << 10)) | |||
m_max_downloaders = 2; | |||
else if (net_bw_limit_out < (20 << 10)) | |||
m_max_downloaders = 3; | |||
else if (net_bw_limit_out < (40 << 10)) | |||
m_max_downloaders = 4; | |||
else | |||
m_max_downloaders = 5 + (net_bw_limit_out / (100 << 10)); | |||
} | |||
evtimer_set(&m_choke_timer, choke_cb, NULL); | |||
evtimer_add(&m_choke_timer, CHOKE_INTERVAL); | |||
} |