mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 07:18:30 +00:00
Improve performance of printf functions
This commit is contained in:
parent
b107d2709f
commit
dc6d11a031
39 changed files with 577 additions and 650 deletions
|
@ -33,6 +33,7 @@
|
|||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/crc32.h"
|
||||
#include "libc/runtime/clktck.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
|
@ -71,7 +72,11 @@
|
|||
#define HASH_LOAD_FACTOR /* 1. / */ 4
|
||||
#define DEFAULT_PORT 8080
|
||||
|
||||
#define read(F, P, N) readv(F, &(struct iovec){P, N}, 1)
|
||||
#define Hash(P, N) max(1, crc32c(0, P, N));
|
||||
#define LockInc(P) asm volatile("lock inc%z0\t%0" : "=m"(*(P)))
|
||||
#define AppendCrlf(P) mempcpy(P, "\r\n", 2)
|
||||
#define HasHeader(H) (!!msg.headers[H].a)
|
||||
#define HeaderData(H) (inbuf.p + msg.headers[H].a)
|
||||
#define HeaderLength(H) (msg.headers[H].b - msg.headers[H].a)
|
||||
#define HeaderEqualCase(H, S) \
|
||||
|
@ -171,7 +176,7 @@ static const char kRegCode[][9] = {
|
|||
};
|
||||
|
||||
struct Buffer {
|
||||
size_t n;
|
||||
size_t n, c;
|
||||
char *p;
|
||||
};
|
||||
|
||||
|
@ -327,6 +332,7 @@ static bool istext;
|
|||
static bool zombied;
|
||||
static bool gzipped;
|
||||
static bool branded;
|
||||
static bool funtrace;
|
||||
static bool meltdown;
|
||||
static bool heartless;
|
||||
static bool printport;
|
||||
|
@ -385,6 +391,7 @@ static struct Buffer effectivepath;
|
|||
|
||||
static struct Url url;
|
||||
static struct HttpRequest msg;
|
||||
static char slashpath[PATH_MAX];
|
||||
|
||||
static long double startread;
|
||||
static long double lastrefresh;
|
||||
|
@ -399,7 +406,7 @@ static wontreturn void PrintUsage(FILE *f, int rc) {
|
|||
fprintf(f, "\
|
||||
SYNOPSIS\n\
|
||||
\n\
|
||||
%s [-hvduzmba] [-p PORT] [-- SCRIPTARGS...]\n\
|
||||
%s [-hvduzmbagf] [-p PORT] [-- SCRIPTARGS...]\n\
|
||||
\n\
|
||||
DESCRIPTION\n\
|
||||
\n\
|
||||
|
@ -415,8 +422,11 @@ FLAGS\n\
|
|||
-m log messages\n\
|
||||
-b log message body\n\
|
||||
-a log resource usage\n\
|
||||
-g log handler latency\n\
|
||||
-H K:V sets http header globally [repeat]\n\
|
||||
-g log handler latency\n"
|
||||
#ifndef TINY
|
||||
" -f log worker function calls\n"
|
||||
#endif
|
||||
" -H K:V sets http header globally [repeat]\n\
|
||||
-D DIR serve assets from local directory [repeat]\n\
|
||||
-t MS tunes read and write timeouts [default 30000]\n\
|
||||
-c SEC configures static asset cache-control headers\n\
|
||||
|
@ -545,8 +555,6 @@ USAGE\n\
|
|||
then puts the original back once the program loads. If you want\n\
|
||||
your redbean to follow the platform-local executable convention\n\
|
||||
then delete the /.ape file from zip.\n\
|
||||
\n\
|
||||
LEGAL\n\
|
||||
\n\
|
||||
redbean contains software licensed ISC, MIT, BSD-2, BSD-3, zlib\n\
|
||||
which makes it a permissively licensed gift to anyone who might\n\
|
||||
|
@ -664,38 +672,53 @@ static void UseOutput(void) {
|
|||
contentlength = outbuf.n;
|
||||
outbuf.p = 0;
|
||||
outbuf.n = 0;
|
||||
outbuf.c = 0;
|
||||
}
|
||||
|
||||
static void DropOutput(void) {
|
||||
free(outbuf.p);
|
||||
outbuf.p = 0;
|
||||
outbuf.n = 0;
|
||||
outbuf.c = 0;
|
||||
}
|
||||
|
||||
static void ClearOutput(void) {
|
||||
outbuf.n = 0;
|
||||
}
|
||||
|
||||
static void Grow(size_t n) {
|
||||
do {
|
||||
if (outbuf.c) {
|
||||
outbuf.c += outbuf.c >> 1;
|
||||
} else {
|
||||
outbuf.c = 16 * 1024;
|
||||
}
|
||||
} while (n > outbuf.c);
|
||||
outbuf.p = xrealloc(outbuf.p, outbuf.c);
|
||||
}
|
||||
|
||||
static void AppendData(const char *data, size_t size) {
|
||||
outbuf.p = xrealloc(outbuf.p, outbuf.n + size);
|
||||
size_t n;
|
||||
n = outbuf.n + size;
|
||||
if (n > outbuf.c) Grow(n);
|
||||
memcpy(outbuf.p + outbuf.n, data, size);
|
||||
outbuf.n += size;
|
||||
outbuf.n = n;
|
||||
}
|
||||
|
||||
static void AppendString(const char *s) {
|
||||
AppendData(s, strlen(s));
|
||||
}
|
||||
|
||||
static void AppendFmt(const char *fmt, ...) {
|
||||
static void Append(const char *fmt, ...) {
|
||||
int n;
|
||||
char *p;
|
||||
va_list va;
|
||||
va_list va, vb;
|
||||
va_start(va, fmt);
|
||||
n = vasprintf(&p, fmt, va);
|
||||
va_copy(vb, va);
|
||||
n = vsnprintf(outbuf.p + outbuf.n, outbuf.c - outbuf.n, fmt, va);
|
||||
if (n >= outbuf.c - outbuf.n) {
|
||||
Grow(outbuf.n + n + 1);
|
||||
vsnprintf(outbuf.p + outbuf.n, outbuf.c - outbuf.n, fmt, vb);
|
||||
}
|
||||
va_end(vb);
|
||||
va_end(va);
|
||||
CHECK_NE(-1, n);
|
||||
AppendData(p, n);
|
||||
free(p);
|
||||
outbuf.n += n;
|
||||
}
|
||||
|
||||
static char *MergePaths(const char *p, size_t n, const char *q, size_t m,
|
||||
|
@ -833,10 +856,6 @@ static void DescribeAddress(char buf[32], uint32_t addr, uint16_t port) {
|
|||
*p++ = '\0';
|
||||
}
|
||||
|
||||
static bool HasHeader(int h) {
|
||||
return !!msg.headers[h].a;
|
||||
}
|
||||
|
||||
static void GetServerAddr(uint32_t *ip, uint16_t *port) {
|
||||
*ip = ntohl(serveraddr.sin_addr.s_addr);
|
||||
if (port) *port = ntohs(serveraddr.sin_port);
|
||||
|
@ -975,7 +994,7 @@ static void ProgramHeader(const char *s) {
|
|||
|
||||
static void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "azhdugvmbl:p:r:R:H:c:L:P:U:G:B:D:t:")) !=
|
||||
while ((opt = getopt(argc, argv, "azhdugvmbfl:p:r:R:H:c:L:P:U:G:B:D:t:")) !=
|
||||
-1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
|
@ -1002,6 +1021,9 @@ static void GetOpts(int argc, char *argv[]) {
|
|||
case 'z':
|
||||
printport = true;
|
||||
break;
|
||||
case 'f':
|
||||
funtrace = true;
|
||||
break;
|
||||
case 'k':
|
||||
encouragekeepalive = true;
|
||||
break;
|
||||
|
@ -1097,53 +1119,53 @@ static void AppendResourceReport(struct rusage *ru, const char *nl) {
|
|||
long utime, stime;
|
||||
long double ticks;
|
||||
if (ru->ru_maxrss) {
|
||||
AppendFmt("ballooned to %,ldkb in size%s", ru->ru_maxrss, nl);
|
||||
Append("ballooned to %,ldkb in size%s", ru->ru_maxrss, nl);
|
||||
}
|
||||
if ((utime = ru->ru_utime.tv_sec * 1000000 + ru->ru_utime.tv_usec) |
|
||||
(stime = ru->ru_stime.tv_sec * 1000000 + ru->ru_stime.tv_usec)) {
|
||||
ticks = ceill((long double)(utime + stime) / (1000000.L / CLK_TCK));
|
||||
AppendFmt("needed %,ldµs cpu (%d%% kernel)%s", utime + stime,
|
||||
(int)((long double)stime / (utime + stime) * 100), nl);
|
||||
Append("needed %,ldµs cpu (%d%% kernel)%s", utime + stime,
|
||||
(int)((long double)stime / (utime + stime) * 100), nl);
|
||||
if (ru->ru_idrss) {
|
||||
AppendFmt("needed %,ldkb memory on average%s",
|
||||
lroundl(ru->ru_idrss / ticks), nl);
|
||||
Append("needed %,ldkb memory on average%s", lroundl(ru->ru_idrss / ticks),
|
||||
nl);
|
||||
}
|
||||
if (ru->ru_isrss) {
|
||||
AppendFmt("needed %,ldkb stack on average%s",
|
||||
lroundl(ru->ru_isrss / ticks), nl);
|
||||
Append("needed %,ldkb stack on average%s", lroundl(ru->ru_isrss / ticks),
|
||||
nl);
|
||||
}
|
||||
if (ru->ru_ixrss) {
|
||||
AppendFmt("mapped %,ldkb shared on average%s",
|
||||
lroundl(ru->ru_ixrss / ticks), nl);
|
||||
Append("mapped %,ldkb shared on average%s", lroundl(ru->ru_ixrss / ticks),
|
||||
nl);
|
||||
}
|
||||
}
|
||||
if (ru->ru_minflt || ru->ru_majflt) {
|
||||
AppendFmt("caused %,ld page faults (%d%% memcpy)%s",
|
||||
ru->ru_minflt + ru->ru_majflt,
|
||||
(int)((long double)ru->ru_minflt /
|
||||
(ru->ru_minflt + ru->ru_majflt) * 100),
|
||||
nl);
|
||||
Append("caused %,ld page faults (%d%% memcpy)%s",
|
||||
ru->ru_minflt + ru->ru_majflt,
|
||||
(int)((long double)ru->ru_minflt / (ru->ru_minflt + ru->ru_majflt) *
|
||||
100),
|
||||
nl);
|
||||
}
|
||||
if (ru->ru_nvcsw + ru->ru_nivcsw > 1) {
|
||||
AppendFmt(
|
||||
Append(
|
||||
"%,ld context switches (%d%% consensual)%s",
|
||||
ru->ru_nvcsw + ru->ru_nivcsw,
|
||||
(int)((long double)ru->ru_nvcsw / (ru->ru_nvcsw + ru->ru_nivcsw) * 100),
|
||||
nl);
|
||||
}
|
||||
if (ru->ru_inblock || ru->ru_oublock) {
|
||||
AppendFmt("performed %,ld read and %,ld write i/o operations%s",
|
||||
ru->ru_inblock, ru->ru_oublock, nl);
|
||||
Append("performed %,ld read and %,ld write i/o operations%s",
|
||||
ru->ru_inblock, ru->ru_oublock, nl);
|
||||
}
|
||||
if (ru->ru_msgrcv || ru->ru_msgsnd) {
|
||||
AppendFmt("received %,ld message and sent %,ld%s", ru->ru_msgrcv,
|
||||
ru->ru_msgsnd, nl);
|
||||
Append("received %,ld message and sent %,ld%s", ru->ru_msgrcv,
|
||||
ru->ru_msgsnd, nl);
|
||||
}
|
||||
if (ru->ru_nsignals) {
|
||||
AppendFmt("received %,ld signals%s", ru->ru_nsignals, nl);
|
||||
Append("received %,ld signals%s", ru->ru_nsignals, nl);
|
||||
}
|
||||
if (ru->ru_nswap) {
|
||||
AppendFmt("got swapped %,ld times%s", ru->ru_nswap, nl);
|
||||
Append("got swapped %,ld times%s", ru->ru_nswap, nl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1237,7 +1259,7 @@ static void ReapZombies(void) {
|
|||
} while (!terminated);
|
||||
}
|
||||
|
||||
static ssize_t WritevAll(int fd, struct iovec *iov, int iovlen) {
|
||||
static inline ssize_t WritevAll(int fd, struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
size_t wrote;
|
||||
do {
|
||||
|
@ -1266,13 +1288,6 @@ static ssize_t WritevAll(int fd, struct iovec *iov, int iovlen) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t Hash(const void *data, size_t size) {
|
||||
uint32_t h;
|
||||
h = crc32c(0, data, size);
|
||||
if (!h) h = 1;
|
||||
return h;
|
||||
}
|
||||
|
||||
static bool ClientAcceptsGzip(void) {
|
||||
return msg.version >= 10 && /* RFC1945 § 3.5 */
|
||||
HeaderHas(&msg, inbuf.p, kHttpAcceptEncoding, "gzip", 4);
|
||||
|
@ -1453,23 +1468,16 @@ static struct Asset *GetAsset(const char *path, size_t pathlen) {
|
|||
struct Asset *a;
|
||||
if (!(a = GetAssetFile(path, pathlen))) {
|
||||
if (!(a = GetAssetZip(path, pathlen))) {
|
||||
if (pathlen > 1 && path[pathlen - 1] != '/') {
|
||||
path2 = xmalloc(pathlen + 1);
|
||||
memcpy(mempcpy(path2, path, pathlen), "/", 1);
|
||||
a = GetAssetZip(path2, pathlen + 1);
|
||||
free(path2);
|
||||
if (pathlen > 1 && path[pathlen - 1] != '/' &&
|
||||
pathlen + 1 <= sizeof(slashpath)) {
|
||||
memcpy(mempcpy(slashpath, path, pathlen), "/", 1);
|
||||
a = GetAssetZip(slashpath, pathlen + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static char *AppendCrlf(char *p) {
|
||||
p[0] = '\r';
|
||||
p[1] = '\n';
|
||||
return p + 2;
|
||||
}
|
||||
|
||||
static bool MustNotIncludeMessageBody(void) { /* RFC2616 § 4.4 */
|
||||
return msg.method == kHttpHead || (100 <= statuscode && statuscode <= 199) ||
|
||||
statuscode == 204 || statuscode == 304;
|
||||
|
@ -1523,19 +1531,9 @@ static char *AppendCache(char *p, int64_t seconds) {
|
|||
return AppendExpires(p, (int64_t)shared->nowish + seconds);
|
||||
}
|
||||
|
||||
static bool IsPublic(void) {
|
||||
uint32_t ip;
|
||||
GetRemoteAddr(&ip, 0);
|
||||
return IsPublicIp(ip);
|
||||
}
|
||||
|
||||
static char *AppendServer(char *p, const char *s) {
|
||||
p = stpcpy(p, "Server: ");
|
||||
if (IsPublic()) {
|
||||
p = mempcpy(p, s, strchrnul(s, '/') - s);
|
||||
} else {
|
||||
p = stpcpy(p, s);
|
||||
}
|
||||
p = stpcpy(p, s);
|
||||
return AppendCrlf(p);
|
||||
}
|
||||
|
||||
|
@ -1658,15 +1656,15 @@ static void AppendLogo(void) {
|
|||
struct Asset *a;
|
||||
if ((a = GetAsset("/redbean.png", 12)) && (p = LoadAsset(a, &n))) {
|
||||
q = EncodeBase64(p, n, &n);
|
||||
AppendString("<img src=\"data:image/png;base64,");
|
||||
Append("<img src=\"data:image/png;base64,");
|
||||
AppendData(q, n);
|
||||
AppendString("\">\r\n");
|
||||
Append("\">\r\n");
|
||||
free(q);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t Send(struct iovec *iov, int iovlen) {
|
||||
static inline ssize_t Send(struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
if ((rc = WritevAll(client, iov, iovlen)) == -1) {
|
||||
if (errno == ECONNRESET) {
|
||||
|
@ -1711,11 +1709,11 @@ static char *CommitOutput(char *p) {
|
|||
static char *ServeDefaultErrorPage(char *p, unsigned code, const char *reason) {
|
||||
p = AppendContentType(p, "text/html; charset=ISO-8859-1");
|
||||
reason = FreeLater(EscapeHtml(reason, -1, 0));
|
||||
AppendString("\
|
||||
Append("\
|
||||
<!doctype html>\r\n\
|
||||
<title>");
|
||||
AppendFmt("%d %s", code, reason);
|
||||
AppendString("\
|
||||
Append("%d %s", code, reason);
|
||||
Append("\
|
||||
</title>\r\n\
|
||||
<style>\r\n\
|
||||
html { color: #111; font-family: sans-serif; }\r\n\
|
||||
|
@ -1723,8 +1721,8 @@ img { vertical-align: middle; }\r\n\
|
|||
</style>\r\n\
|
||||
<h1>\r\n");
|
||||
AppendLogo();
|
||||
AppendFmt("%d %s\r\n", code, reason);
|
||||
AppendString("</h1>\r\n");
|
||||
Append("%d %s\r\n", code, reason);
|
||||
Append("</h1>\r\n");
|
||||
UseOutput();
|
||||
return p;
|
||||
}
|
||||
|
@ -1734,7 +1732,7 @@ static char *ServeErrorImpl(unsigned code, const char *reason) {
|
|||
char *p, *s;
|
||||
struct Asset *a;
|
||||
LockInc(&shared->errors);
|
||||
DropOutput();
|
||||
ClearOutput();
|
||||
p = SetStatus(code, reason);
|
||||
s = xasprintf("/%d.html", code);
|
||||
a = GetAsset(s, strlen(s));
|
||||
|
@ -1877,7 +1875,15 @@ static char *ServeAsset(struct Asset *a, const char *path, size_t pathlen) {
|
|||
} else {
|
||||
LockInc(&shared->openfails);
|
||||
WARNF("open(%`'s) failed %s", a->file->path, strerror(errno));
|
||||
return ServeError(500, "Internal Server Error");
|
||||
if (errno == ENFILE) {
|
||||
LockInc(&shared->enfiles);
|
||||
return ServeError(503, "Service Unavailable");
|
||||
} else if (errno == EMFILE) {
|
||||
LockInc(&shared->emfiles);
|
||||
return ServeError(503, "Service Unavailable");
|
||||
} else {
|
||||
return ServeError(500, "Internal Server Error");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
content = "";
|
||||
|
@ -3320,30 +3326,27 @@ static char *HandleRedirect(struct Redirect *r) {
|
|||
static void LogMessage(const char *d, const char *s, size_t n) {
|
||||
size_t n2, n3;
|
||||
char *s2, *s3;
|
||||
if (logmessages) {
|
||||
while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n;
|
||||
if ((s2 = DecodeLatin1(s, n, &n2))) {
|
||||
if ((s3 = IndentLines(s2, n2, &n3, 1))) {
|
||||
LOGF("%s %,ld byte message\n%.*s", d, n, n3, s3);
|
||||
free(s3);
|
||||
}
|
||||
free(s2);
|
||||
while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n;
|
||||
if ((s2 = DecodeLatin1(s, n, &n2))) {
|
||||
if ((s3 = IndentLines(s2, n2, &n3, 1))) {
|
||||
LOGF("%s %,ld byte message\n%.*s", d, n, n3, s3);
|
||||
free(s3);
|
||||
}
|
||||
free(s2);
|
||||
}
|
||||
}
|
||||
|
||||
static void LogBody(const char *d, const char *s, size_t n) {
|
||||
char *s2, *s3;
|
||||
size_t n2, n3;
|
||||
if (n && logbodies) {
|
||||
while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n;
|
||||
if ((s2 = VisualizeControlCodes(s, n, &n2))) {
|
||||
if ((s3 = IndentLines(s2, n2, &n3, 1))) {
|
||||
LOGF("%s %,ld byte payload\n%.*s", d, n, n3, s3);
|
||||
free(s3);
|
||||
}
|
||||
free(s2);
|
||||
if (!n) return;
|
||||
while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n;
|
||||
if ((s2 = VisualizeControlCodes(s, n, &n2))) {
|
||||
if ((s3 = IndentLines(s2, n2, &n3, 1))) {
|
||||
LOGF("%s %,ld byte payload\n%.*s", d, n, n3, s3);
|
||||
free(s3);
|
||||
}
|
||||
free(s2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3351,7 +3354,7 @@ static ssize_t SendString(const char *s) {
|
|||
size_t n;
|
||||
ssize_t rc;
|
||||
n = strlen(s);
|
||||
LogMessage("sending", s, n);
|
||||
if (logmessages) LogMessage("sending", s, n);
|
||||
for (;;) {
|
||||
if ((rc = write(client, s, n)) != -1 || errno != EINTR) {
|
||||
return rc;
|
||||
|
@ -3522,11 +3525,11 @@ static const char *MergeNames(const char *a, const char *b) {
|
|||
}
|
||||
|
||||
static void AppendLong1(const char *a, long x) {
|
||||
if (x) AppendFmt("%s: %ld\r\n", a, x);
|
||||
if (x) Append("%s: %ld\r\n", a, x);
|
||||
}
|
||||
|
||||
static void AppendLong2(const char *a, const char *b, long x) {
|
||||
if (x) AppendFmt("%s.%s: %ld\r\n", a, b, x);
|
||||
if (x) Append("%s.%s: %ld\r\n", a, b, x);
|
||||
}
|
||||
|
||||
static void AppendTimeval(const char *a, struct timeval *tv) {
|
||||
|
@ -3681,7 +3684,7 @@ char *ServeListing(void) {
|
|||
char rb[8], tb[64], *rp[6];
|
||||
size_t i, n, pathlen, rn[6];
|
||||
if (msg.method != kHttpGet && msg.method != kHttpHead) return BadMethod();
|
||||
AppendString("\
|
||||
Append("\
|
||||
<!doctype html>\r\n\
|
||||
<meta charset=\"utf-8\">\r\n\
|
||||
<title>redbean zip listing</title>\r\n\
|
||||
|
@ -3698,7 +3701,7 @@ td { padding-right: 3em; }\r\n\
|
|||
rp[0] = EscapeHtml(brand, -1, &rn[0]);
|
||||
AppendData(rp[0], rn[0]);
|
||||
free(rp[0]);
|
||||
AppendString("</h1><hr></header><pre>\r\n");
|
||||
Append("</h1><hr></header><pre>\r\n");
|
||||
memset(w, 0, sizeof(w));
|
||||
n = GetZipCdirRecords(cdir);
|
||||
for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
|
||||
|
@ -3733,15 +3736,15 @@ td { padding-right: 3em; }\r\n\
|
|||
if (IsCompressionMethodSupported(
|
||||
ZIP_LFILE_COMPRESSIONMETHOD(zmap + lf)) &&
|
||||
IsAcceptablePath(path, pathlen)) {
|
||||
AppendFmt("<a href=\"%.*s\">%-*.*s</a> %s %0*o %4s %,*ld %'s\r\n",
|
||||
rn[2], rp[2], w[0], rn[4], rp[4], tb, w[1],
|
||||
GetZipCfileMode(zmap + cf), DescribeCompressionRatio(rb, lf),
|
||||
w[2], GetZipLfileUncompressedSize(zmap + lf), rp[5]);
|
||||
Append("<a href=\"%.*s\">%-*.*s</a> %s %0*o %4s %,*ld %'s\r\n",
|
||||
rn[2], rp[2], w[0], rn[4], rp[4], tb, w[1],
|
||||
GetZipCfileMode(zmap + cf), DescribeCompressionRatio(rb, lf),
|
||||
w[2], GetZipLfileUncompressedSize(zmap + lf), rp[5]);
|
||||
} else {
|
||||
AppendFmt("%-*.*s %s %0*o %4s %,*ld %'s\r\n", w[0], rn[4], rp[4], tb,
|
||||
w[1], GetZipCfileMode(zmap + cf),
|
||||
DescribeCompressionRatio(rb, lf), w[2],
|
||||
GetZipLfileUncompressedSize(zmap + lf), rp[5]);
|
||||
Append("%-*.*s %s %0*o %4s %,*ld %'s\r\n", w[0], rn[4], rp[4], tb,
|
||||
w[1], GetZipCfileMode(zmap + cf),
|
||||
DescribeCompressionRatio(rb, lf), w[2],
|
||||
GetZipLfileUncompressedSize(zmap + lf), rp[5]);
|
||||
}
|
||||
free(rp[5]);
|
||||
free(rp[4]);
|
||||
|
@ -3752,38 +3755,38 @@ td { padding-right: 3em; }\r\n\
|
|||
}
|
||||
free(path);
|
||||
}
|
||||
AppendString("</pre><footer><hr>\r\n");
|
||||
AppendString("<table border=\"0\"><tr><td valign=\"top\">\r\n");
|
||||
AppendString("<a href=\"/statusz\">/statusz</a> says your redbean<br>\r\n");
|
||||
Append("</pre><footer><hr>\r\n");
|
||||
Append("<table border=\"0\"><tr><td valign=\"top\">\r\n");
|
||||
Append("<a href=\"/statusz\">/statusz</a> says your redbean<br>\r\n");
|
||||
AppendResourceReport(&shared->children, "<br>\r\n");
|
||||
AppendString("<td valign=\"top\">\r\n");
|
||||
Append("<td valign=\"top\">\r\n");
|
||||
and = "";
|
||||
x = nowl() - startserver;
|
||||
y = ldiv(x, 24L * 60 * 60);
|
||||
if (y.quot) {
|
||||
AppendFmt("%,ld day%s ", y.quot, y.quot == 1 ? "" : "s");
|
||||
Append("%,ld day%s ", y.quot, y.quot == 1 ? "" : "s");
|
||||
and = "and ";
|
||||
}
|
||||
y = ldiv(y.rem, 60 * 60);
|
||||
if (y.quot) {
|
||||
AppendFmt("%,ld hour%s ", y.quot, y.quot == 1 ? "" : "s");
|
||||
Append("%,ld hour%s ", y.quot, y.quot == 1 ? "" : "s");
|
||||
and = "and ";
|
||||
}
|
||||
y = ldiv(y.rem, 60);
|
||||
if (y.quot) {
|
||||
AppendFmt("%,ld minute%s ", y.quot, y.quot == 1 ? "" : "s");
|
||||
Append("%,ld minute%s ", y.quot, y.quot == 1 ? "" : "s");
|
||||
and = "and ";
|
||||
}
|
||||
AppendFmt("%s%,ld second%s of operation<br>\r\n", and, y.rem,
|
||||
y.rem == 1 ? "" : "s");
|
||||
Append("%s%,ld second%s of operation<br>\r\n", and, y.rem,
|
||||
y.rem == 1 ? "" : "s");
|
||||
x = shared->messageshandled;
|
||||
AppendFmt("%,ld message%s handled<br>\r\n", x, x == 1 ? "" : "s");
|
||||
Append("%,ld message%s handled<br>\r\n", x, x == 1 ? "" : "s");
|
||||
x = shared->connectionshandled;
|
||||
AppendFmt("%,ld connection%s handled<br>\r\n", x, x == 1 ? "" : "s");
|
||||
Append("%,ld connection%s handled<br>\r\n", x, x == 1 ? "" : "s");
|
||||
x = shared->workers;
|
||||
AppendFmt("%,ld connection%s active<br>\r\n", x, x == 1 ? "" : "s");
|
||||
AppendString("</table>\r\n");
|
||||
AppendString("</footer>\r\n");
|
||||
Append("%,ld connection%s active<br>\r\n", x, x == 1 ? "" : "s");
|
||||
Append("</table>\r\n");
|
||||
Append("</footer>\r\n");
|
||||
p = SetStatus(200, "OK");
|
||||
p = AppendContentType(p, "text/html");
|
||||
p = AppendCache(p, 0);
|
||||
|
@ -4014,7 +4017,7 @@ static char *HandleRequest(void) {
|
|||
return ServeFailure(505, "HTTP Version Not Supported");
|
||||
}
|
||||
if ((p = SynchronizeStream())) return p;
|
||||
LogBody("received", inbuf.p + hdrsize, msgsize - hdrsize);
|
||||
if (logbodies) LogBody("received", inbuf.p + hdrsize, msgsize - hdrsize);
|
||||
if (msg.version < 11 || HeaderEqualCase(kHttpConnection, "close")) {
|
||||
connectionclose = true;
|
||||
}
|
||||
|
@ -4072,10 +4075,11 @@ static bool HandleMessage(void) {
|
|||
char *p, *s;
|
||||
struct iovec iov[4];
|
||||
long actualcontentlength;
|
||||
g_syscount = 0;
|
||||
if ((rc = ParseHttpRequest(&msg, inbuf.p, amtread)) != -1) {
|
||||
if (!rc) return false;
|
||||
hdrsize = rc;
|
||||
LogMessage("received", inbuf.p, hdrsize);
|
||||
if (logmessages) LogMessage("received", inbuf.p, hdrsize);
|
||||
RecordNetworkOrigin();
|
||||
p = HandleRequest();
|
||||
} else {
|
||||
|
@ -4091,12 +4095,12 @@ static bool HandleMessage(void) {
|
|||
LockInc(&shared->synchronizationfailures);
|
||||
DEBUGF("could not synchronize message stream");
|
||||
}
|
||||
if (connectionclose) {
|
||||
if (0 && connectionclose) {
|
||||
LockInc(&shared->shutdowns);
|
||||
shutdown(client, SHUT_RD);
|
||||
}
|
||||
if (msg.version >= 10) {
|
||||
p = AppendHeader(p, "Date", shared->currentdate);
|
||||
p = AppendCrlf(stpcpy(stpcpy(p, "Date: "), shared->currentdate));
|
||||
if (!branded) p = AppendServer(p, serverheader);
|
||||
if (extrahdrs) p = stpcpy(p, extrahdrs);
|
||||
if (connectionclose) {
|
||||
|
@ -4112,7 +4116,7 @@ static bool HandleMessage(void) {
|
|||
p = AppendContentLength(p, actualcontentlength);
|
||||
p = AppendCrlf(p);
|
||||
CHECK_LE(p - hdrbuf.p, hdrbuf.n);
|
||||
LogMessage("sending", hdrbuf.p, p - hdrbuf.p);
|
||||
if (logmessages) LogMessage("sending", hdrbuf.p, p - hdrbuf.p);
|
||||
iov[0].iov_base = hdrbuf.p;
|
||||
iov[0].iov_len = p - hdrbuf.p;
|
||||
iovlen = 1;
|
||||
|
@ -4137,7 +4141,7 @@ static bool HandleMessage(void) {
|
|||
iovlen = 1;
|
||||
}
|
||||
if (loglatency || LOGGABLE(kLogDebug)) {
|
||||
flogf(kLogDebug, __FILE__, __LINE__, NULL, "%`'.*s handled in %,ldµs",
|
||||
flogf(kLogDebug, __FILE__, __LINE__, NULL, "%`'.*s latency %,ldµs",
|
||||
msg.uri.b - msg.uri.a, inbuf.p + msg.uri.a,
|
||||
(long)((nowl() - startrequest) * 1e6L));
|
||||
}
|
||||
|
@ -4150,6 +4154,7 @@ static bool HandleMessage(void) {
|
|||
static void InitRequest(void) {
|
||||
frags = 0;
|
||||
msgsize = 0;
|
||||
outbuf.n = 0;
|
||||
content = NULL;
|
||||
gzipped = false;
|
||||
branded = false;
|
||||
|
@ -4272,10 +4277,13 @@ static void HandleConnection(void) {
|
|||
case 0:
|
||||
meltdown = false;
|
||||
connectionclose = false;
|
||||
if (funtrace && !IsTiny()) {
|
||||
ftrace_install();
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
FATALF("%s too many processes %s", DescribeServer(), strerror(errno));
|
||||
LockInc(&shared->forkerrors);
|
||||
++shared->forkerrors;
|
||||
LockInc(&shared->dropped);
|
||||
EnterMeltdownMode();
|
||||
SendServiceUnavailable();
|
||||
|
@ -4292,8 +4300,7 @@ static void HandleConnection(void) {
|
|||
HandleMessages();
|
||||
DEBUGF("%s closing after %,ldµs", DescribeClient(),
|
||||
(long)((nowl() - startconnection) * 1e6L));
|
||||
if (close(client) != -1) {
|
||||
} else {
|
||||
if (close(client) == -1) {
|
||||
LockInc(&shared->closeerrors);
|
||||
WARNF("%s close failed", DescribeClient());
|
||||
}
|
||||
|
@ -4303,7 +4310,7 @@ static void HandleConnection(void) {
|
|||
CollectGarbage();
|
||||
}
|
||||
} else if (errno == EINTR || errno == EAGAIN) {
|
||||
LockInc(&shared->acceptinterrupts);
|
||||
++shared->acceptinterrupts;
|
||||
} else if (errno == ENFILE) {
|
||||
LockInc(&shared->enfiles);
|
||||
WARNF("%s too many open files", DescribeServer());
|
||||
|
@ -4321,19 +4328,19 @@ static void HandleConnection(void) {
|
|||
WARNF("%s ran out of buffer");
|
||||
EnterMeltdownMode();
|
||||
} else if (errno == ENONET) {
|
||||
LockInc(&shared->enonets);
|
||||
++shared->enonets;
|
||||
WARNF("%s network gone", DescribeServer());
|
||||
sleep(1);
|
||||
} else if (errno == ENETDOWN) {
|
||||
LockInc(&shared->enetdowns);
|
||||
++shared->enetdowns;
|
||||
WARNF("%s network down", DescribeServer());
|
||||
sleep(1);
|
||||
} else if (errno == ECONNABORTED) {
|
||||
LockInc(&shared->acceptresets);
|
||||
++shared->acceptresets;
|
||||
WARNF("%s connection reset before accept");
|
||||
} else if (errno == ENETUNREACH || errno == EHOSTUNREACH ||
|
||||
errno == EOPNOTSUPP || errno == ENOPROTOOPT || errno == EPROTO) {
|
||||
LockInc(&shared->accepterrors);
|
||||
++shared->accepterrors;
|
||||
WARNF("%s ephemeral accept error %s", DescribeServer(), strerror(errno));
|
||||
} else {
|
||||
FATALF("%s accept error %s", DescribeServer(), strerror(errno));
|
||||
|
@ -4408,8 +4415,8 @@ void RedBean(int argc, char *argv[], const char *prog) {
|
|||
if (setitimer(ITIMER_REAL, &kHeartbeat, NULL) == -1) {
|
||||
heartless = true;
|
||||
}
|
||||
CHECK_NE(-1,
|
||||
(server = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP)));
|
||||
server = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
|
||||
CHECK_NE(-1, server);
|
||||
TuneSockets();
|
||||
if (bind(server, &serveraddr, sizeof(serveraddr)) == -1) {
|
||||
if (errno == EADDRINUSE) {
|
||||
|
@ -4473,7 +4480,7 @@ void RedBean(int argc, char *argv[], const char *prog) {
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
setenv("GDB", "", true);
|
||||
showcrashreports();
|
||||
if (!IsTiny()) showcrashreports();
|
||||
RedBean(argc, argv, (const char *)getauxval(AT_EXECFN));
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue