/* thread.cc */
-notmuch_thread_t *
+notmuch_private_status_t
_notmuch_thread_create (void *ctx,
notmuch_database_t *notmuch,
unsigned int seed_doc_id,
notmuch_doc_id_set_t *match_set,
notmuch_string_list_t *excluded_terms,
notmuch_exclude_t omit_exclude,
- notmuch_sort_t sort);
+ notmuch_sort_t sort,
+ notmuch_thread_t **thread);
/* indexopts.c */
*
* for (stat = notmuch_query_search_threads (query, &threads);
* stat == NOTMUCH_STATUS_SUCCESS &&
- * notmuch_threads_valid (threads);
+ * ! notmuch_threads_status (threads);
* notmuch_threads_move_to_next (threads))
* {
* thread = notmuch_threads_get (threads);
*
* See the documentation of notmuch_query_search_threads for example
* code showing how to iterate over a notmuch_threads_t object.
+ *
+ * Note that an iterator may become invalid either due to getting exhausted or
+ * due to a runtime error. Use notmuch_threads_status to distinguish
+ * between those cases.
*/
notmuch_bool_t
notmuch_threads_valid (notmuch_threads_t *threads);
+/**
+ * Get the status of the given 'threads' iterator.
+ *
+ * Return value:
+ *
+ * @retval #NOTMUCH_STATUS_SUCCESS The iterator is valid; notmuch_threads_get
+ * may return a valid object
+ *
+ * @retval #NOTMUCH_STATUS_ITERATOR_EXHAUSTED All items have been read
+ *
+ * @retval #NOTMUCH_STATUS_OUT_OF_MEMORY Iteration failed to allocate memory
+ *
+ * @retval #NOTMUCH_STATUS_OPERATION_INVALIDATED Iteration was invalidated by
+ * the database. Re-open the database and try again.
+ *
+ * See the documentation of notmuch_query_search_threads for example
+ * code showing how to iterate over a notmuch_threads_t object.
+ */
+notmuch_status_t
+notmuch_threads_status (notmuch_threads_t *threads);
+
/**
* Get the current thread from 'threads' as a notmuch_thread_t.
*
*
* If 'threads' is already pointing at the last thread then the
* iterator will be moved to a point just beyond that last thread,
- * (where notmuch_threads_valid will return FALSE and
- * notmuch_threads_get will return NULL).
+ * (where notmuch_threads_status will return NOTMUCH_STATUS_ITERATOR_EXHAUSTED
+ * and notmuch_threads_get will return NULL).
*
* See the documentation of notmuch_query_search_threads for example
* code showing how to iterate over a notmuch_threads_t object.
/* The set of matched docid's that have not been assigned to a
* thread. Initially, this contains every docid in doc_ids. */
notmuch_doc_id_set_t match_set;
+ notmuch_status_t status;
};
/* We need this in the message functions so forward declare. */
threads = talloc (query, notmuch_threads_t);
if (threads == NULL)
return NOTMUCH_STATUS_OUT_OF_MEMORY;
+ threads->status = NOTMUCH_STATUS_SUCCESS;
threads->doc_ids = NULL;
talloc_set_destructor (threads, _notmuch_threads_destructor);
notmuch_bool_t
notmuch_threads_valid (notmuch_threads_t *threads)
+{
+ return notmuch_threads_status (threads) == NOTMUCH_STATUS_SUCCESS;
+}
+
+notmuch_status_t
+notmuch_threads_status (notmuch_threads_t *threads)
{
unsigned int doc_id;
if (! threads)
- return false;
+ return NOTMUCH_STATUS_ITERATOR_EXHAUSTED;
+ if (threads->status)
+ return threads->status;
while (threads->doc_id_pos < threads->doc_ids->len) {
doc_id = g_array_index (threads->doc_ids, unsigned int,
threads->doc_id_pos++;
}
- return threads->doc_id_pos < threads->doc_ids->len;
+ return (threads->doc_id_pos < threads->doc_ids->len) ?
+ NOTMUCH_STATUS_SUCCESS : NOTMUCH_STATUS_ITERATOR_EXHAUSTED;
}
notmuch_thread_t *
notmuch_threads_get (notmuch_threads_t *threads)
{
+ notmuch_thread_t *thread;
unsigned int doc_id;
+ notmuch_private_status_t status;
if (! notmuch_threads_valid (threads))
return NULL;
doc_id = g_array_index (threads->doc_ids, unsigned int,
threads->doc_id_pos);
- return _notmuch_thread_create (threads->query,
- threads->query->notmuch,
- doc_id,
- &threads->match_set,
- threads->query->exclude_terms,
- threads->query->omit_excluded,
- threads->query->sort);
+ status = _notmuch_thread_create (threads->query,
+ threads->query->notmuch,
+ doc_id,
+ &threads->match_set,
+ threads->query->exclude_terms,
+ threads->query->omit_excluded,
+ threads->query->sort,
+ &thread);
+ if (status) {
+ threads->status = COERCE_STATUS (status, "error creating a thread");
+ }
+
+ return thread;
}
void
*
* Here, 'ctx' is talloc context for the resulting thread object.
*
- * This function returns NULL in the case of any error.
+ * This function write NULL in the case of any error.
*/
-notmuch_thread_t *
+notmuch_private_status_t
_notmuch_thread_create (void *ctx,
notmuch_database_t *notmuch,
unsigned int seed_doc_id,
notmuch_doc_id_set_t *match_set,
notmuch_string_list_t *exclude_terms,
notmuch_exclude_t omit_excluded,
- notmuch_sort_t sort)
+ notmuch_sort_t sort,
+ notmuch_thread_t **pthread)
{
void *local = talloc_new (ctx);
notmuch_thread_t *thread = NULL;
notmuch_messages_t *messages;
notmuch_message_t *message;
- notmuch_status_t status;
+ notmuch_private_status_t status;
- seed_message = _notmuch_message_create (local, notmuch, seed_doc_id, NULL);
- if (! seed_message)
- INTERNAL_ERROR ("Thread seed message %u does not exist", seed_doc_id);
+ *pthread = NULL;
+
+ seed_message = _notmuch_message_create (local, notmuch, seed_doc_id, &status);
+ if (status)
+ return status;
thread_id = notmuch_message_get_thread_id (seed_message);
thread_id_query_string = talloc_asprintf (local, "thread:%s", thread_id);
* oldest or newest subject is desired. */
notmuch_query_set_sort (thread_id_query, NOTMUCH_SORT_OLDEST_FIRST);
- status = notmuch_query_search_messages (thread_id_query, &messages);
+ status = (notmuch_private_status_t) notmuch_query_search_messages (thread_id_query, &messages);
if (status)
goto DONE;
/* Commit to returning thread. */
(void) talloc_steal (ctx, thread);
+ *pthread = thread;
DONE:
talloc_free (local);
- return thread;
+ if (! *pthread && ! status)
+ status = NOTMUCH_PRIVATE_STATUS_OUT_OF_MEMORY;
+ return status;
}
notmuch_messages_t *
cp -a $NOTMUCH_SRCDIR/test/corpora/lkml ${MAIL_DIR}/
test_begin_subtest "handling NOTMUCH_STATUS_OPERATION_INVALIDATED in _notmuch_thread_create"
-test_subtest_known_broken
test_C ${MAIL_DIR} <<EOF
#include <notmuch-test.h>
// on the first try
for (try = 0; try < 2; try++) {
for (;
- notmuch_threads_valid (threads);
+ ! notmuch_threads_status (threads);
notmuch_threads_move_to_next (threads)) {
notmuch_thread_t *thread = notmuch_threads_get (threads);
}
- status = NOTMUCH_STATUS_ITERATOR_EXHAUSTED;
+ status = notmuch_threads_status (threads);
if (status != NOTMUCH_STATUS_OPERATION_INVALIDATED)
break;