libnotmuch: Underlying support for doing partial-results searches.

The library interface now allows the caller to do incremental searches,
(such as one page of results at a time). Next we'll just need to hook
this up to "notmuch search" and the emacs interface.
This commit is contained in:
Carl Worth 2009-11-12 16:47:27 -08:00
parent e530910ae2
commit 93dcc3b695
7 changed files with 70 additions and 26 deletions

View file

@ -313,6 +313,14 @@ 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;
@ -345,13 +353,22 @@ 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
* messages object is owned by the query and as such, will only be * messages object is owned by the query and as such, will only be
* valid until notmuch_query_destroy. * valid until notmuch_query_destroy.
* *
* The 'first' and 'max_messages' arguments can be used to obtain
* partial results from the search. For example, to get results 10 at
* a time, pass 'max_messages' as 10 and for 'first' pass the values
* 0, 10, 20, etc. As a special case, a value of -1 for 'max_messages'
* indicates that no limiting is to be performed. So a search with
* 'first' == 0 and 'max_messages' == -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;
@ -384,7 +401,8 @@ notmuch_query_search_threads (notmuch_query_t *query);
* reason to call it if the query is about to be destroyed). * reason to call it if the query is about to be destroyed).
*/ */
notmuch_messages_t * notmuch_messages_t *
notmuch_query_search_messages (notmuch_query_t *query); notmuch_query_search_messages (notmuch_query_t *query,
int first, int max_messages);
/* Destroy a notmuch_query_t along with any associated resources. /* Destroy a notmuch_query_t along with any associated resources.
* *

View file

@ -88,7 +88,9 @@ _notmuch_messages_destructor (notmuch_messages_t *messages)
} }
notmuch_messages_t * notmuch_messages_t *
notmuch_query_search_messages (notmuch_query_t *query) notmuch_query_search_messages (notmuch_query_t *query,
int first,
int max_messages)
{ {
notmuch_database_t *notmuch = query->notmuch; notmuch_database_t *notmuch = query->notmuch;
const char *query_string = query->query_string; const char *query_string = query->query_string;
@ -138,7 +140,9 @@ notmuch_query_search_messages (notmuch_query_t *query)
enquire.set_query (final_query); enquire.set_query (final_query);
mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ()); if (max_messages == -1)
max_messages = notmuch->xapian_db->get_doccount ();
mset = enquire.get_mset (first, max_messages);
messages->notmuch = notmuch; messages->notmuch = notmuch;
@ -171,7 +175,9 @@ _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;
@ -179,6 +185,7 @@ 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)
@ -193,29 +200,48 @@ 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);
for (messages = notmuch_query_search_messages (query); while (threads_seen < first + max_threads)
notmuch_messages_has_more (messages);
notmuch_messages_advance (messages))
{ {
message = notmuch_messages_get (messages); int messages_seen_previously = messages_seen;
thread_id = notmuch_message_get_thread_id (message); for (messages = notmuch_query_search_messages (query,
messages_seen,
if (! g_hash_table_lookup_extended (seen, max_threads);
thread_id, NULL, notmuch_messages_has_more (messages);
(void **) &thread)) notmuch_messages_advance (messages))
{ {
thread = _notmuch_thread_create (query, query->notmuch, message = notmuch_messages_get (messages);
thread_id);
g_hash_table_insert (seen, xstrdup (thread_id), thread); thread_id = notmuch_message_get_thread_id (message);
g_ptr_array_add (threads->threads, thread); if (! g_hash_table_lookup_extended (seen,
thread_id, NULL,
(void **) &thread))
{
if (threads_seen > first) {
thread = _notmuch_thread_create (query, query->notmuch,
thread_id);
g_ptr_array_add (threads->threads, thread);
} else {
thread = NULL;
}
g_hash_table_insert (seen, xstrdup (thread_id), thread);
threads_seen++;
}
if (thread)
_notmuch_thread_add_message (thread, message);
notmuch_message_destroy (message);
messages_seen++;
} }
_notmuch_thread_add_message (thread, message); /* Stop if we're not seeing any more messages. */
if (messages_seen == messages_seen_previously)
notmuch_message_destroy (message); break;
} }
g_hash_table_unref (seen); g_hash_table_unref (seen);

View file

@ -57,7 +57,7 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[])
output = stdout; output = stdout;
} }
for (messages = notmuch_query_search_messages (query); for (messages = notmuch_query_search_messages (query, 0, -1);
notmuch_messages_has_more (messages); notmuch_messages_has_more (messages);
notmuch_messages_advance (messages)) notmuch_messages_advance (messages))
{ {

View file

@ -211,7 +211,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
return 1; return 1;
} }
for (messages = notmuch_query_search_messages (query); for (messages = notmuch_query_search_messages (query, 0, -1);
notmuch_messages_has_more (messages); notmuch_messages_has_more (messages);
notmuch_messages_advance (messages)) notmuch_messages_advance (messages))
{ {

View file

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

View file

@ -153,7 +153,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
return 1; return 1;
} }
for (messages = notmuch_query_search_messages (query); for (messages = notmuch_query_search_messages (query, 0, -1);
notmuch_messages_has_more (messages); notmuch_messages_has_more (messages);
notmuch_messages_advance (messages)) notmuch_messages_advance (messages))
{ {

View file

@ -86,7 +86,7 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))
return 1; return 1;
} }
for (messages = notmuch_query_search_messages (query); for (messages = notmuch_query_search_messages (query, 0, -1);
notmuch_messages_has_more (messages); notmuch_messages_has_more (messages);
notmuch_messages_advance (messages)) notmuch_messages_advance (messages))
{ {