On Thu, Jun 2, 2011 at 10:20 AM, Sebastian Spaeth <Sebastian at sspaeth.de> 
wrote:
> On Thu, 2 Jun 2011 19:43:29 +1000, Brian May wrote:
>> On 2 June 2011 17:05, Sebastian Spaeth <Sebastian at sspaeth.de> wrote:
>>
>> > What would be the best way to solve this (besides fixing the C api to
>> > allow to reset the iterator ;-) ?)
>
>> * It is not easy to fix the C api to reset the iterator (what about
>> repeating the search?)
>
> I am not sure about the difficulty of that, I am not a C-kind of
> guy. Repeating the search would be easy but potentially gives you
> different results since the db could have changed since then.

Not too hard.  Here's an utterly untested patch that implements
iterator resetting for notmuch_messages_t iterators.  It *should* be
much more efficient than performing the query again, but if you use
it, I'd love to know if that's actually true.

This may not be useful if __len__ is gone, unless you really want to
turn Messages/Threads into iterators rather than generators (as I've
pointed out before, there is absolutely nothing unusual or un-Pythonic
about how Messages/Threads works right now [well, except for the
presence of __len__ in a generator, I suppose]).

diff --git a/lib/messages.c b/lib/messages.c
index 7bcd1ab..085691c 100644
--- a/lib/messages.c
+++ b/lib/messages.c
@@ -80,7 +80,8 @@ _notmuch_messages_create (notmuch_message_list_t *list)
        return NULL;

     messages->is_of_list_type = TRUE;
-    messages->iterator = list->head;
+    messages->head = list->head;
+    notmuch_messages_reset (messages);

     return messages;
 }
@@ -137,6 +138,15 @@ notmuch_messages_move_to_next (notmuch_messages_t
*messages)
 }

 void
+notmuch_messages_reset (notmuch_messages_t *messages)
+{
+    if (! messages->is_of_list_type)
+       return _notmuch_mset_messages_reset (messages);
+
+    messages->iterator = messages->head;
+}
+
+void
 notmuch_messages_destroy (notmuch_messages_t *messages)
 {
     talloc_free (messages);
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 02e24ee..805d60c 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -413,6 +413,7 @@ typedef struct _notmuch_message_list {
  */
 struct visible _notmuch_messages {
     notmuch_bool_t is_of_list_type;
+    notmuch_message_node_t *head;
     notmuch_message_node_t *iterator;
 };

@@ -441,6 +442,9 @@ _notmuch_mset_messages_get (notmuch_messages_t *messages);
 void
 _notmuch_mset_messages_move_to_next (notmuch_messages_t *messages);

+void
+_notmuch_mset_messages_reset (notmuch_messages_t *messages);
+
 notmuch_bool_t
 _notmuch_doc_id_set_contains (notmuch_doc_id_set_t *doc_ids,
                               unsigned int doc_id);
diff --git a/lib/notmuch.h b/lib/notmuch.h
index 9cdcec0..044cfaa 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -734,6 +734,15 @@ notmuch_messages_get (notmuch_messages_t *messages);
 void
 notmuch_messages_move_to_next (notmuch_messages_t *messages);

+/* Reset the 'messages' iterator back to the first message.
+ *
+ * For iterators returned from notmuch_query_search_messages, this is
+ * both more efficient than performing the query a second time and
+ * guaranteed to result in the same messages as the first iteration.
+ */
+void
+notmuch_messages_reset (notmuch_messages_t *messages);
+
 /* Destroy a notmuch_messages_t object.
  *
  * It's not strictly necessary to call this function. All memory from
diff --git a/lib/query.cc b/lib/query.cc
index 6f02b04..1e75be0 100644
--- a/lib/query.cc
+++ b/lib/query.cc
@@ -32,6 +32,7 @@ struct _notmuch_query {
 typedef struct _notmuch_mset_messages {
     notmuch_messages_t base;
     notmuch_database_t *notmuch;
+    Xapian::MSet mset;
     Xapian::MSetIterator iterator;
     Xapian::MSetIterator iterator_end;
 } notmuch_mset_messages_t;
@@ -128,6 +129,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
        messages->base.is_of_list_type = FALSE;
        messages->base.iterator = NULL;
        messages->notmuch = notmuch;
+       new (&messages->mset) Xapian::MSet ();
        new (&messages->iterator) Xapian::MSetIterator ();
        new (&messages->iterator_end) Xapian::MSetIterator ();

@@ -181,8 +183,8 @@ notmuch_query_search_messages (notmuch_query_t *query)

        mset = enquire.get_mset (0, notmuch->xapian_db->get_doccount ());

-       messages->iterator = mset.begin ();
-       messages->iterator_end = mset.end ();
+       messages->mset = mset;
+       _notmuch_mset_messages_reset (&messages->base);

        return &messages->base;

@@ -257,6 +259,17 @@ _notmuch_mset_messages_move_to_next
(notmuch_messages_t *messages)
     mset_messages->iterator++;
 }

+void
+_notmuch_mset_messages_reset (notmuch_messages_t *messages)
+{
+    notmuch_mset_messages_t *mset_messages;
+
+    mset_messages = (notmuch_mset_messages_t *) messages;
+
+    mset_messages->iterator = mset_messages->mset.begin ();
+    mset_messages->iterator_end = mset_messages->mset.end ();
+}
+
 static notmuch_bool_t
 _notmuch_doc_id_set_init (void *ctx,
                          notmuch_doc_id_set_t *doc_ids,

Reply via email to