Add live reindexing to redbean when zip changes

This commit is contained in:
Justine Tunney 2021-05-02 11:50:43 -07:00
parent 84001a246c
commit daa32d27d4
2 changed files with 68 additions and 31 deletions

View file

@ -40,9 +40,7 @@ OpenExecutable:
pushq MAP_ANONYMOUS(%rip) # -0x28(%rbp) pushq MAP_ANONYMOUS(%rip) # -0x28(%rbp)
pushq MAP_PRIVATE(%rip) # -0x30(%rbp) pushq MAP_PRIVATE(%rip) # -0x30(%rbp)
pushq MAP_FIXED(%rip) # -0x38(%rbp) pushq MAP_FIXED(%rip) # -0x38(%rbp)
pushq MAP_SHARED(%rip) # -0x40(%rbp) pushq __NR_mprotect(%rip) # -0x40(%rbp)
pushq __NR_mprotect(%rip) # -0x48(%rbp)
pushq __NR_mprotect(%rip) # -0x50(%rbp)
push %rbx # code buffer push %rbx # code buffer
push %r12 # data buffer push %r12 # data buffer
push %r14 # filename push %r14 # filename
@ -98,7 +96,7 @@ OpenExecutable:
rep movsb rep movsb
// Change protection. // Change protection.
mov -0x48(%rbp),%eax # __NR_mprotect mov -0x40(%rbp),%eax # __NR_mprotect
mov %rbx,%rdi mov %rbx,%rdi
mov $PAGESIZE,%esi mov $PAGESIZE,%esi
mov $PROT_READ|PROT_EXEC,%edx mov $PROT_READ|PROT_EXEC,%edx
@ -133,7 +131,7 @@ OpenExecutable:
mov $ape_rom_filesz,%esi mov $ape_rom_filesz,%esi
mov $PROT_READ|PROT_EXEC,%edx mov $PROT_READ|PROT_EXEC,%edx
mov -0x38(%rbp),%r10d # MAP_FIXED mov -0x38(%rbp),%r10d # MAP_FIXED
or -0x40(%rbp),%r10d # MAP_SHARED or -0x30(%rbp),%r10d # MAP_PRIVATE
mov %r15d,%r8d mov %r15d,%r8d
mov $ape_rom_offset,%r9d mov $ape_rom_offset,%r9d
push %r9 # openbsd:pad push %r9 # openbsd:pad

View file

@ -241,6 +241,7 @@ static struct Assets {
static struct Shared { static struct Shared {
int workers; int workers;
long double nowish; long double nowish;
long double lastreindex;
long double lastmeltdown; long double lastmeltdown;
char currentdate[32]; char currentdate[32];
struct rusage server; struct rusage server;
@ -318,6 +319,7 @@ static struct Shared {
long readresets; long readresets;
long readtimeouts; long readtimeouts;
long redirects; long redirects;
long reindexes;
long reloads; long reloads;
long rewrites; long rewrites;
long serveroptions; long serveroptions;
@ -379,13 +381,14 @@ static uint32_t clientaddrsize;
static lua_State *L; static lua_State *L;
static size_t zsize; static size_t zsize;
static char *content; static char *content;
static uint8_t *cdir;
static uint8_t *zmap; static uint8_t *zmap;
static uint8_t *zcdir;
static size_t hdrsize; static size_t hdrsize;
static size_t msgsize; static size_t msgsize;
static size_t amtread; static size_t amtread;
static char *extrahdrs; static char *extrahdrs;
static char *luaheaderp; static char *luaheaderp;
static const char *zpath;
static const char *brand; static const char *brand;
static const char *pidpath; static const char *pidpath;
static const char *logpath; static const char *logpath;
@ -408,6 +411,7 @@ static struct Url url;
static struct HttpRequest msg; static struct HttpRequest msg;
static char slashpath[PATH_MAX]; static char slashpath[PATH_MAX];
static struct stat zst;
static long double startread; static long double startread;
static long double lastrefresh; static long double lastrefresh;
static long double startserver; static long double startserver;
@ -1415,12 +1419,12 @@ static void IndexAssets(void) {
struct Asset *p; struct Asset *p;
uint32_t i, n, m, step, hash; uint32_t i, n, m, step, hash;
CHECK_GE(HASH_LOAD_FACTOR, 2); CHECK_GE(HASH_LOAD_FACTOR, 2);
CHECK(READ32LE(cdir) == kZipCdir64HdrMagic || CHECK(READ32LE(zcdir) == kZipCdir64HdrMagic ||
READ32LE(cdir) == kZipCdirHdrMagic); READ32LE(zcdir) == kZipCdirHdrMagic);
n = GetZipCdirRecords(cdir); n = GetZipCdirRecords(zcdir);
m = roundup2pow(MAX(1, n) * HASH_LOAD_FACTOR); m = roundup2pow(MAX(1, n) * HASH_LOAD_FACTOR);
p = xcalloc(m, sizeof(struct Asset)); p = xcalloc(m, sizeof(struct Asset));
for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { for (cf = GetZipCdirOffset(zcdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf)); CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf));
lf = GetZipCfileOffset(zmap + cf); lf = GetZipCfileOffset(zmap + cf);
if (!IsCompressionMethodSupported(ZIP_LFILE_COMPRESSIONMETHOD(zmap + lf))) { if (!IsCompressionMethodSupported(ZIP_LFILE_COMPRESSIONMETHOD(zmap + lf))) {
@ -1447,17 +1451,17 @@ static void IndexAssets(void) {
assets.n = m; assets.n = m;
} }
static void OpenZip(const char *path) { static void OpenZip(void) {
int fd; int fd;
uint8_t *p; uint8_t *p;
struct stat st; if (zmap) munmap(zmap, zsize);
CHECK_NE(-1, (fd = open(path, O_RDONLY))); CHECK_NE(-1, (fd = open(zpath, O_RDONLY)));
CHECK_NE(-1, fstat(fd, &st)); CHECK_NE(-1, fstat(fd, &zst));
CHECK((zsize = st.st_size)); CHECK((zsize = zst.st_size));
CHECK_NE(MAP_FAILED, CHECK_NE(MAP_FAILED,
(zmap = mmap(NULL, zsize, PROT_READ, MAP_SHARED, fd, 0))); (zmap = mmap(NULL, zsize, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_NOTNULL((cdir = GetZipCdir(zmap, zsize))); CHECK_NOTNULL((zcdir = GetZipCdir(zmap, zsize)));
if (endswith(path, ".com.dbg") && (p = memmem(zmap, zsize, "MZqFpD", 6))) { if (endswith(zpath, ".com.dbg") && (p = memmem(zmap, zsize, "MZqFpD", 6))) {
zsize -= p - zmap; zsize -= p - zmap;
zmap = p; zmap = p;
} }
@ -2080,11 +2084,11 @@ td { padding-right: 3em; }\r\n\
"<hr>\r\n" "<hr>\r\n"
"</header>\r\n" "</header>\r\n"
"<pre>\r\n", "<pre>\r\n",
strnlen(GetZipCdirComment(cdir), GetZipCdirCommentSize(cdir)), strnlen(GetZipCdirComment(zcdir), GetZipCdirCommentSize(zcdir)),
GetZipCdirComment(cdir)); GetZipCdirComment(zcdir));
memset(w, 0, sizeof(w)); memset(w, 0, sizeof(w));
n = GetZipCdirRecords(cdir); n = GetZipCdirRecords(zcdir);
for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { for (cf = GetZipCdirOffset(zcdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf)); CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf));
lf = GetZipCfileOffset(zmap + cf); lf = GetZipCfileOffset(zmap + cf);
path = GetAssetPath(cf, &pathlen); path = GetAssetPath(cf, &pathlen);
@ -2095,8 +2099,8 @@ td { padding-right: 3em; }\r\n\
} }
free(path); free(path);
} }
n = GetZipCdirRecords(cdir); n = GetZipCdirRecords(zcdir);
for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { for (cf = GetZipCdirOffset(zcdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf)); CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf));
lf = GetZipCfileOffset(zmap + cf); lf = GetZipCfileOffset(zmap + cf);
path = GetAssetPath(cf, &pathlen); path = GetAssetPath(cf, &pathlen);
@ -2299,6 +2303,7 @@ static char *ServeStatusz(void) {
AppendLong1("readresets", shared->readresets); AppendLong1("readresets", shared->readresets);
AppendLong1("readtimeouts", shared->readtimeouts); AppendLong1("readtimeouts", shared->readtimeouts);
AppendLong1("redirects", shared->redirects); AppendLong1("redirects", shared->redirects);
AppendLong1("reindexes", shared->reindexes);
AppendLong1("reloads", shared->reloads); AppendLong1("reloads", shared->reloads);
AppendLong1("rewrites", shared->rewrites); AppendLong1("rewrites", shared->rewrites);
AppendLong1("serveroptions", shared->serveroptions); AppendLong1("serveroptions", shared->serveroptions);
@ -2507,6 +2512,13 @@ static char *Route(const char *host, size_t hostlen, const char *path,
} }
} }
static void Reindex(void) {
LockInc(&shared->reindexes);
LOGF("reindexing");
OpenZip();
IndexAssets();
}
static const char *LuaCheckPath(lua_State *L, int idx, size_t *pathlen) { static const char *LuaCheckPath(lua_State *L, int idx, size_t *pathlen) {
const char *path; const char *path;
if (lua_isnoneornil(L, idx)) { if (lua_isnoneornil(L, idx)) {
@ -3446,8 +3458,8 @@ static int LuaGetZipPaths(lua_State *L) {
size_t i, n, pathlen; size_t i, n, pathlen;
lua_newtable(L); lua_newtable(L);
i = 0; i = 0;
n = GetZipCdirRecords(cdir); n = GetZipCdirRecords(zcdir);
for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { for (cf = GetZipCdirOffset(zcdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf)); CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf));
path = GetAssetPath(cf, &pathlen); path = GetAssetPath(cf, &pathlen);
lua_pushlstring(L, path, pathlen); lua_pushlstring(L, path, pathlen);
@ -3847,13 +3859,31 @@ static void LuaReload(void) {
} }
static void HandleReload(void) { static void HandleReload(void) {
LockInc(&shared->reloads);
LOGF("reloading"); LOGF("reloading");
Reindex();
LuaReload(); LuaReload();
} }
static bool ZipCdirChanged(void) {
struct stat st;
if (!IsZipCdir32(zmap, zsize, zcdir - zmap) &&
!IsZipCdir64(zmap, zsize, zcdir - zmap)) {
return true;
}
if (stat(zpath, &st) != -1 && st.st_ino != zst.st_ino) {
return true;
}
return false;
}
static void HandleHeartbeat(void) { static void HandleHeartbeat(void) {
if (nowl() - lastrefresh > 60 * 60) RefreshTime(); if (nowl() - lastrefresh > 60 * 60) RefreshTime();
UpdateCurrentDate(nowl()); UpdateCurrentDate(nowl());
if (ZipCdirChanged()) {
shared->lastreindex = nowl();
kill(0, SIGUSR1);
}
getrusage(RUSAGE_SELF, &shared->server); getrusage(RUSAGE_SELF, &shared->server);
#ifndef STATIC #ifndef STATIC
LuaRun("/.heartbeat.lua"); LuaRun("/.heartbeat.lua");
@ -4344,6 +4374,10 @@ static void HandleMessages(void) {
LogClose(DescribeClose()); LogClose(DescribeClose());
return; return;
} }
if (invalidated) {
HandleReload();
invalidated = false;
}
} }
if (msgsize == amtread) { if (msgsize == amtread) {
amtread = 0; amtread = 0;
@ -4363,6 +4397,10 @@ static void HandleMessages(void) {
} }
} }
CollectGarbage(); CollectGarbage();
if (invalidated) {
HandleReload();
invalidated = false;
}
} }
} }
@ -4485,7 +4523,7 @@ static void TuneSockets(void) {
setsockopt(server, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); setsockopt(server, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
} }
static void RestoreApe(const char *prog) { static void RestoreApe(void) {
char *p; char *p;
size_t n; size_t n;
struct Asset *a; struct Asset *a;
@ -4493,7 +4531,7 @@ static void RestoreApe(const char *prog) {
if (IsWindows()) return; /* TODO */ if (IsWindows()) return; /* TODO */
if (IsOpenbsd()) return; /* TODO */ if (IsOpenbsd()) return; /* TODO */
if (IsNetbsd()) return; /* TODO */ if (IsNetbsd()) return; /* TODO */
if (endswith(prog, ".com.dbg")) return; if (endswith(zpath, ".com.dbg")) return;
close(OpenExecutable()); close(OpenExecutable());
if ((a = GetAssetZip("/.ape", 5)) && (p = LoadAsset(a, &n))) { if ((a = GetAssetZip("/.ape", 5)) && (p = LoadAsset(a, &n))) {
mprotect(ape_rom_vaddr, PAGESIZE, PROT_READ | PROT_WRITE); mprotect(ape_rom_vaddr, PAGESIZE, PROT_READ | PROT_WRITE);
@ -4506,7 +4544,7 @@ static void RestoreApe(const char *prog) {
} }
} }
void RedBean(int argc, char *argv[], const char *prog) { void RedBean(int argc, char *argv[]) {
uint32_t addrsize; uint32_t addrsize;
gmtoff = GetGmtOffset((lastrefresh = startserver = nowl())); gmtoff = GetGmtOffset((lastrefresh = startserver = nowl()));
CHECK_GT(CLK_TCK, 0); CHECK_GT(CLK_TCK, 0);
@ -4514,9 +4552,10 @@ void RedBean(int argc, char *argv[], const char *prog) {
(shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE), (shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
-1, 0))); -1, 0)));
OpenZip(prog); zpath = (const char *)getauxval(AT_EXECFN);
OpenZip();
IndexAssets(); IndexAssets();
RestoreApe(prog); RestoreApe();
SetDefaults(); SetDefaults();
GetOpts(argc, argv); GetOpts(argc, argv);
LuaInit(); LuaInit();
@ -4603,6 +4642,6 @@ int main(int argc, char *argv[]) {
setenv("GDB", "", true); setenv("GDB", "", true);
showcrashreports(); showcrashreports();
} }
RedBean(argc, argv, (const char *)getauxval(AT_EXECFN)); RedBean(argc, argv);
return 0; return 0;
} }