notmuch search: Remove the chunked-searching hack.

This was a poor workaround around the fact that the existing
notmuch_threads_t object is implemented poorly. It's got a fine
iterartor-based interface, but the implementation does all of the
work up-front in _create rather than doing the work incrementally
while iterating.

So to start fixing this, first get rid of all the hacks we had working
around this. This drops the --first and --max-threads options from the
search command, (but hopefully nobody was using them
anyway---notmuch.el certainly wasn't).
This commit is contained in:
Carl Worth 2009-11-23 20:12:57 -08:00
parent f615803932
commit 1fd8b7866f
6 changed files with 25 additions and 144 deletions

View file

@ -322,14 +322,6 @@ notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort);
* object is owned by the query and as such, will only be valid until * object is owned by the query and as such, will only be valid until
* notmuch_query_destroy. * notmuch_query_destroy.
* *
* The 'first' and 'max_threads' arguments can be used to obtain
* partial results from the search. For example, to get results 10 at
* a time, pass 'max_threads' as 10 and for 'first' pass the values 0,
* 10, 20, etc. As a special case, a value of -1 for 'max_threads'
* indicates that no limiting is to be performed. So a search with
* 'first' == 0 and 'max_threads' == -1 will return the complete
* results of the search.
*
* Typical usage might be: * Typical usage might be:
* *
* notmuch_query_t *query; * notmuch_query_t *query;
@ -362,8 +354,7 @@ notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort);
* to call it if the query is about to be destroyed). * to call it if the query is about to be destroyed).
*/ */
notmuch_threads_t * notmuch_threads_t *
notmuch_query_search_threads (notmuch_query_t *query, notmuch_query_search_threads (notmuch_query_t *query);
int first, int max_threads);
/* Execute a query for messages, returning a notmuch_messages_t object /* Execute a query for messages, returning a notmuch_messages_t object
* which can be used to iterate over the results. The returned * which can be used to iterate over the results. The returned

View file

@ -171,9 +171,7 @@ _notmuch_threads_destructor (notmuch_threads_t *threads)
} }
notmuch_threads_t * notmuch_threads_t *
notmuch_query_search_threads (notmuch_query_t *query, notmuch_query_search_threads (notmuch_query_t *query)
int first,
int max_threads)
{ {
notmuch_threads_t *threads; notmuch_threads_t *threads;
notmuch_thread_t *thread; notmuch_thread_t *thread;
@ -181,7 +179,6 @@ notmuch_query_search_threads (notmuch_query_t *query,
notmuch_messages_t *messages; notmuch_messages_t *messages;
notmuch_message_t *message; notmuch_message_t *message;
GHashTable *seen; GHashTable *seen;
int messages_seen = 0, threads_seen = 0;
threads = talloc (query, notmuch_threads_t); threads = talloc (query, notmuch_threads_t);
if (threads == NULL) if (threads == NULL)
@ -196,13 +193,7 @@ notmuch_query_search_threads (notmuch_query_t *query,
seen = g_hash_table_new_full (g_str_hash, g_str_equal, seen = g_hash_table_new_full (g_str_hash, g_str_equal,
free, NULL); free, NULL);
while (max_threads < 0 || threads_seen < first + max_threads) for (messages = notmuch_query_search_messages (query, 0, -1);
{
int messages_seen_previously = messages_seen;
for (messages = notmuch_query_search_messages (query,
messages_seen,
max_threads);
notmuch_messages_has_more (messages); notmuch_messages_has_more (messages);
notmuch_messages_advance (messages)) notmuch_messages_advance (messages))
{ {
@ -214,31 +205,15 @@ notmuch_query_search_threads (notmuch_query_t *query,
thread_id, NULL, thread_id, NULL,
(void **) &thread)) (void **) &thread))
{ {
if (threads_seen >= first) {
thread = _notmuch_thread_create (query, query->notmuch, thread = _notmuch_thread_create (query, query->notmuch,
thread_id, thread_id,
query->query_string); query->query_string);
g_ptr_array_add (threads->threads, thread); g_ptr_array_add (threads->threads, thread);
} else {
thread = NULL;
}
g_hash_table_insert (seen, xstrdup (thread_id), thread); g_hash_table_insert (seen, xstrdup (thread_id), thread);
threads_seen++;
} }
notmuch_message_destroy (message); notmuch_message_destroy (message);
messages_seen++;
if (max_threads >= 0 && threads_seen >= first + max_threads)
break;
}
/* Stop if we're not seeing any more messages. */
if (messages_seen == messages_seen_previously)
break;
} }
g_hash_table_unref (seen); g_hash_table_unref (seen);

View file

@ -20,40 +20,24 @@
#include "notmuch-client.h" #include "notmuch-client.h"
/* If the user asks for more than this number of threads, then break static void
the results down into chunks so that results start appearing
quickly rather than the user having to wait until all results are
available before anything appears.
Since each subsequent chunk ends up having to re-do threading work
done by all previous chunks, we double the chunk size repeatedly
until all desired results have been returned.
*/
#define NOTMUCH_SEARCH_INITIAL_CHUNK_SIZE 100
/* Do the actual search for a chunk of threads and display the results,
(returning the number of threads found in this chunk). */
static int
do_search_threads (const void *ctx, do_search_threads (const void *ctx,
notmuch_query_t *query, notmuch_query_t *query,
notmuch_sort_t sort, notmuch_sort_t sort)
int first, int max_threads)
{ {
notmuch_thread_t *thread; notmuch_thread_t *thread;
notmuch_threads_t *threads; notmuch_threads_t *threads;
notmuch_tags_t *tags; notmuch_tags_t *tags;
time_t date; time_t date;
const char *relative_date; const char *relative_date;
int num_threads = 0;
for (threads = notmuch_query_search_threads (query, first, max_threads); for (threads = notmuch_query_search_threads (query);
notmuch_threads_has_more (threads); notmuch_threads_has_more (threads);
notmuch_threads_advance (threads)) notmuch_threads_advance (threads))
{ {
int first_tag = 1; int first_tag = 1;
thread = notmuch_threads_get (threads); thread = notmuch_threads_get (threads);
num_threads++;
if (sort == NOTMUCH_SORT_OLDEST_FIRST) if (sort == NOTMUCH_SORT_OLDEST_FIRST)
date = notmuch_thread_get_oldest_date (thread); date = notmuch_thread_get_oldest_date (thread);
@ -84,8 +68,6 @@ do_search_threads (const void *ctx,
notmuch_thread_destroy (thread); notmuch_thread_destroy (thread);
} }
return num_threads;
} }
int int
@ -95,32 +77,16 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
notmuch_database_t *notmuch; notmuch_database_t *notmuch;
notmuch_query_t *query; notmuch_query_t *query;
char *query_str; char *query_str;
int i, first = 0, max_threads = -1; char *opt;
char *opt, *end;
notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST; notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
int chunk_size; int i;
int threads_in_chunk;
for (i = 0; i < argc && argv[i][0] == '-'; i++) { for (i = 0; i < argc && argv[i][0] == '-'; i++) {
if (strcmp (argv[i], "--") == 0) { if (strcmp (argv[i], "--") == 0) {
i++; i++;
break; break;
} }
if (STRNCMP_LITERAL (argv[i], "--first=") == 0) { if (STRNCMP_LITERAL (argv[i], "--sort=") == 0) {
opt = argv[i] + sizeof ("--first=") - 1;
first = strtoul (opt, &end, 10);
if (*opt == '\0' || *end != '\0') {
fprintf (stderr, "Invalid value for --first: %s\n", opt);
return 1;
}
} else if (STRNCMP_LITERAL (argv[i], "--max-threads=") == 0) {
opt = argv[i] + sizeof ("--max-threads=") - 1;
max_threads = strtoul (opt, &end, 10);
if (*opt == '\0' || *end != '\0') {
fprintf (stderr, "Invalid value for --max-threads: %s\n", opt);
return 1;
}
} else if (STRNCMP_LITERAL (argv[i], "--sort=") == 0) {
opt = argv[i] + sizeof ("--sort=") - 1; opt = argv[i] + sizeof ("--sort=") - 1;
if (strcmp (opt, "oldest-first") == 0) { if (strcmp (opt, "oldest-first") == 0) {
sort = NOTMUCH_SORT_OLDEST_FIRST; sort = NOTMUCH_SORT_OLDEST_FIRST;
@ -166,25 +132,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
notmuch_query_set_sort (query, sort); notmuch_query_set_sort (query, sort);
/* If we receive a max-threads option, then the user is do_search_threads (ctx, query, sort);
responsible for any chunking and we return all results at
once. */
if (max_threads < 0)
chunk_size = NOTMUCH_SEARCH_INITIAL_CHUNK_SIZE;
else
chunk_size = max_threads;
do {
threads_in_chunk = do_search_threads (ctx, query, sort,
first, chunk_size);
if (chunk_size == max_threads)
break;
first += chunk_size;
chunk_size *= 2;
} while (threads_in_chunk);
notmuch_query_destroy (query); notmuch_query_destroy (query);
notmuch_database_close (notmuch); notmuch_database_close (notmuch);

View file

@ -238,7 +238,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
return 1; return 1;
} }
for (threads = notmuch_query_search_threads (query, 0, -1); for (threads = notmuch_query_search_threads (query);
notmuch_threads_has_more (threads); notmuch_threads_has_more (threads);
notmuch_threads_advance (threads)) notmuch_threads_advance (threads))
{ {

View file

@ -154,29 +154,6 @@ Supported options for
include include
.RS 4 .RS 4
.TP 4 .TP 4
.BR \-\-max\-threads= <value>
Restricts displayed search results to a subset of the complete results
that would match the terms. With this option, no more than <value>
thread results will be displayed. If this option is not used, then all
matching threads will be displayed. See also the
.B \-\-first
option.
.TP
.BR \-\-first= <value>
Omits the first <value> threads from the search results that would
otherwise be displayed. Together with the
.BR \-\-max\-threads
option, this can be used to perform incremental searches. For example,
the first 50 thread results can be displayed with
.B "\-\-first=0 \-\-max\-threads=50"
and the next 50 could be displayed with
.B "\-\-first=50 \-\-max\-threads=50"
etc.
.TP
.BR \-\-sort= ( newest\-first | oldest\-first ) .BR \-\-sort= ( newest\-first | oldest\-first )
This option can be used to present results in either chronological order This option can be used to present results in either chronological order

View file

@ -162,16 +162,6 @@ command_t commands[] = {
"\n" "\n"
"\t\tSupported options for search include:\n" "\t\tSupported options for search include:\n"
"\n" "\n"
"\t\t--max-threads=<value>\n"
"\n"
"\t\t\tRestricts displayed search results to a subset\n"
"\t\t\tof the results that would match the terms.\n"
"\n"
"\t\t--first=<value>\n"
"\n"
"\t\t\tOmits the first <value> threads from the search\n"
"\t\t\tresults that would otherwise be displayed.\n"
"\n"
"\t\t--sort=(newest-first|oldest-first)\n" "\t\t--sort=(newest-first|oldest-first)\n"
"\n" "\n"
"\t\t\tPresent results in either chronological order\n" "\t\t\tPresent results in either chronological order\n"