about summary refs log tree commit diff
path: root/cli/stat.c
diff options
context:
space:
mode:
authorRichard Nyberg <rnyberg@murmeldjur.se>2006-09-13 07:02:07 +0000
committerRichard Nyberg <rnyberg@murmeldjur.se>2006-09-13 07:02:07 +0000
commit86754d7d53b59ce52de51a32f865d4916c119bdb (patch)
treef017a8199a94e675fb50f55876119fe9e9d1944b /cli/stat.c
parent763cbbb59f40bdfb2478e58a685acfc262876af6 (diff)
downloadbtpd-86754d7d53b59ce52de51a32f865d4916c119bdb.tar.gz
btpd-86754d7d53b59ce52de51a32f865d4916c119bdb.zip
btpd now has a library of torrents indexed by number and info hash.
The add and del commands adds or removes torrents from this library.
The start and stop commands are used to active or deactivate torrents.
Also, a mechanism for qeurying data on torrents has been added. It's
only used by the btcli list and stat commands yet though.

btcli has been split into different files for each command.

Both btpd and btcli now use misc/btpd_if.h for all ipc definitions.

Misc changes:
- struct metainfo is gone. Use the new mi_* functions.
- Add printf format type checking where appropriate.

Diffstat (limited to 'cli/stat.c')
-rw-r--r--cli/stat.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/cli/stat.c b/cli/stat.c
new file mode 100644
index 0000000..2af1210
--- /dev/null
+++ b/cli/stat.c
@@ -0,0 +1,193 @@
+#include <math.h>
+
+#include "btcli.h"
+
+void
+usage_stat(void)
+{
+    printf(
+        "Display stats for active torrents.\n"
+        "\n"
+        "Usage: stat [-i] [-w seconds] [file ...]\n"
+        "\n"
+        "Arguments:\n"
+        "file ...\n"
+        "\tOnly display stats for the given torrent(s).\n"
+        "\n"
+        "Options:\n"
+        "-i\n"
+        "\tDisplay individual lines for each torrent.\n"
+        "\n"
+        "-n\n"
+        "\tDisplay the name of each torrent. Implies '-i'.\n"
+        "\n"
+        "-w n\n"
+        "\tDisplay stats every n seconds.\n"
+        "\n");
+    exit(1);
+}
+
+struct btstat {
+    unsigned num;
+    enum ipc_tstate state;
+    unsigned peers, tr_errors;
+    long long content_got, content_size, downloaded, uploaded, rate_up,
+        rate_down;
+    uint32_t pieces_seen, torrent_pieces;
+};
+
+struct cbarg {
+    int individual, names;
+    struct btstat tot;
+};
+
+static enum ipc_tval stkeys[] = {
+    IPC_TVAL_STATE,
+    IPC_TVAL_NUM,
+    IPC_TVAL_NAME,
+    IPC_TVAL_PCOUNT,
+    IPC_TVAL_TRERR,
+    IPC_TVAL_PCCOUNT,
+    IPC_TVAL_PCSEEN,
+    IPC_TVAL_SESSUP,
+    IPC_TVAL_SESSDWN,
+    IPC_TVAL_RATEUP,
+    IPC_TVAL_RATEDWN,
+    IPC_TVAL_CGOT,
+    IPC_TVAL_CSIZE
+};
+
+static size_t nstkeys = sizeof(stkeys) / sizeof(stkeys[0]);
+
+static void
+print_stat(struct btstat *st)
+{
+    printf("%5.1f%% %6.1fM %7.2fkB/s %6.1fM %7.2fkB/s %5u %5.1f%%",
+        floor(1000.0 * st->content_got / st->content_size) / 10,
+        (double)st->downloaded / (1 << 20),
+        (double)st->rate_down / (20 << 10),
+        (double)st->uploaded / (1 << 20),
+        (double)st->rate_up / (20 << 10),
+        st->peers,
+        floor(1000.0 * st->pieces_seen / st->torrent_pieces) / 10);
+    if (st->tr_errors > 0)
+        printf(" E%u", st->tr_errors);
+    printf("\n");
+}
+
+void
+stat_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg)
+{
+    struct cbarg *cba = arg;
+    struct btstat st, *tot = &cba->tot;
+    if (objerr != IPC_OK || res[IPC_TVAL_STATE].v.num == IPC_TSTATE_INACTIVE)
+        return;
+    bzero(&st, sizeof(st));
+    st.state = res[IPC_TVAL_STATE].v.num;
+    st.num = res[IPC_TVAL_NUM].v.num;
+    tot->torrent_pieces += (st.torrent_pieces = res[IPC_TVAL_PCCOUNT].v.num);
+    tot->pieces_seen += (st.pieces_seen = res[IPC_TVAL_PCSEEN].v.num);
+    tot->content_got += (st.content_got = res[IPC_TVAL_CGOT].v.num);
+    tot->content_size += (st.content_size = res[IPC_TVAL_CSIZE].v.num);
+    tot->downloaded += (st.downloaded = res[IPC_TVAL_SESSDWN].v.num);
+    tot->uploaded += (st.uploaded = res[IPC_TVAL_SESSUP].v.num);
+    tot->rate_down += (st.rate_down = res[IPC_TVAL_RATEDWN].v.num);
+    tot->rate_up += (st.rate_up = res[IPC_TVAL_RATEUP].v.num);
+    tot->peers += (st.peers = res[IPC_TVAL_PCOUNT].v.num);
+    if ((st.tr_errors = res[IPC_TVAL_TRERR].v.num) > 0)
+        tot->tr_errors++;
+    if (cba->individual) {
+        if (cba->names)
+            printf("%.*s\n", (int)res[IPC_TVAL_NAME].v.str.l,
+                res[IPC_TVAL_NAME].v.str.p);
+        int n = printf("%u:", st.num);
+        while (n < 7) {
+            putchar(' ');
+            n++;
+        }
+        printf("%c. ", tstate_char(st.state));
+        print_stat(&st);
+    }
+}
+
+static void
+do_stat(int individual, int names, int seconds, struct ipc_torrent *tps,
+    int ntps)
+{
+    enum ipc_err err;
+    struct cbarg cba;
+    if (names)
+        individual = 1;
+    if (individual)
+        printf("NUM    ST ");
+    printf("  HAVE   DLOAD       RTDWN   ULOAD        RTUP PEERS  AVAIL\n");
+    cba.individual = individual;
+    cba.names = names;
+again:
+    bzero(&cba.tot, sizeof(cba.tot));
+    cba.tot.state = IPC_TSTATE_INACTIVE;
+    if (tps == NULL)
+        err = btpd_tget_wc(ipc, IPC_TWC_ACTIVE, stkeys, nstkeys,
+            stat_cb, &cba);
+    else
+        err = btpd_tget(ipc, tps, ntps, stkeys, nstkeys, stat_cb, &cba);
+    if (handle_ipc_res(err, "stat") != IPC_OK)
+        exit(1);
+    if (names)
+        printf("-----\n");
+    if (individual)
+        printf("Total:    ");
+    print_stat(&cba.tot);
+    if (seconds > 0) {
+        sleep(seconds);
+        goto again;
+    }
+}
+
+static struct option stat_opts [] = {
+    { "help", no_argument, NULL, 'H' },
+    {NULL, 0, NULL, 0}
+};
+
+void
+cmd_stat(int argc, char **argv)
+{
+    int ch;
+    int wflag = 0, iflag = 0, nflag = 0, seconds = 0;
+    struct ipc_torrent *tps = NULL;
+    int ntps = 0;
+    char *endptr;
+    while ((ch = getopt_long(argc, argv, "inw:", stat_opts, NULL)) != -1) {
+        switch (ch) {
+        case 'i':
+            iflag = 1;
+            break;
+        case 'n':
+            nflag = 1;
+            break;
+        case 'w':
+            wflag = 1;
+            seconds = strtol(optarg, &endptr, 10);
+            if (*endptr != '\0' || seconds < 1)
+                usage_stat();
+            break;
+        default:
+            usage_stat();
+        }
+    }
+    argc -= optind;
+    argv += optind;
+
+    if (argc > 0) {
+        tps = malloc(argc * sizeof(*tps));
+        for (int i = 0; i < argc; i++) {
+            if (torrent_spec(argv[i], &tps[ntps]))
+                ntps++;
+            else
+                exit(1);
+
+        }
+    }
+    btpd_connect();
+    do_stat(iflag, nflag, seconds, tps, ntps);
+}