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

View file

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