]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap: Add imap_search_seqset_iter_*() API for batched iteration of a seqset
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 4 Feb 2020 15:20:15 +0000 (17:20 +0200)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 6 Feb 2020 16:14:32 +0000 (16:14 +0000)
src/imap/imap-search-args.c
src/imap/imap-search-args.h

index 59d332b0036e884726cb70b97c5b6e82746ad834..eb506d904a42c8ec36f31e25ed8166309b70feb2 100644 (file)
@@ -224,3 +224,85 @@ void imap_search_add_changed_since(struct mail_search_args *search_args,
        search_arg->next = search_args->args->next;
        search_args->args->next = search_arg;
 }
+
+struct imap_search_seqset_iter {
+       struct mail_search_args *search_args;
+       ARRAY_TYPE(seq_range) seqset_left;
+       unsigned int batch_size;
+};
+
+static void imap_search_seqset_next_batch(struct imap_search_seqset_iter *iter)
+{
+       array_clear(&iter->search_args->args->value.seqset);
+       seq_range_array_merge_n(&iter->search_args->args->value.seqset,
+                               &iter->seqset_left, iter->batch_size);
+}
+
+struct imap_search_seqset_iter *
+imap_search_seqset_iter_init(struct mail_search_args *search_args,
+                            uint32_t messages_count, unsigned int batch_size)
+{
+       struct imap_search_seqset_iter *iter;
+
+       i_assert(search_args->args->next == NULL);
+
+       iter = i_new(struct imap_search_seqset_iter, 1);
+       iter->search_args = search_args;
+       iter->batch_size = batch_size;
+       mail_search_args_ref(iter->search_args);
+
+       /* Assume that the search query is always a seqset or SEARCH_ALL. */
+       switch (search_args->args->type) {
+       case SEARCH_SEQSET:
+               break;
+       case SEARCH_ALL:
+               if (search_args->args->match_not) {
+                       /* $ used before search result was saved */
+                       return iter;
+               }
+               /* 1:* - convert to seqset */
+               search_args->args->type = SEARCH_SEQSET;
+               p_array_init(&search_args->args->value.seqset,
+                            search_args->pool, 1);
+               seq_range_array_add_range(&search_args->args->value.seqset,
+                                         1, messages_count);
+               break;
+       default:
+               i_panic("Unexpected search_args type %d",
+                       search_args->args->type);
+       }
+
+       i_assert(search_args->args->type == SEARCH_SEQSET);
+
+       i_array_init(&iter->seqset_left,
+                    array_count(&search_args->args->value.seqset));
+       array_append_array(&iter->seqset_left, &search_args->args->value.seqset);
+       imap_search_seqset_next_batch(iter);
+       return iter;
+}
+
+void imap_search_seqset_iter_deinit(struct imap_search_seqset_iter **_iter)
+{
+       struct imap_search_seqset_iter *iter = *_iter;
+
+       if (iter == NULL)
+               return;
+
+       mail_search_args_unref(&iter->search_args);
+       array_free(&iter->seqset_left);
+       i_free(iter);
+}
+
+bool imap_search_seqset_iter_next(struct imap_search_seqset_iter *iter)
+{
+       if (!array_is_created(&iter->seqset_left))
+               return FALSE;
+
+       /* remove the last batch of searched mails from seqset_left */
+       seq_range_array_invert(&iter->search_args->args->value.seqset,
+                              1, UINT32_MAX);
+       seq_range_array_intersect(&iter->seqset_left,
+                                 &iter->search_args->args->value.seqset);
+       imap_search_seqset_next_batch(iter);
+       return array_count(&iter->search_args->args->value.seqset) > 0;
+}
index abcc87bc314d0b6b5ad71d1852a3c2bbf21ab5d0..32c95c49cac50fb1ad0f863a8f8e7bc7bc0663b3 100644 (file)
@@ -28,4 +28,16 @@ int imap_search_get_seqset(struct client_command_context *cmd,
 void imap_search_add_changed_since(struct mail_search_args *search_args,
                                   uint64_t modseq);
 
+/* Iterate search_args in batches of messages. The search_args itself is
+   modified each time imap_search_seqset_iter_next() is called. Note that
+   search_args is expected to come from imap_search_get_anyset(), i.e. it
+   must contain only SEARCH_SEQSET or SEARCH_ALL arg. */
+struct imap_search_seqset_iter *
+imap_search_seqset_iter_init(struct mail_search_args *search_args,
+                            uint32_t messages_count, unsigned int batch_size);
+/* Iterate the next batch. Returns TRUE if the batch was updated, FALSE if
+   all the batches have been iterated. */
+bool imap_search_seqset_iter_next(struct imap_search_seqset_iter *iter);
+void imap_search_seqset_iter_deinit(struct imap_search_seqset_iter **iter);
+
 #endif