about summary refs log tree commit homepage
path: root/ext/mwrap/httpd.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mwrap/httpd.h')
-rw-r--r--ext/mwrap/httpd.h241
1 files changed, 126 insertions, 115 deletions
diff --git a/ext/mwrap/httpd.h b/ext/mwrap/httpd.h
index ef4d83c..8a105aa 100644
--- a/ext/mwrap/httpd.h
+++ b/ext/mwrap/httpd.h
@@ -221,7 +221,7 @@ static FILE *fbuf_init(struct mw_fbuf *fb)
 {
         fb->ptr = NULL;
         fb->fp = open_memstream(&fb->ptr, &fb->len);
-        if (!fb->fp) fprintf(stderr, "open_memstream: %m\n");
+        if (!fb->fp) perror("open_memstream");
         return fb->fp;
 }
 
@@ -237,7 +237,7 @@ static int fbuf_close(struct mw_fbuf *fb)
 {
         int e = ferror(fb->fp) | fclose(fb->fp);
         fb->fp = NULL;
-        if (e) fprintf(stderr, "ferror|fclose: %m\n");
+        if (e) perror("ferror|fclose");
         return e;
 }
 
@@ -279,7 +279,7 @@ static enum mw_qev h1_200(struct mw_h1 *h1, struct mw_fbuf *fb, const char *ct)
          */
         off_t clen = ftello(fb->fp);
         if (clen < 0) {
-                fprintf(stderr, "ftello: %m\n");
+                perror("ftello");
                 fbuf_close(fb);
                 return h1_close(h1);
         }
@@ -468,7 +468,7 @@ static off_t write_loc_name(FILE *fp, const struct src_loc *l)
         off_t beg = ftello(fp);
 
         if (beg < 0) {
-                fprintf(stderr, "ftello: %m\n");
+                perror("ftello");
                 return beg;
         }
         if (l->f) {
@@ -498,15 +498,17 @@ static off_t write_loc_name(FILE *fp, const struct src_loc *l)
         }
         off_t end = ftello(fp);
         if (end < 0) {
-                fprintf(stderr, "ftello: %m\n");
+                perror("ftello");
                 return end;
         }
         return end - beg;
 }
 
-static struct h1_src_loc *accumulate(unsigned long min, size_t *hslc, FILE *lp)
+static struct h1_src_loc *
+accumulate(struct mw_fbuf *lb, unsigned long min, size_t *hslc)
 {
         struct mw_fbuf fb;
+        if (!fbuf_init(lb)) return NULL;
         if (!fbuf_init(&fb)) return NULL;
         rcu_read_lock();
         struct cds_lfht *t = CMM_LOAD_SHARED(totals);
@@ -528,18 +530,23 @@ static struct h1_src_loc *accumulate(unsigned long min, size_t *hslc, FILE *lp)
                         HUGE_VAL;
                 hsl.max_life = uatomic_read(&l->max_lifespan);
                 hsl.sl = l;
-                hsl.lname_len = write_loc_name(lp, l);
+                hsl.lname_len = write_loc_name(lb->fp, l);
                 fwrite(&hsl, sizeof(hsl), 1, fb.fp);
         }
         rcu_read_unlock();
 
-        struct h1_src_loc *hslv;
-        if (fbuf_close(&fb)) {
-                hslv = NULL;
-        } else {
-                *hslc = fb.len / sizeof(*hslv);
-                mwrap_assert((fb.len % sizeof(*hslv)) == 0);
-                hslv = (struct h1_src_loc *)fb.ptr;
+        if (fbuf_close(&fb) || fbuf_close(lb))
+                return NULL;
+
+        struct h1_src_loc *hslv = (struct h1_src_loc *)fb.ptr;
+        *hslc = fb.len / sizeof(*hslv);
+        mwrap_assert((fb.len % sizeof(*hslv)) == 0);
+        char *n = lb->ptr;
+        for (size_t i = 0; i < *hslc; ++i) {
+                hslv[i].loc_name = n;
+                n += hslv[i].lname_len;
+                if (hslv[i].lname_len < 0)
+                        return NULL;
         }
         return hslv;
 }
@@ -609,124 +616,128 @@ static enum mw_qev each_at(struct mw_h1 *h1, struct mw_h1req *h1r)
         return h1_200(h1, &html, TYPE_HTML);
 }
 
-/* /$PID/each/$MIN endpoint */
-static enum mw_qev each_gt(struct mw_h1 *h1, struct mw_h1req *h1r,
-                                unsigned long min, bool csv)
-{
-        static const char default_sort[] = "bytes";
-        const char *sort;
-        size_t sort_len = 0;
+typedef int (*cmp_fn)(const void *, const void *);
 
-        if (!csv) {
-                sort = default_sort;
-                sort_len = sizeof(default_sort) - 1;
+static cmp_fn write_csv_header(FILE *fp, const char *sort, size_t sort_len)
+{
+        cmp_fn cmp = NULL;
+        for (size_t i = 0; i < CAA_ARRAY_SIZE(fields); i++) {
+                const char *fn = fields[i].fname;
+                if (i)
+                        fputc(',', fp);
+                fputs(fn, fp);
+                if (fields[i].flen == sort_len && !memcmp(fn, sort, sort_len))
+                        cmp = fields[i].cmp;
         }
+        fputc('\n', fp);
+        return cmp;
+}
 
-        if (h1r->qstr && h1r->qlen > 5 && !memcmp(h1r->qstr, "sort=", 5)) {
-                sort = h1r->qstr + 5;
-                sort_len = h1r->qlen - 5;
+static void write_csv_data(FILE *fp, struct h1_src_loc *hslv, size_t hslc)
+{
+        for (size_t i = 0; i < hslc; i++) {
+                struct h1_src_loc *hsl = &hslv[i];
+
+                fprintf(fp, "%zu,%zu,%zu,%zu,%0.3f,%zu,",
+                        hsl->bytes, hsl->allocations, hsl->frees,
+                        hsl->live, hsl->mean_life, hsl->max_life);
+                write_q_csv(fp, hsl->loc_name, hsl->lname_len);
+                fputc('\n', fp);
         }
+}
 
-        size_t hslc;
+static void *write_csv(FILE *fp, size_t min, const char *sort, size_t sort_len)
+{
         AUTO_CLOFREE struct mw_fbuf lb;
-        if (!fbuf_init(&lb)) return h1_close(h1);
-        AUTO_FREE struct h1_src_loc *hslv = accumulate(min, &hslc, lb.fp);
-        if (!hslv)
-                return h1_close(h1);
+        size_t hslc;
+        AUTO_FREE struct h1_src_loc *hslv = accumulate(&lb, min, &hslc);
+        if (!hslv) return NULL;
 
-        if (fbuf_close(&lb))
-                return h1_close(h1);
+        cmp_fn cmp = write_csv_header(fp, sort, sort_len);
+        if (cmp)
+                qsort(hslv, hslc, sizeof(*hslv), cmp);
+        write_csv_data(fp, hslv, hslc);
+        return fp;
+}
 
-        char *n = lb.ptr;
-        for (size_t i = 0; i < hslc; ++i) {
-                hslv[i].loc_name = n;
-                n += hslv[i].lname_len;
-                if (hslv[i].lname_len < 0)
-                        return h1_close(h1);
+/* /$PID/each/$MIN endpoint */
+static enum mw_qev each_gt(struct mw_h1 *h1, struct mw_h1req *h1r,
+                                size_t min, bool csv)
+{
+        static const char default_sort[] = "bytes";
+        const char *sort = csv ? NULL : default_sort;
+        size_t sort_len = csv ? 0 : (sizeof(default_sort) - 1);
+
+        if (h1r->qstr && h1r->qlen > 5 && !memcmp(h1r->qstr, "sort=", 5)) {
+                sort = h1r->qstr + 5;
+                sort_len = h1r->qlen - 5;
         }
 
         struct mw_fbuf bdy;
         FILE *fp = wbuf_init(&bdy);
         if (!fp) return h1_close(h1);
-
-        if (!csv) {
-                unsigned depth = (unsigned)CMM_LOAD_SHARED(bt_req_depth);
-                fprintf(fp, "<html><head><title>mwrap each &gt;%lu"
-                        "</title></head><body><p>mwrap each &gt;%lu "
-                        "(change `%lu' in URL to adjust filtering) - "
-                        "MWRAP=bt:%u <a href=\"%lu.csv\">.csv</a>",
-                        min, min, min, depth, min);
-                show_stats(fp);
-                /* need borders to distinguish multi-level traces */
-                if (depth)
-                        FPUTS("<table\nborder=1><tr>", fp);
-                else /* save screen space if only tracing one line */
-                        FPUTS("<table><tr>", fp);
+        if (csv) {
+                if (write_csv(fp, min, sort, sort_len))
+                        return h1_200(h1, &bdy, TYPE_CSV);
+                return h1_close(h1);
         }
 
-        int (*cmp)(const void *, const void *) = NULL;
-        if (csv) {
-                for (size_t i = 0; i < CAA_ARRAY_SIZE(fields); i++) {
-                        const char *fn = fields[i].fname;
-                        if (i)
-                                fputc(',', fp);
-                        fputs(fn, fp);
-                        if (fields[i].flen == sort_len &&
-                                        !memcmp(fn, sort, sort_len))
-                                cmp = fields[i].cmp;
-                }
-                fputc('\n', fp);
-        } else {
-                for (size_t i = 0; i < CAA_ARRAY_SIZE(fields); i++) {
-                        const char *fn = fields[i].fname;
-                        FPUTS("<th>", fp);
-                        if (fields[i].flen == sort_len &&
-                                        !memcmp(fn, sort, sort_len)) {
-                                cmp = fields[i].cmp;
-                                fprintf(fp, "<b>%s</b>", fields[i].fname);
-                        } else {
-                                fprintf(fp, "<a\nhref=\"./%lu?sort=%s\">%s</a>",
-                                        min, fn, fn);
-                        }
-                        FPUTS("</th>", fp);
+        size_t hslc;
+        AUTO_CLOFREE struct mw_fbuf lb;
+        AUTO_FREE struct h1_src_loc *hslv = accumulate(&lb, min, &hslc);
+        if (!hslv)
+                return h1_close(h1);
+
+        unsigned depth = (unsigned)CMM_LOAD_SHARED(bt_req_depth);
+        fprintf(fp, "<html><head><title>mwrap each &gt;%lu"
+                "</title></head><body><p>mwrap each &gt;%lu "
+                "(change `%lu' in URL to adjust filtering) - "
+                "MWRAP=bt:%u <a href=\"%lu.csv\">.csv</a>",
+                min, min, min, depth, min);
+        show_stats(fp);
+        /* need borders to distinguish multi-level traces */
+        if (depth)
+                FPUTS("<table\nborder=1><tr>", fp);
+        else /* save screen space if only tracing one line */
+                FPUTS("<table><tr>", fp);
+        cmp_fn cmp = NULL;
+        for (size_t i = 0; i < CAA_ARRAY_SIZE(fields); i++) {
+                const char *fn = fields[i].fname;
+                FPUTS("<th>", fp);
+                if (fields[i].flen == sort_len &&
+                                !memcmp(fn, sort, sort_len)) {
+                        cmp = fields[i].cmp;
+                        fprintf(fp, "<b>%s</b>", fields[i].fname);
+                } else {
+                        fprintf(fp, "<a\nhref=\"./%lu?sort=%s\">%s</a>",
+                                min, fn, fn);
                 }
+                FPUTS("</th>", fp);
         }
-        if (!csv)
-                FPUTS("</tr>", fp);
+        FPUTS("</tr>", fp);
         if (cmp)
                 qsort(hslv, hslc, sizeof(*hslv), cmp);
-        else if (!csv)
+        else
                 FPUTS("<tr><td>sort= not understood</td></tr>", fp);
-        if (csv) {
-                for (size_t i = 0; i < hslc; i++) {
-                        struct h1_src_loc *hsl = &hslv[i];
 
-                        fprintf(fp, "%zu,%zu,%zu,%zu,%0.3f,%zu,",
-                                hsl->bytes, hsl->allocations, hsl->frees,
-                                hsl->live, hsl->mean_life, hsl->max_life);
-                        write_q_csv(fp, hsl->loc_name, hsl->lname_len);
-                        fputc('\n', fp);
-                }
-        } else {
-                for (size_t i = 0; i < hslc; i++) {
-                        struct h1_src_loc *hsl = &hslv[i];
+        for (size_t i = 0; i < hslc; i++) {
+                struct h1_src_loc *hsl = &hslv[i];
 
-                        fprintf(fp, "<tr><td>%zu</td><td>%zu</td><td>%zu</td>"
-                                "<td>%zu</td><td>%0.3f</td><td>%zu</td>",
-                                hsl->bytes, hsl->allocations, hsl->frees,
-                                hsl->live, hsl->mean_life, hsl->max_life);
-                        FPUTS("<td><a\nhref=\"../at/", fp);
+                fprintf(fp, "<tr><td>%zu</td><td>%zu</td><td>%zu</td>"
+                        "<td>%zu</td><td>%0.3f</td><td>%zu</td>",
+                        hsl->bytes, hsl->allocations, hsl->frees,
+                        hsl->live, hsl->mean_life, hsl->max_life);
+                FPUTS("<td><a\nhref=\"../at/", fp);
 
-                        write_b64_url(fp, src_loc_hash_tip(hsl->sl),
-                                        src_loc_hash_len(hsl->sl));
+                write_b64_url(fp, src_loc_hash_tip(hsl->sl),
+                                src_loc_hash_len(hsl->sl));
 
-                        FPUTS("\">", fp);
-                        write_html(fp, hsl->loc_name, hsl->lname_len);
-                        FPUTS("</a></td></tr>", fp);
-                }
-                FPUTS("</table></body></html>", fp);
+                FPUTS("\">", fp);
+                write_html(fp, hsl->loc_name, hsl->lname_len);
+                FPUTS("</a></td></tr>", fp);
         }
-        return h1_200(h1, &bdy, csv ? TYPE_CSV : TYPE_HTML);
+        FPUTS("</table></body></html>", fp);
+        return h1_200(h1, &bdy, TYPE_HTML);
 }
 
 /* /$PID/ root endpoint */
@@ -781,7 +792,7 @@ static enum mw_qev h1_dispatch(struct mw_h1 *h1, struct mw_h1req *h1r)
                 if ((c = PATH_SKIP(h1r, "/each/"))) {
                         errno = 0;
                         char *e;
-                        unsigned long min = strtoul(c, &e, 10);
+                        size_t min = (size_t)strtoul(c, &e, 10);
                         if (!errno) {
                                 if (*e == ' ' || *e == '?')
                                         return each_gt(h1, h1r, min, false);
@@ -857,7 +868,7 @@ static enum mw_qev h1_drain_input(struct mw_h1 *h1, struct mw_h1req *h1r,
                                 return h1_close(h1);
                         default: /* ENOMEM, ENOBUFS, ... */
                                 assert(errno != EBADF);
-                                fprintf(stderr, "read: %m\n");
+                                perror("read");
                                 return h1_close(h1);
                         }
                 }
@@ -990,7 +1001,7 @@ static enum mw_qev h1_event_step(struct mw_h1 *h1, struct mw_h1d *h1d)
         if (!h1r) {
                 h1r = h1d->shared_h1r = malloc(sizeof(*h1r));
                 if (!h1r) {
-                        fprintf(stderr, "h1r malloc: %m\n");
+                        perror("h1r malloc");
                         return h1_close(h1);
                 }
         }
@@ -1034,7 +1045,7 @@ static enum mw_qev h1_event_step(struct mw_h1 *h1, struct mw_h1d *h1d)
                                 return h1_close(h1);
                         default: /* ENOMEM, ENOBUFS, ... */
                                 assert(errno != EBADF);
-                                fprintf(stderr, "read: %m\n");
+                                perror("read");
                                 return h1_close(h1);
                         }
                 }
@@ -1142,7 +1153,7 @@ static void h1d_unlink(struct mw_h1d *h1d, bool do_close)
         if (h1d->lfd < 0 || !h1d->pid_len)
                 return;
         if (getsockname(h1d->lfd, &sa.any, &len) < 0) {
-                fprintf(stderr, "getsockname: %m\n");
+                perror("getsockname");
                 return;
         }
         if (do_close) { /* only safe to close if thread isn't running */
@@ -1208,13 +1219,13 @@ static int h1d_init(struct mw_h1d *h1d, const char *menv)
                 return fprintf(stderr, "unlink(%s): %m\n", sa.un.sun_path);
         h1d->lfd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
         if (h1d->lfd < 0)
-                return fprintf(stderr, "socket: %m\n");
+                return perror("socket"), 1;
         if (bind(h1d->lfd, &sa.any, (socklen_t)sizeof(sa)) < 0) {
-                fprintf(stderr, "bind: %m\n");
+                perror("bind");
                 goto close_fail;
         }
         if (listen(h1d->lfd, 1024) < 0) {
-                fprintf(stderr, "listen: %m\n");
+                perror("listen");
                 goto close_fail;
         }
         h1d->alive = 1; /* runs in parent, before pthread_create */