about summary refs log tree commit diff
path: root/concat.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2021-06-12 19:20:47 -0400
committerJune McEnroe <june@causal.agency>2021-06-12 19:20:47 -0400
commit9b09a5ff483aef05dc5b4d9ab0fd0243d21cb1d3 (patch)
tree2a2be7ddda0e4161833e0e35cdf8585aa8016fc7 /concat.c
parentAdd margin between header navs (diff)
downloadbubger-9b09a5ff483aef05dc5b4d9ab0fd0243d21cb1d3.tar.gz
bubger-9b09a5ff483aef05dc5b4d9ab0fd0243d21cb1d3.zip
Use SEARCH for a subset of thread roots
This does way less duplicate work by fetching all threads and all
thread root envelopes once, then doing searches for subsets of
thread roots.
Diffstat (limited to 'concat.c')
-rw-r--r--concat.c86
1 files changed, 62 insertions, 24 deletions
diff --git a/concat.c b/concat.c
index 800a7a2..54a49a7 100644
--- a/concat.c
+++ b/concat.c
@@ -27,6 +27,7 @@
 
 #include <err.h>
 #include <inttypes.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -54,6 +55,17 @@ void concatFetch(FILE *imap, enum Atom tag, struct List threads) {
 	fprintf(imap, " (UID ENVELOPE)\r\n");
 }
 
+void concatSearch(
+	FILE *imap, enum Atom tag, struct List threads, const char *expr
+) {
+	fprintf(imap, "%s UID SEARCH CHARSET UTF-8 UID ", Atoms[tag]);
+	for (size_t i = 0; i < threads.len; ++i) {
+		uint32_t root = threadRoot(dataCheck(threads.ptr[i], List).list);
+		fprintf(imap, "%s%" PRIu32, (i ? "," : ""), root);
+	}
+	fprintf(imap, " %s\r\n", expr);
+}
+
 void concatData(
 	struct List threads, struct Envelope *envelopes, struct List items
 ) {
@@ -230,13 +242,13 @@ void concatThreads(struct List threads, const struct Envelope *envelopes) {
 	}
 }
 
-static char *searchPath(const char *name, const char *type) {
+static char *indexPath(const char *name, const char *type) {
 	struct Variable vars[] = {
 		{ "name", name },
 		{ "type", type },
 		{0},
 	};
-	return templateString(PATH_SEARCH, vars, escapePath);
+	return templateString(PATH_INDEX, vars, escapePath);
 }
 
 static int numberCompare(const void *_a, const void *_b) {
@@ -261,23 +273,43 @@ static int sortCompare(const void *_a, const void *_b) {
 	}
 }
 
-size_t concatSearchEntries = 20;
+size_t concatIndexEntries = 20;
 
-void concatSearch(
-	const char *name, struct List threads, const struct Envelope *envelopes,
-	char *searches[const], size_t len
+void concatIndex(
+	const char *name, struct List roots,
+	struct List threads, const struct Envelope *envelopes
 ) {
-	char *path = searchPath(name, "atom");
+	bool *bitmap = calloc(threads.len, sizeof(*bitmap));
+	if (!bitmap) err(EX_OSERR, "calloc");
+
+	for (size_t i = 0; i < roots.len; ++i) {
+		dataCheck(roots.ptr[i], Number);
+	}
+	for (size_t i = 0; i < threads.len; ++i) {
+		uint32_t root = threadRoot(dataCheck(threads.ptr[i], List).list);
+		for (size_t j = 0; j < roots.len; ++j) {
+			if (root == roots.ptr[j].number) {
+				bitmap[i] = true;
+				break;
+			}
+		}
+	}
+
+	char *path = indexPath(name, "atom");
 	FILE *file = fopen(path, "w");
 	if (!file) err(EX_CANTCREAT, "%s", path);
 
-	int error = atomSearchOpen(file, name);
+	int error = atomIndexOpen(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
 	struct List flat = {0};
-	listFlatten(&flat, threads);
+	for (size_t i = 0; i < threads.len; ++i) {
+		if (!bitmap[i]) continue;
+		listFlatten(&flat, threads.ptr[i].list);
+	}
 	qsort(flat.ptr, flat.len, sizeof(*flat.ptr), numberCompare);
-	for (size_t i = 0; i < flat.len && i < concatSearchEntries; ++i) {
+
+	for (size_t i = 0; i < flat.len && i < concatIndexEntries; ++i) {
 		uint32_t uid = dataCheck(flat.ptr[i], Number).number;
 		char *src = uidPath(uid, "atom");
 		error = concatFile(file, src);
@@ -286,30 +318,37 @@ void concatSearch(
 	}
 	listFree(flat);
 
-	error = atomSearchClose(file) || fclose(file);
+	error = atomIndexClose(file) || fclose(file);
 	if (error) err(EX_IOERR, "%s", path);
 	if (!quiet) printf("%s\n", path);
 	free(path);
-
-	struct Sort *order = calloc(threads.len, sizeof(*order));
+	
+	size_t len = 0;
+	struct Sort *order = calloc(roots.len, sizeof(*order));
 	if (!order) err(EX_OSERR, "calloc");
 
 	for (size_t i = 0; i < threads.len; ++i) {
-		order[i].index = i;
-		order[i].created = envelopes[i].time;
+		if (!bitmap[i]) continue;
 
 		struct stat status;
 		char *path = threadPath(envelopes[i].messageID, "html");
-		if (!stat(path, &status)) order[i].updated = status.st_mtime;
+		error = stat(path, &status);
+		if (error) err(EX_DATAERR, "%s", path);
 		free(path);
+
+		order[len].index = i;
+		order[len].created = envelopes[i].time;
+		order[len].updated = status.st_mtime;
+		len++;
 	}
-	qsort(order, threads.len, sizeof(*order), sortCompare);
+	qsort(order, len, sizeof(*order), sortCompare);
+	free(bitmap);
 
-	path = searchPath(name, "html");
+	path = indexPath(name, "html");
 	file = fopen(path, "w");
 	if (!file) err(EX_CANTCREAT, "%s", path);
 
-	error = htmlSearchHead(file, name);
+	error = htmlIndexHead(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
 	if (concatHead) {
@@ -317,19 +356,18 @@ void concatSearch(
 		if (error) err(EX_IOERR, "%s", path);
 	}
 
-	error = htmlSearchOpen(file, name, searches, len);
+	error = htmlIndexOpen(file, name);
 	if (error) err(EX_IOERR, "%s", path);
 
-	for (size_t i = threads.len - 1; i < threads.len; --i) {
-		if (!order[i].updated) continue;
+	for (size_t i = len - 1; i < len; --i) {
 		const struct Envelope *envelope = &envelopes[order[i].index];
 		struct List thread = dataCheck(threads.ptr[order[i].index], List).list;
-		error = htmlSearchThread(file, envelope, thread);
+		error = htmlIndexThread(file, envelope, thread);
 		if (error) err(EX_IOERR, "%s", path);
 	}
 	free(order);
 
-	error = htmlSearchClose(file) || fclose(file);
+	error = htmlIndexClose(file) || fclose(file);
 	if (error) err(EX_IOERR, "%s", path);
 	if (!quiet) printf("%s\n", path);
 	free(path);