code: plan9front

Download patch

ref: b0ad72be22c9125e674d53bc7f9c086cd7c1ac83
parent: fc6d319a3fc26e3a8335cbe61764ce5c67580a3e
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Sep 25 21:54:03 EDT 2023

upas/fs: write index out to temp file

pridx() can be extremely slow when reading from
imap, because it ensures each message is cached.
Ensuring each message is cached may take a round
trip to the IMAP server.

Instead, we should write the index to a temp file,
and rename it, to reduce the window wher the index
can be broken.

--- a/sys/src/cmd/upas/fs/idx.c
+++ b/sys/src/cmd/upas/fs/idx.c
@@ -240,12 +240,12 @@
 int
 wridxfile(Mailbox *mb)
 {
-	char buf[Pathlen + 4];
+	char *p, buf[Pathlen + 32];
 	int r, fd;
 	Biobuf b;
-	Dir *d;
+	Dir *d, n;
 
-	snprint(buf, sizeof buf, "%s.idx", mb->path);
+	snprint(buf, sizeof buf, "%s.idx.tmp", mb->path);
 	iprint("wridxfile %s\n", buf);
 	if((fd = exopen(buf)) == -1){
 		rerrstr(buf, sizeof buf);
@@ -258,8 +258,21 @@
 	Binit(&b, fd, OWRITE);
 	r = pridx(&b, mb);
 	Bterm(&b);
+
+	/* remove and rename over the old index */
+	snprint(buf, sizeof buf, "%s.idx", mb->path);
+	remove(buf);
+
+	if((p = strrchr(mb->path, '/')) == nil)
+		sysfatal("index path is directory");
+	snprint(buf, sizeof buf, "%s.idx", p+1);
+	nulldir(&n);
+	n.name = buf;
+	if(dirfwstat(fd, &n) == -1)
+		sysfatal("dirfwstat: %r");
+
 	d = dirfstat(fd);
-	if(d == 0)
+	if(d == nil)
 		sysfatal("dirfstat: %r");
 	mb->qid = d->qid;
 	free(d);