From 9b09a5ff483aef05dc5b4d9ab0fd0243d21cb1d3 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sat, 12 Jun 2021 19:20:47 -0400 Subject: 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. --- concat.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 24 deletions(-) (limited to 'concat.c') diff --git a/concat.c b/concat.c index 800a7a2..54a49a7 100644 --- a/concat.c +++ b/concat.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -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); -- cgit 1.4.1