[dovecot-cvs] dovecot/src/lib-storage/index Makefile.am,1.7,1.8 index-copy.c,1.25,1.26 index-fetch.c,1.39,1.40 index-fetch.h,1.14,1.15 index-messageset.c,1.11,1.12 index-messageset.h,1.5,1.6 index-search.c,1.64,1.65 index-storage.c,1.25,1.26 index-storage.h,1.28,1.29 Message-Id: <20030120145254.505F0238C6@danu.procontrol.fi>
cras at procontrol.fi
cras at procontrol.fi
Mon Jan 20 16:52:54 EET 2003
Update of /home/cvs/dovecot/src/lib-storage/index
In directory danu:/tmp/cvs-serv7093/lib-storage/index
Modified Files:
Makefile.am index-copy.c index-fetch.c index-fetch.h
index-messageset.c index-messageset.h index-search.c
index-storage.c index-storage.h index-update-flags.c
Removed Files:
index-fetch-section.c index-msgcache.c index-sort.c
index-sort.h
Log Message:
mail-storage.h interface changes, affects pretty much everything.
FETCH, SEARCH, SORT and THREAD handling were pretty much moved from
lib-storage/ to imap/ so adding non-index storages would be much easier now.
Also POP3 server can now be easily implemented with lib-storage.
Not too well tested, and at least one major problem: partial fetching is
_slow_.
Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/Makefile.am,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- Makefile.am 22 Dec 2002 17:52:47 -0000 1.7
+++ Makefile.am 20 Jan 2003 14:52:51 -0000 1.8
@@ -13,20 +13,16 @@
index-copy.c \
index-expunge.c \
index-fetch.c \
- index-fetch-section.c \
+ index-mail.c \
index-mailbox-check.c \
index-messageset.c \
- index-msgcache.c \
index-save.c \
index-search.c \
- index-sort.c \
index-status.c \
index-storage.c \
index-sync.c \
index-update-flags.c
noinst_HEADERS = \
- index-fetch.h \
index-messageset.h \
- index-sort.h \
index-storage.h
Index: index-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-copy.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- index-copy.c 11 Jan 2003 19:55:57 -0000 1.25
+++ index-copy.c 20 Jan 2003 14:52:51 -0000 1.26
@@ -8,51 +8,49 @@
#include <unistd.h>
-struct copy_context {
- struct mailbox *dest;
- const char **custom_flags;
- int copy_inside_mailbox;
-};
-
-static int copy_cb(struct mail_index *index, struct mail_index_record *rec,
- unsigned int client_seq __attr_unused__,
- unsigned int idx_seq __attr_unused__, void *context)
+static int copy_messageset(struct messageset_context *ctx,
+ struct index_mailbox *src, struct mailbox *dest)
{
- struct copy_context *ctx = context;
- struct index_mailbox *dest_ibox = NULL;
+ const struct messageset_mail *mail;
+ struct mail_full_flags flags;
struct istream *input;
time_t internal_date;
int failed, deleted;
- input = index->open_mail(index, rec, &internal_date, &deleted);
- if (input == NULL)
- return FALSE;
+ memset(&flags, 0, sizeof(flags));
+ flags.custom_flags =
+ mail_custom_flags_list_get(src->index->custom_flags);
+ flags.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
- if (ctx->copy_inside_mailbox) {
- /* kludgy.. */
- dest_ibox = (struct index_mailbox *) ctx->dest;
- dest_ibox->delay_save_unlocking = TRUE;
- }
+ while ((mail = index_messageset_next(ctx)) != NULL) {
+ input = src->index->open_mail(src->index, mail->rec,
+ &internal_date, &deleted);
+ if (input == NULL) {
+ if (deleted)
+ continue;
+ return FALSE;
+ }
- /* save it in destination mailbox */
- failed = !ctx->dest->save(ctx->dest, rec->msg_flags,
- ctx->custom_flags, internal_date, 0,
- input, input->v_limit);
+ /* save it in destination mailbox */
+ flags.flags = mail->rec->msg_flags;
+ failed = !dest->save(dest, &flags, internal_date, 0,
+ input, input->v_limit);
+ i_stream_unref(input);
- if (ctx->copy_inside_mailbox)
- dest_ibox->delay_save_unlocking = FALSE;
+ if (failed)
+ return FALSE;
+ }
- i_stream_unref(input);
- return !failed;
+ return TRUE;
}
int index_storage_copy(struct mailbox *box, struct mailbox *destbox,
const char *messageset, int uidset)
{
struct index_mailbox *ibox = (struct index_mailbox *) box;
- struct copy_context ctx;
+ struct messageset_context *ctx;
enum mail_lock_type lock_type;
- int failed;
+ int ret, copy_inside_mailbox;
if (destbox->readonly) {
mail_storage_set_error(box->storage,
@@ -60,15 +58,18 @@
return FALSE;
}
- ctx.copy_inside_mailbox =
+ copy_inside_mailbox =
destbox->storage == box->storage &&
strcmp(destbox->name, box->name) == 0;
- if (ctx.copy_inside_mailbox) {
+ if (copy_inside_mailbox) {
/* copying inside same mailbox */
if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
return FALSE;
+ /* kludgy.. */
+ ((struct index_mailbox *) destbox)->delay_save_unlocking = TRUE;
+
lock_type = MAIL_LOCK_EXCLUSIVE;
} else {
lock_type = MAIL_LOCK_SHARED;
@@ -77,15 +78,16 @@
if (!index_storage_sync_and_lock(ibox, TRUE, lock_type))
return FALSE;
- ctx.custom_flags =
- mail_custom_flags_list_get(ibox->index->custom_flags);
- ctx.dest = destbox;
+ ctx = index_messageset_init(ibox, messageset, uidset);
+ ret = copy_messageset(ctx, ibox, destbox);
+ if (index_messageset_deinit(ctx) < 0)
+ ret = FALSE;
- failed = index_messageset_foreach(ibox, messageset, uidset,
- copy_cb, &ctx) <= 0;
+ if (copy_inside_mailbox)
+ ((struct index_mailbox *) destbox)->delay_save_unlocking = TRUE;
if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
return FALSE;
- return !failed;
+ return ret;
}
Index: index-fetch.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-fetch.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- index-fetch.c 5 Jan 2003 13:09:52 -0000 1.39
+++ index-fetch.c 20 Jan 2003 14:52:51 -0000 1.40
@@ -3,414 +3,157 @@
#include "lib.h"
#include "ostream.h"
#include "str.h"
+#include "mail-index.h"
+#include "mail-modifylog.h"
#include "mail-custom-flags.h"
#include "index-storage.h"
-#include "index-fetch.h"
#include "index-messageset.h"
-#include "message-send.h"
-#include "imap-date.h"
-#include "imap-util.h"
-#include "imap-message-cache.h"
-
-#include <unistd.h>
-
-static int index_fetch_internaldate(struct mail_index_record *rec,
- struct fetch_context *ctx)
-{
- time_t date;
+#include "index-mail.h"
- date = imap_msgcache_get_internal_date(ctx->cache);
- if (date != (time_t)-1) {
- str_printfa(ctx->str, "INTERNALDATE \"%s\" ",
- imap_to_datetime(date));
- return TRUE;
- } else {
- mail_storage_set_critical(ctx->storage,
- "Couldn't generate INTERNALDATE for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
- }
-}
+struct mail_fetch_context {
+ struct index_mailbox *ibox;
+ struct mail_index *index;
-static int index_fetch_body(struct mail_index_record *rec,
- struct fetch_context *ctx)
-{
- const char *body;
+ struct messageset_context *msgset_ctx;
+ struct index_mail mail;
- body = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODY);
- if (body != NULL) {
- str_printfa(ctx->str, "BODY (%s) ", body);
- return TRUE;
- } else {
- mail_storage_set_critical(ctx->storage,
- "Couldn't generate BODY for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
- }
-}
+ int update_seen;
+};
-static int index_fetch_bodystructure(struct mail_index_record *rec,
- struct fetch_context *ctx)
+struct mail_fetch_context *
+index_storage_fetch_init(struct mailbox *box,
+ enum mail_fetch_field wanted_fields, int *update_seen,
+ const char *messageset, int uidset)
{
- const char *bodystructure;
+ struct index_mailbox *ibox = (struct index_mailbox *) box;
+ struct mail_fetch_context *ctx;
- bodystructure = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODYSTRUCTURE);
- if (bodystructure != NULL) {
- str_printfa(ctx->str, "BODYSTRUCTURE (%s) ", bodystructure);
- return TRUE;
- } else {
- mail_storage_set_critical(ctx->storage,
- "Couldn't generate BODYSTRUCTURE for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
- }
-}
+ ctx = i_new(struct mail_fetch_context, 1);
-static int index_fetch_envelope(struct mail_index_record *rec,
- struct fetch_context *ctx)
-{
- const char *envelope;
+ if (!box->readonly)
+ *update_seen = FALSE;
- envelope = imap_msgcache_get(ctx->cache, IMAP_CACHE_ENVELOPE);
- if (envelope != NULL) {
- str_printfa(ctx->str, "ENVELOPE (%s) ", envelope);
- return TRUE;
- } else {
- mail_storage_set_critical(ctx->storage,
- "Couldn't generate ENVELOPE for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
+ /* need exclusive lock to update the \Seen flags */
+ if (*update_seen) {
+ if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
+ return NULL;
}
-}
-static int index_fetch_rfc822_size(struct mail_index_record *rec,
- struct fetch_context *ctx)
-{
- uoff_t size;
+ if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
+ return NULL;
- size = imap_msgcache_get_virtual_size(ctx->cache);
- if (size == (uoff_t)-1) {
- mail_storage_set_critical(ctx->storage,
- "Couldn't get RFC822.SIZE for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
+ if (*update_seen &&
+ ibox->index->header->messages_count ==
+ ibox->index->header->seen_messages_count) {
+ /* if all messages are already seen, there's no point in
+ keeping exclusive lock */
+ *update_seen = FALSE;
+ (void)index_storage_lock(ibox, MAIL_LOCK_SHARED);
}
- str_printfa(ctx->str, "RFC822.SIZE %"PRIuUOFF_T" ", size);
- return TRUE;
-}
-
-static void index_fetch_flags(struct mail_index_record *rec,
- struct fetch_context *ctx)
-{
- enum mail_flags flags;
-
- flags = rec->msg_flags;
- if (rec->uid >= ctx->index->first_recent_uid)
- flags |= MAIL_RECENT;
- if (ctx->update_seen)
- flags |= MAIL_SEEN;
-
- str_printfa(ctx->str, "FLAGS (%s) ",
- imap_write_flags(flags, ctx->custom_flags,
- ctx->custom_flags_count));
-}
+ ctx->ibox = ibox;
+ ctx->index = ibox->index;
+ ctx->update_seen = *update_seen;
-static void index_fetch_uid(struct mail_index_record *rec,
- struct fetch_context *ctx)
-{
- str_printfa(ctx->str, "UID %u ", rec->uid);
+ index_mail_init(ibox, &ctx->mail, wanted_fields, NULL);
+ ctx->msgset_ctx = index_messageset_init(ibox, messageset, uidset);
+ return ctx;
}
-static int index_fetch_send_rfc822(struct mail_index_record *rec,
- struct fetch_context *ctx)
+int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found)
{
- struct message_size hdr_size, body_size;
- struct istream *input;
- const char *str;
-
- if (!imap_msgcache_get_rfc822(ctx->cache, &input,
- &hdr_size, &body_size)) {
- mail_storage_set_critical(ctx->storage,
- "Couldn't get RFC822 for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
- }
-
- str = t_strdup_printf(" RFC822 {%"PRIuUOFF_T"}\r\n",
- hdr_size.virtual_size + body_size.virtual_size);
- if (ctx->first) {
- str++; ctx->first = FALSE;
- }
- if (o_stream_send_str(ctx->output, str) < 0)
- return FALSE;
-
- body_size.physical_size += hdr_size.physical_size;
- body_size.virtual_size += hdr_size.virtual_size;
- return message_send(ctx->output, input, &body_size, 0, (uoff_t)-1);
-}
+ int ret;
-static int index_fetch_send_rfc822_header(struct mail_index_record *rec,
- struct fetch_context *ctx)
-{
- struct message_size hdr_size;
- struct istream *input;
- const char *str;
+ ret = index_messageset_deinit(ctx->msgset_ctx);
- if (!imap_msgcache_get_rfc822(ctx->cache, &input, &hdr_size, NULL)) {
- mail_storage_set_critical(ctx->storage,
- "Couldn't get RFC822.HEADER for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
- }
+ if (all_found != NULL)
+ *all_found = ret > 0;
- str = t_strdup_printf(" RFC822.HEADER {%"PRIuUOFF_T"}\r\n",
- hdr_size.virtual_size);
- if (ctx->first) {
- str++; ctx->first = FALSE;
- }
- if (o_stream_send_str(ctx->output, str) < 0)
- return FALSE;
+ if (!index_storage_lock(ctx->ibox, MAIL_LOCK_UNLOCK))
+ ret = -1;
- return message_send(ctx->output, input, &hdr_size, 0, (uoff_t)-1);
+ if (ctx->ibox->fetch_mail.pool != NULL)
+ index_mail_deinit(&ctx->ibox->fetch_mail);
+ index_mail_deinit(&ctx->mail);
+ i_free(ctx);
+ return ret >= 0;
}
-static int index_fetch_send_rfc822_text(struct mail_index_record *rec,
- struct fetch_context *ctx)
+struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx)
{
- struct message_size body_size;
- struct istream *input;
- const char *str;
-
- if (!imap_msgcache_get_rfc822(ctx->cache, &input, NULL, &body_size)) {
- mail_storage_set_critical(ctx->storage,
- "Couldn't get RFC822.TEXT for UID %u (index %s)",
- rec->uid, ctx->index->filepath);
- return FALSE;
- }
-
- str = t_strdup_printf(" RFC822.TEXT {%"PRIuUOFF_T"}\r\n",
- body_size.virtual_size);
- if (ctx->first) {
- str++; ctx->first = FALSE;
- }
- if (o_stream_send_str(ctx->output, str) < 0)
- return FALSE;
+ const struct messageset_mail *msgset_mail;
+ struct mail_index_record *rec;
+ int ret;
- return message_send(ctx->output, input, &body_size, 0, (uoff_t)-1);
-}
+ do {
+ msgset_mail = index_messageset_next(ctx->msgset_ctx);
+ if (msgset_mail == NULL)
+ return NULL;
-static enum imap_cache_field index_get_cache(struct mail_fetch_data *fetch_data)
-{
- struct mail_fetch_body_data *sect;
- enum imap_cache_field field;
+ rec = msgset_mail->rec;
+ ctx->mail.mail.seen_updated = FALSE;
+ if (ctx->update_seen && (rec->msg_flags & MAIL_SEEN) == 0) {
+ if (ctx->index->update_flags(ctx->index, rec,
+ msgset_mail->idx_seq,
+ rec->msg_flags | MAIL_SEEN,
+ FALSE))
+ ctx->mail.mail.seen_updated = TRUE;
+ }
- field = 0;
- if (fetch_data->body)
- field |= IMAP_CACHE_BODY;
- if (fetch_data->bodystructure)
- field |= IMAP_CACHE_BODYSTRUCTURE;
- if (fetch_data->envelope)
- field |= IMAP_CACHE_ENVELOPE;
- if (fetch_data->internaldate)
- field |= IMAP_CACHE_INTERNALDATE;
+ ctx->mail.mail.seq = msgset_mail->client_seq;
+ ctx->mail.mail.uid = rec->uid;
- if (fetch_data->rfc822_size)
- field |= IMAP_CACHE_VIRTUAL_SIZE;
- if (fetch_data->rfc822) {
- field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE |
- IMAP_CACHE_MESSAGE_BODY_SIZE;
- }
- if (fetch_data->rfc822_header)
- field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE;
- if (fetch_data->rfc822_text)
- field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_BODY_SIZE;
+ ret = index_mail_next(&ctx->mail, rec);
+ } while (ret == 0);
- /* check what body[] sections want */
- sect = fetch_data->body_sections;
- for (; sect != NULL; sect = sect->next)
- field |= index_fetch_body_get_cache(sect->section);
- return field;
+ return ret < 0 ? NULL : &ctx->mail.mail;
}
-static int fetch_msgcache_open(struct fetch_context *ctx,
- struct mail_index_record *rec)
+static struct mail *
+fetch_record(struct index_mailbox *ibox, struct mail_index_record *rec,
+ enum mail_fetch_field wanted_fields)
{
- enum imap_cache_field fields;
+ if (ibox->fetch_mail.pool != NULL)
+ index_mail_deinit(&ibox->fetch_mail);
- fields = index_get_cache(ctx->fetch_data);
- if (fields == 0)
- return TRUE;
+ index_mail_init(ibox, &ibox->fetch_mail, wanted_fields, NULL);
+ if (index_mail_next(&ibox->fetch_mail, rec) <= 0)
+ return NULL;
- return index_msgcache_open(ctx->cache, ctx->index, rec, fields);
+ return &ibox->fetch_mail.mail;
}
-static int index_fetch_mail(struct mail_index *index __attr_unused__,
- struct mail_index_record *rec,
- unsigned int client_seq, unsigned int idx_seq,
- void *context)
+struct mail *index_storage_fetch_uid(struct mailbox *box, unsigned int uid,
+ enum mail_fetch_field wanted_fields)
{
- struct fetch_context *ctx = context;
- struct mail_fetch_body_data *sect;
- size_t len, orig_len;
- int failed, data_written, fetch_flags;
-
- /* first see what we need to do. this way we don't first do some
- light parsing and later notice that we need to do heavier parsing
- anyway */
- if (!fetch_msgcache_open(ctx, rec)) {
- /* most likely message not found, just ignore it. */
- imap_msgcache_close(ctx->cache);
- ctx->failed = TRUE;
- return TRUE;
- }
-
- if (ctx->update_seen && (rec->msg_flags & MAIL_SEEN) == 0) {
- (void)index->update_flags(index, rec, idx_seq,
- rec->msg_flags | MAIL_SEEN, FALSE);
- fetch_flags = TRUE;
- } else {
- fetch_flags = FALSE;
- }
-
- ctx->str = t_str_new(2048);
-
- str_printfa(ctx->str, "* %u FETCH (", client_seq);
- orig_len = str_len(ctx->str);
-
- failed = TRUE;
- data_written = FALSE;
- do {
- /* these can't fail */
- if (ctx->fetch_data->uid)
- index_fetch_uid(rec, ctx);
- if (ctx->fetch_data->flags || fetch_flags)
- index_fetch_flags(rec, ctx);
-
- /* rest can */
- if (ctx->fetch_data->internaldate)
- if (!index_fetch_internaldate(rec, ctx))
- break;
- if (ctx->fetch_data->body)
- if (!index_fetch_body(rec, ctx))
- break;
- if (ctx->fetch_data->bodystructure)
- if (!index_fetch_bodystructure(rec, ctx))
- break;
- if (ctx->fetch_data->envelope)
- if (!index_fetch_envelope(rec, ctx))
- break;
- if (ctx->fetch_data->rfc822_size)
- if (!index_fetch_rfc822_size(rec, ctx))
- break;
-
- /* send the data written into temp string,
- not including the trailing zero */
- ctx->first = str_len(ctx->str) == orig_len;
- len = str_len(ctx->str);
- if (len > 0) {
- if (!ctx->first)
- str_truncate(ctx->str, --len);
-
- if (o_stream_send(ctx->output,
- str_c(ctx->str), len) < 0)
- break;
- }
-
- data_written = TRUE;
-
- /* large data */
- if (ctx->fetch_data->rfc822)
- if (!index_fetch_send_rfc822(rec, ctx))
- break;
- if (ctx->fetch_data->rfc822_text)
- if (!index_fetch_send_rfc822_text(rec, ctx))
- break;
- if (ctx->fetch_data->rfc822_header)
- if (!index_fetch_send_rfc822_header(rec, ctx))
- break;
-
- sect = ctx->fetch_data->body_sections;
- for (; sect != NULL; sect = sect->next) {
- if (!index_fetch_body_section(rec, sect, ctx))
- break;
- }
+ struct index_mailbox *ibox = (struct index_mailbox *) box;
+ struct mail_index_record *rec;
- failed = FALSE;
- } while (0);
+ i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
- if (data_written) {
- if (o_stream_send(ctx->output, ")\r\n", 3) < 0)
- failed = TRUE;
- }
+ rec = ibox->index->lookup_uid_range(ibox->index, uid, uid, NULL);
+ if (rec == NULL)
+ return NULL;
- imap_msgcache_close(ctx->cache);
- return !failed;
+ return fetch_record(ibox, rec, wanted_fields);
}
-int index_storage_fetch(struct mailbox *box, struct mail_fetch_data *fetch_data,
- struct ostream *output, int *all_found)
+struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
+ enum mail_fetch_field wanted_fields)
{
struct index_mailbox *ibox = (struct index_mailbox *) box;
- struct fetch_context ctx;
- struct mail_fetch_body_data *sect;
- int ret;
-
- memset(&ctx, 0, sizeof(ctx));
-
- if (!box->readonly) {
- /* If we have any BODY[..] sections, \Seen flag is added for
- all messages */
- sect = fetch_data->body_sections;
- for (; sect != NULL; sect = sect->next) {
- if (!sect->peek) {
- ctx.update_seen = TRUE;
- break;
- }
- }
-
- if (fetch_data->rfc822 || fetch_data->rfc822_text)
- ctx.update_seen = TRUE;
- }
-
- /* need exclusive lock to update the \Seen flags */
- if (ctx.update_seen) {
- if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
- return FALSE;
- }
-
- if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
- return FALSE;
-
- if (ctx.update_seen &&
- ibox->index->header->messages_count ==
- ibox->index->header->seen_messages_count) {
- /* if all messages are already seen, there's no point in
- keeping exclusive lock */
- ctx.update_seen = FALSE;
- (void)index_storage_lock(ibox, MAIL_LOCK_SHARED);
- }
-
- ctx.box = box;
- ctx.storage = box->storage;
- ctx.cache = ibox->cache;
- ctx.index = ibox->index;
- ctx.custom_flags =
- mail_custom_flags_list_get(ibox->index->custom_flags);
- ctx.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
-
- ctx.fetch_data = fetch_data;
- ctx.output = output;
+ struct mail_index_record *rec;
+ unsigned int expunges_before;
- ret = index_messageset_foreach(ibox, fetch_data->messageset,
- fetch_data->uidset,
- index_fetch_mail, &ctx);
+ i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
- if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
- return FALSE;
+ if (mail_modifylog_seq_get_expunges(ibox->index->modifylog, seq, seq,
+ &expunges_before) == NULL)
+ return NULL;
- if (all_found != NULL)
- *all_found = ret == 1 && !ctx.failed;
+ rec = ibox->index->lookup(ibox->index, seq - expunges_before);
+ if (rec == NULL)
+ return NULL;
- return ret > 0;
+ return fetch_record(ibox, rec, wanted_fields);
}
Index: index-fetch.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-fetch.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- index-fetch.h 5 Jan 2003 13:09:52 -0000 1.14
+++ index-fetch.h 20 Jan 2003 14:52:51 -0000 1.15
@@ -10,7 +10,7 @@
const char **custom_flags;
unsigned int custom_flags_count;
- struct mail_fetch_data *fetch_data;
+ //struct mail_fetch_data *fetch_data;
struct ostream *output;
string_t *str;
int update_seen, failed;
Index: index-messageset.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-messageset.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- index-messageset.c 11 Jan 2003 19:55:57 -0000 1.11
+++ index-messageset.c 20 Jan 2003 14:52:51 -0000 1.12
@@ -1,342 +1,291 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
#include "mail-index.h"
#include "mail-index-util.h"
#include "mail-modifylog.h"
+#include "index-storage.h"
#include "index-messageset.h"
-static unsigned int get_next_number(const char **str)
-{
- unsigned int num;
+struct messageset_context {
+ struct index_mailbox *ibox;
+ struct mail_index *index;
- num = 0;
- while (**str != '\0') {
- if (**str < '0' || **str > '9')
- break;
+ const struct modify_log_expunge *expunges;
+ int expunges_found;
- num = num*10 + (**str - '0');
- (*str)++;
- }
+ struct messageset_mail mail;
+ unsigned int messages_count;
+ unsigned int num1, num2;
- return num;
-}
+ const char *messageset, *p;
+ int uidset;
-static int mail_index_foreach(struct mail_index *index,
- unsigned int seq, unsigned int seq2,
- msgset_foreach_callback_t callback, void *context)
-{
- struct mail_index_record *rec;
- const struct modify_log_expunge *expunges;
- unsigned int idx_seq, expunges_before, temp;
- int expunges_found;
+ int first, ret;
+ const char *error;
+};
- if (seq > seq2) {
- /* swap, as specified by latest IMAP4rev1 spec */
- temp = seq;
- seq = seq2;
- seq2 = temp;
- }
+static int uidset_init(struct messageset_context *ctx);
+static int seqset_init(struct messageset_context *ctx);
- /* get list of expunged messages in our range. the expunges_before
- can be used to calculate the current real sequence position */
- expunges = mail_modifylog_seq_get_expunges(index->modifylog, seq, seq2,
- &expunges_before);
- if (expunges == NULL)
- return -1;
+struct messageset_context *
+index_messageset_init(struct index_mailbox *ibox,
+ const char *messageset, int uidset)
+{
+ struct messageset_context *ctx;
- i_assert(expunges_before < seq);
- expunges_found = expunges->uid1 != 0;
+ i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
- /* Reset index errors, since we later rely on it to check if failed */
- index_reset_error(index);
+ ctx = i_new(struct messageset_context, 1);
+ ctx->ibox = ibox;
+ ctx->index = ibox->index;
+ ctx->messages_count = ibox->synced_messages_count;
+ ctx->p = ctx->messageset = messageset;
+ ctx->uidset = uidset;
- /* get the first non-expunged message. note that if all messages
- were expunged in the range, this points outside wanted range. */
- idx_seq = seq - expunges_before;
- rec = index->lookup(index, idx_seq);
- for (; rec != NULL; seq++, idx_seq++) {
- /* skip expunged sequences */
- i_assert(rec->uid != 0);
+ /* Reset index errors, we rely on it to check for failures */
+ index_reset_error(ctx->index);
- while (expunges->uid1 != 0 && expunges->uid1 < rec->uid) {
- i_assert(expunges->uid2 < rec->uid);
+ return ctx;
+}
- seq += expunges->seq_count;
- expunges++;
- }
- i_assert(!(expunges->uid1 <= rec->uid &&
- expunges->uid2 >= rec->uid));
+struct messageset_context *
+index_messageset_init_range(struct index_mailbox *ibox,
+ unsigned int num1, unsigned int num2, int uidset)
+{
+ struct messageset_context *ctx;
- if (seq > seq2)
- break;
+ ctx = index_messageset_init(ibox, NULL, uidset);
+ ctx->num1 = num1;
+ ctx->num2 = num2;
+ return ctx;
+}
- t_push();
- if (!callback(index, rec, seq, idx_seq, context)) {
- t_pop();
- return 0;
- }
- t_pop();
+int index_messageset_deinit(struct messageset_context *ctx)
+{
+ int ret = ctx->ret;
- rec = index->next(index, rec);
+ if (ret == 1 && ctx->expunges_found) {
+ /* some of the messages weren't found */
+ ret = 0;
}
- if (rec == NULL &&
- index->get_last_error(index) != MAIL_INDEX_ERROR_NONE) {
- /* error occured */
- return -1;
+ if (ret == -1)
+ mail_storage_set_index_error(ctx->ibox);
+ else if (ret == -2) {
+ /* user error */
+ mail_storage_set_syntax_error(ctx->ibox->box.storage,
+ "%s", ctx->error);
}
- return !expunges_found && seq > seq2 ? 1 : 2;
+ i_free(ctx);
+ return ret;
}
-static int mail_index_messageset_foreach(struct mail_index *index,
- const char *messageset,
- unsigned int messages_count,
- msgset_foreach_callback_t callback,
- void *context, const char **error)
+static unsigned int get_next_number(const char **str)
{
- const char *input;
- unsigned int seq, seq2;
- int ret, all_found;
+ unsigned int num;
- i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
+ num = 0;
+ while (**str != '\0') {
+ if (**str < '0' || **str > '9')
+ break;
- *error = NULL;
- if (messages_count == 0) {
- *error = "No messages in mailbox";
- return -2;
+ num = num*10 + (**str - '0');
+ (*str)++;
}
- all_found = TRUE;
- input = messageset;
- while (*input != '\0') {
- if (*input == '*') {
- /* last message */
- seq = messages_count;
- input++;
- } else {
- seq = get_next_number(&input);
- if (seq == 0) {
- *error = t_strconcat("Invalid messageset: ",
- messageset, NULL);
- return -2;
- }
- }
+ return num;
+}
- if (*input != ':')
- seq2 = seq;
- else {
- /* first:last range */
- input++;
+static int messageset_parse_next(struct messageset_context *ctx)
+{
+ if (ctx->p == NULL) {
+ /* num1..num2 already set. */
+ ctx->p = "";
+ return TRUE;
+ }
- if (*input != '*') {
- seq2 = get_next_number(&input);
- if (seq2 == 0) {
- *error = t_strconcat("Invalid "
- "messageset: ",
- messageset, NULL);
- return -2;
- }
- } else {
- seq2 = messages_count;
- input++;
- }
+ if (*ctx->p == '*') {
+ /* last message */
+ ctx->num1 = (unsigned int)-1;
+ ctx->p++;
+ } else {
+ ctx->num1 = get_next_number(&ctx->p);
+ if (ctx->num1 == 0) {
+ ctx->error = t_strconcat("Invalid messageset: ",
+ ctx->messageset, NULL);
+ return FALSE;
}
+ }
- if (*input == ',')
- input++;
- else if (*input != '\0') {
- *error = t_strdup_printf("Unexpected char '%c' "
- "with messageset: %s",
- *input, messageset);
- return -2;
- }
+ if (*ctx->p != ':')
+ ctx->num2 = ctx->num1;
+ else {
+ /* first:last range */
+ ctx->p++;
- if (seq > messages_count || seq2 > messages_count) {
- /* non-existent messages requested */
- if (seq <= messages_count)
- seq = seq2;
- *error = t_strdup_printf("Message sequence %u "
- "larger than mailbox size %u",
- seq, messages_count);
- return -2;
+ if (*ctx->p == '*') {
+ ctx->num2 = (unsigned int)-1;
+ ctx->p++;
+ } else {
+ ctx->num2 = get_next_number(&ctx->p);
+ if (ctx->num2 == 0) {
+ ctx->error = t_strconcat("Invalid messageset: ",
+ ctx->messageset, NULL);
+ return FALSE;
+ }
}
+ }
- t_push();
- ret = mail_index_foreach(index, seq, seq2, callback, context);
- t_pop();
- if (ret <= 0)
- return ret;
- if (ret == 2)
- all_found = FALSE;
+ if (*ctx->p == ',')
+ ctx->p++;
+ else if (*ctx->p != '\0') {
+ ctx->error = t_strdup_printf("Unexpected char '%c' "
+ "with messageset: %s",
+ *ctx->p, ctx->messageset);
+ return FALSE;
}
- return all_found ? 1 : 2;
+ if (ctx->num1 > ctx->num2) {
+ /* swap, as specified by latest IMAP4rev1 draft */
+ unsigned int temp = ctx->num1;
+ ctx->num1 = ctx->num2;
+ ctx->num2 = temp;
+ }
+
+ return TRUE;
}
-static int mail_index_uid_foreach(struct mail_index *index,
- unsigned int uid, unsigned int uid2,
- msgset_foreach_callback_t callback,
- void *context)
+static int uidset_init(struct messageset_context *ctx)
{
- struct mail_index_record *rec;
- const struct modify_log_expunge *expunges;
- unsigned int client_seq, idx_seq, expunges_before, temp;
- int expunges_found;
+ unsigned int expunges_before;
- if (uid > uid2) {
- /* swap, as specified by latest IMAP4rev1 spec */
- temp = uid;
- uid = uid2;
- uid2 = temp;
+ if (ctx->num1 == (unsigned int)-1) {
+ struct mail_index_record *rec;
+
+ rec = ctx->index->lookup(ctx->index, ctx->messages_count);
+ ctx->num1 = rec == NULL ? 0 : rec->uid;
}
+ if (ctx->num2 == (unsigned int)-1)
+ ctx->num2 = ctx->index->header->next_uid-1;
+
/* get list of expunged messages in our range. */
- expunges = mail_modifylog_uid_get_expunges(index->modifylog, uid, uid2,
- &expunges_before);
- if (expunges == NULL)
+ ctx->expunges = mail_modifylog_uid_get_expunges(ctx->index->modifylog,
+ ctx->num1, ctx->num2,
+ &expunges_before);
+ if (ctx->expunges == NULL)
return -1;
- expunges_found = expunges->uid1 != 0;
+ if (ctx->expunges->uid1 != 0)
+ ctx->expunges_found = TRUE;
- rec = index->lookup_uid_range(index, uid, uid2, &idx_seq);
- if (rec == NULL)
- return expunges_found ? 2 : 1;
+ /* get the first message */
+ ctx->mail.rec = ctx->index->lookup_uid_range(ctx->index,
+ ctx->num1, ctx->num2,
+ &ctx->mail.idx_seq);
+ if (ctx->mail.rec == NULL) {
+ return ctx->index->get_last_error(ctx->index) ==
+ MAIL_INDEX_ERROR_NONE ? 1 : -1;
+ }
- client_seq = idx_seq + expunges_before;
- while (rec != NULL && rec->uid <= uid2) {
- while (expunges->uid1 != 0 && expunges->uid1 < rec->uid) {
- i_assert(expunges->uid2 < rec->uid);
+ ctx->mail.client_seq = ctx->mail.idx_seq + expunges_before;
+ return 0;
+}
- client_seq += expunges->seq_count;
- expunges++;
- }
- i_assert(!(expunges->uid1 <= rec->uid &&
- expunges->uid2 >= rec->uid));
+static int seqset_init(struct messageset_context *ctx)
+{
+ unsigned int expunges_before;
- t_push();
- if (!callback(index, rec, client_seq, idx_seq, context)) {
- t_pop();
- return 0;
- }
- t_pop();
+ if (ctx->num1 == (unsigned int)-1)
+ ctx->num1 = ctx->messages_count;
- client_seq++; idx_seq++;
- rec = index->next(index, rec);
- }
+ if (ctx->num2 == (unsigned int)-1)
+ ctx->num2 = ctx->messages_count;
- if (rec == NULL &&
- index->get_last_error(index) != MAIL_INDEX_ERROR_NONE) {
- /* error occured */
+ /* get list of expunged messages in our range. the expunges_before
+ can be used to calculate the current real sequence position */
+ ctx->expunges = mail_modifylog_seq_get_expunges(ctx->index->modifylog,
+ ctx->num1, ctx->num2,
+ &expunges_before);
+ if (ctx->expunges == NULL)
return -1;
+
+ i_assert(expunges_before < ctx->num1);
+ if (ctx->expunges->uid1 != 0)
+ ctx->expunges_found = TRUE;
+
+ /* get the first non-expunged message. note that if all messages
+ were expunged in the range, this points outside wanted range. */
+ ctx->mail.idx_seq = ctx->num1 - expunges_before;
+ ctx->mail.rec = ctx->index->lookup(ctx->index, ctx->mail.idx_seq);
+ if (ctx->mail.rec == NULL) {
+ return ctx->index->get_last_error(ctx->index) ==
+ MAIL_INDEX_ERROR_NONE ? 1 : -1;
}
- return expunges_found ? 2 : 1;
+ ctx->mail.client_seq = ctx->num1;
+ return 0;
}
-static int mail_index_uidset_foreach(struct mail_index *index,
- const char *uidset,
- unsigned int messages_count,
- msgset_foreach_callback_t callback,
- void *context, const char **error)
+const struct messageset_mail *
+index_messageset_next(struct messageset_context *ctx)
{
- struct mail_index_record *rec;
- const char *input;
- unsigned int uid, uid2;
- int ret, all_found;
+ struct messageset_mail *mail = &ctx->mail;
+ int last;
- i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
+ if (ctx->ret != 0)
+ return NULL;
- *error = NULL;
+ if (!ctx->uidset)
+ last = mail->rec == NULL || mail->client_seq >= ctx->num2;
+ else
+ last = mail->rec == NULL || mail->rec->uid >= ctx->num2;
- all_found = TRUE;
- input = uidset;
- while (*input != '\0') {
- if (*input == '*') {
- /* last message */
- if (messages_count == 0)
- uid = 0;
- else {
- rec = index->lookup(index, messages_count);
- uid = rec == NULL ? 0 : rec->uid;
- }
- input++;
- } else {
- uid = get_next_number(&input);
- if (uid == 0) {
- *error = t_strconcat("Invalid uidset: ",
- uidset, NULL);
- return -2;
+ if (!last) {
+ mail->rec = ctx->index->next(ctx->index, mail->rec);
+ mail->client_seq++;
+ mail->idx_seq++;
+ } else {
+ do {
+ if (ctx->p != NULL && *ctx->p == '\0') {
+ /* finished */
+ ctx->ret = 1;
+ return NULL;
}
- }
- if (*input != ':')
- uid2 = uid;
- else {
- /* first:last range */
- input++;
-
- if (*input != '*') {
- uid2 = get_next_number(&input);
- if (uid2 == 0) {
- *error = t_strconcat("Invalid uidset: ",
- uidset, NULL);
- return -2;
- }
- } else {
- uid2 = index->header->next_uid-1;
- input++;
+ if (!messageset_parse_next(ctx)) {
+ ctx->ret = -2;
+ return NULL;
}
- }
- if (*input == ',')
- input++;
- else if (*input != '\0') {
- *error = t_strdup_printf("Unexpected char '%c' with "
- "uidset: %s", *input, uidset);
- return -2;
- }
+ if (ctx->uidset)
+ ctx->ret = uidset_init(ctx);
+ else
+ ctx->ret = seqset_init(ctx);
+ } while (ctx->ret == 1);
- t_push();
- ret = mail_index_uid_foreach(index, uid, uid2,
- callback, context);
- t_pop();
- if (ret <= 0)
- return ret;
- if (ret == 2)
- all_found = FALSE;
+ if (ctx->ret != 0)
+ return NULL;
}
- return all_found ? 1 : 2;
-}
-
-int index_messageset_foreach(struct index_mailbox *ibox,
- const char *messageset, int uidset,
- msgset_foreach_callback_t callback, void *context)
-{
- const char *error;
- int ret;
+ /* fix client_seq */
+ while (ctx->expunges->uid1 != 0 &&
+ ctx->expunges->uid1 < mail->rec->uid) {
+ i_assert(ctx->expunges->uid2 < mail->rec->uid);
- if (uidset) {
- ret = mail_index_uidset_foreach(ibox->index, messageset,
- ibox->synced_messages_count,
- callback, context, &error);
- } else {
- ret = mail_index_messageset_foreach(ibox->index, messageset,
- ibox->synced_messages_count,
- callback, context, &error);
+ mail->client_seq += ctx->expunges->seq_count;
+ ctx->expunges++;
}
- if (ret < 0) {
- if (ret == -2) {
- /* user error */
- mail_storage_set_syntax_error(ibox->box.storage,
- "%s", error);
- } else {
- mail_storage_set_index_error(ibox);
- }
+ i_assert(!(ctx->expunges->uid1 <= mail->rec->uid &&
+ ctx->expunges->uid2 >= mail->rec->uid));
+
+ if (!ctx->uidset && mail->client_seq > ctx->num2) {
+ /* finished this set - see if there's more */
+ return index_messageset_next(ctx);
}
- return ret;
+ return mail;
}
Index: index-messageset.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-messageset.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- index-messageset.h 11 Jan 2003 19:55:57 -0000 1.5
+++ index-messageset.h 20 Jan 2003 14:52:51 -0000 1.6
@@ -1,20 +1,29 @@
#ifndef __INDEX_MESSAGESET_H
#define __INDEX_MESSAGESET_H
-#include "index-storage.h"
+struct index_mailbox;
-/* If FALSE is returned, the loop is stopped. */
-typedef int (*msgset_foreach_callback_t)(struct mail_index *index,
- struct mail_index_record *rec,
- unsigned int client_seq,
- unsigned int idx_seq,
- void *context);
+struct messageset_mail {
+ struct mail_index_record *rec;
+ unsigned int client_seq;
+ unsigned int idx_seq;
+};
-/* Returns 1 if all were found, 2 if some messages were deleted,
- 0 callback returned FALSE, -1 if internal error occured or -2 if messageset
- was invalid. */
-int index_messageset_foreach(struct index_mailbox *ibox,
- const char *messageset, int uidset,
- msgset_foreach_callback_t callback, void *context);
+struct messageset_context;
+
+struct messageset_context *
+index_messageset_init(struct index_mailbox *ibox,
+ const char *messageset, int uidset);
+
+struct messageset_context *
+index_messageset_init_range(struct index_mailbox *ibox,
+ unsigned int num1, unsigned int num2, int uidset);
+
+/* Returns 1 if all were found, 0 if some messages were deleted,
+ -1 if internal error occured or -2 if messageset was invalid. */
+int index_messageset_deinit(struct messageset_context *ctx);
+
+const struct messageset_mail *
+index_messageset_next(struct messageset_context *ctx);
#endif
Index: index-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-search.c,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- index-search.c 13 Jan 2003 21:29:09 -0000 1.64
+++ index-search.c 20 Jan 2003 14:52:51 -0000 1.65
@@ -2,21 +2,19 @@
#include "lib.h"
#include "istream.h"
-#include "ostream.h"
-#include "mmap-util.h"
+#include "str.h"
+#include "message-address.h"
#include "message-date.h"
-#include "message-size.h"
#include "message-body-search.h"
#include "message-header-search.h"
#include "imap-date.h"
#include "imap-envelope.h"
#include "index-storage.h"
-#include "index-sort.h"
-#include "mail-index-util.h"
-#include "mail-modifylog.h"
+#include "index-messageset.h"
+#include "index-mail.h"
#include "mail-custom-flags.h"
+#include "mail-modifylog.h"
#include "mail-search.h"
-#include "mail-thread.h"
#include <stdlib.h>
#include <ctype.h>
@@ -29,24 +27,23 @@
#define TXT_UNKNOWN_CHARSET "[BADCHARSET] Unknown charset"
#define TXT_INVALID_SEARCH_KEY "Invalid search key"
-struct search_index_context {
- pool_t hdr_pool;
+struct mail_search_context {
struct index_mailbox *ibox;
- struct mail_index_record *rec;
- unsigned int client_seq;
- const char *charset;
- const char *error;
+ char *charset;
+ struct mail_search_arg *args;
- unsigned int cached:1;
- unsigned int threading:1;
+ struct messageset_context *msgset_ctx;
+ struct index_mail imail;
+ struct mail *mail;
- /* for threading: */
- const char *message_id, *in_reply_to, *references;
- time_t sent_date;
+ pool_t hdr_pool;
+ const char *error;
+
+ int failed;
};
struct search_header_context {
- struct search_index_context *index_context;
+ struct mail_search_context *index_context;
struct mail_search_arg *args;
const unsigned char *name, *value;
@@ -57,13 +54,11 @@
};
struct search_body_context {
- struct search_index_context *index_ctx;
+ struct mail_search_context *index_ctx;
struct istream *input;
- struct message_part *part;
+ const struct message_part *part;
};
-static enum mail_sort_type sort_unsorted[] = { MAIL_SORT_END };
-
static int msgset_contains(const char *set, unsigned int match_num,
unsigned int max_num)
{
@@ -175,7 +170,7 @@
{
switch (type) {
case SEARCH_ALL:
- return TRUE;
+ return 1;
case SEARCH_SET:
return msgset_contains(value, client_seq,
ibox->synced_messages_count);
@@ -206,9 +201,10 @@
static void search_index_arg(struct mail_search_arg *arg, void *context)
{
- struct search_index_context *ctx = context;
+ struct mail_search_context *ctx = context;
- switch (search_arg_match_index(ctx->ibox, ctx->rec, ctx->client_seq,
+ switch (search_arg_match_index(ctx->ibox, ctx->imail.data.rec,
+ ctx->mail->seq,
arg->type, arg->value.str)) {
case -1:
/* unknown */
@@ -222,19 +218,8 @@
}
}
-static struct imap_message_cache *
-search_open_cache(struct search_index_context *ctx)
-{
- if (!ctx->cached) {
- (void)index_msgcache_open(ctx->ibox->cache,
- ctx->ibox->index, ctx->rec, 0);
- ctx->cached = TRUE;
- }
- return ctx->ibox->cache;
-}
-
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
-static int search_arg_match_cached(struct search_index_context *ctx,
+static int search_arg_match_cached(struct mail_search_context *ctx,
enum mail_search_arg_type type,
const char *value)
{
@@ -246,8 +231,7 @@
case SEARCH_BEFORE:
case SEARCH_ON:
case SEARCH_SINCE:
- internal_date = imap_msgcache_get_internal_date(
- search_open_cache(ctx));
+ internal_date = ctx->mail->get_received_date(ctx->mail);
if (internal_date == (time_t)-1)
return -1;
@@ -270,8 +254,7 @@
/* sizes */
case SEARCH_SMALLER:
case SEARCH_LARGER:
- virtual_size = imap_msgcache_get_virtual_size(
- search_open_cache(ctx));
+ virtual_size = ctx->mail->get_size(ctx->mail);
if (virtual_size == (uoff_t)-1)
return -1;
@@ -288,7 +271,7 @@
static void search_cached_arg(struct mail_search_arg *arg, void *context)
{
- struct search_index_context *ctx = context;
+ struct mail_search_context *ctx = context;
switch (search_arg_match_cached(ctx, arg->type,
arg->value.str)) {
@@ -318,7 +301,8 @@
/* NOTE: Latest IMAP4rev1 draft specifies that timezone is ignored
in searches. sent_time is returned as UTC, so change it. */
- if (!message_date_parse(sent_value, &sent_time, &timezone_offset))
+ if (!message_date_parse((const unsigned char *) sent_value, (size_t)-1,
+ &sent_time, &timezone_offset))
return 0;
sent_time -= timezone_offset * 60;
@@ -336,7 +320,7 @@
}
static struct header_search_context *
-search_header_context(struct search_index_context *ctx,
+search_header_context(struct mail_search_context *ctx,
struct mail_search_arg *arg)
{
int unknown_charset;
@@ -363,7 +347,7 @@
}
/* Returns >0 = matched, 0 = not matched, -1 = unknown */
-static int search_arg_match_envelope(struct search_index_context *ctx,
+static int search_arg_match_envelope(struct mail_search_context *ctx,
struct mail_search_arg *arg)
{
struct mail_index *index = ctx->ibox->index;
@@ -408,7 +392,8 @@
t_push();
/* get field from hopefully cached envelope */
- envelope = index->lookup_field(index, ctx->rec, DATA_FIELD_ENVELOPE);
+ envelope = index->lookup_field(index, ctx->imail.data.rec,
+ DATA_FIELD_ENVELOPE);
if (envelope != NULL) {
ret = imap_envelope_parse(envelope, env_field,
IMAP_ENVELOPE_RESULT_TYPE_STRING,
@@ -457,7 +442,7 @@
static void search_envelope_arg(struct mail_search_arg *arg, void *context)
{
- struct search_index_context *ctx = context;
+ struct mail_search_context *ctx = context;
switch (search_arg_match_envelope(ctx, arg)) {
case -1:
@@ -534,13 +519,24 @@
} else {
t_push();
- /* then check if the value matches */
hdr_search_ctx = search_header_context(ctx->index_context, arg);
if (hdr_search_ctx == NULL)
ret = 0;
- else {
- len = ctx->value_len;
- ret = message_header_search(ctx->value, len,
+ else if (arg->type == SEARCH_FROM || arg->type == SEARCH_TO ||
+ arg->type == SEARCH_CC || arg->type == SEARCH_BCC) {
+ /* we have to match against normalized address */
+ struct message_address *addr;
+ string_t *str;
+
+ addr = message_address_parse(data_stack_pool,
+ ctx->value, ctx->value_len,
+ 0);
+ str = t_str_new(ctx->value_len);
+ message_address_write(str, addr);
+ ret = message_header_search(str_data(str), str_len(str),
+ hdr_search_ctx) ? 1 : 0;
+ } else {
+ ret = message_header_search(ctx->value, ctx->value_len,
hdr_search_ctx) ? 1 : 0;
}
t_pop();
@@ -549,34 +545,15 @@
ARG_SET_RESULT(arg, ret);
}
-static void search_header(struct message_part *part __attr_unused__,
+static void search_header(struct message_part *part,
const unsigned char *name, size_t name_len,
const unsigned char *value, size_t value_len,
void *context)
{
struct search_header_context *ctx = context;
- int timezone_offset;
-
- if (ctx->threading) {
- struct search_index_context *ictx = ctx->index_context;
- if (name_len == 10 && memcasecmp(name, "Message-ID", 10) == 0)
- ictx->message_id = t_strndup(value, value_len);
- else if (name_len == 11 &&
- memcasecmp(name, "In-Reply-To", 11) == 0)
- ictx->in_reply_to = t_strndup(value, value_len);
- else if (name_len == 10 &&
- memcasecmp(name, "References", 10) == 0)
- ictx->references = t_strndup(value, value_len);
- else if (name_len == 4 && memcasecmp(name, "Date", 4) == 0) {
- t_push();
- if (!message_date_parse(t_strndup(value, value_len),
- &ictx->sent_date,
- &timezone_offset))
- ictx->sent_date = 0;
- t_pop();
- }
- }
+ index_mail_parse_header(part, name, name_len, value, value_len,
+ ctx->index_context->mail);
if ((ctx->custom_header && name_len > 0) ||
(name_len == 4 && memcasecmp(name, "Date", 4) == 0) ||
@@ -620,36 +597,39 @@
}
static int search_arg_match_text(struct mail_search_arg *args,
- struct search_index_context *ctx)
+ struct mail_search_context *ctx)
{
struct istream *input;
int have_headers, have_body, have_text;
/* first check what we need to use */
mail_search_args_analyze(args, &have_headers, &have_body, &have_text);
- if (ctx->threading)
- have_headers = TRUE;
if (!have_headers && !have_body && !have_text)
return TRUE;
if (have_headers || have_text) {
struct search_header_context hdr_ctx;
- if (!imap_msgcache_get_data(search_open_cache(ctx), &input))
+ input = ctx->mail->get_stream(ctx->mail, NULL, NULL);
+ if (input == NULL)
return FALSE;
memset(&hdr_ctx, 0, sizeof(hdr_ctx));
hdr_ctx.index_context = ctx;
hdr_ctx.custom_header = TRUE;
hdr_ctx.args = args;
- hdr_ctx.threading = ctx->threading;
+ index_mail_init_parse_header(&ctx->imail);
message_parse_header(NULL, input, NULL,
search_header, &hdr_ctx);
} else {
- if (!imap_msgcache_get_rfc822(search_open_cache(ctx), &input,
- NULL, NULL))
+ struct message_size hdr_size;
+
+ input = ctx->mail->get_stream(ctx->mail, &hdr_size, NULL);
+ if (input == NULL)
return FALSE;
+
+ i_stream_seek(input, hdr_size.physical_size);
}
if (have_text || have_body) {
@@ -658,7 +638,7 @@
memset(&body_ctx, 0, sizeof(body_ctx));
body_ctx.index_ctx = ctx;
body_ctx.input = input;
- body_ctx.part = imap_msgcache_get_parts(search_open_cache(ctx));
+ body_ctx.part = ctx->mail->get_parts(ctx->mail);
mail_search_args_foreach(args, search_body, &body_ctx);
}
@@ -706,7 +686,7 @@
}
static int search_get_sequid(struct index_mailbox *ibox,
- struct mail_search_arg *args,
+ const struct mail_search_arg *args,
unsigned int *first_seq, unsigned int *last_seq,
unsigned int *first_uid, unsigned int *last_uid)
{
@@ -744,7 +724,7 @@
}
static int search_limit_by_flags(struct index_mailbox *ibox,
- struct mail_search_arg *args,
+ const struct mail_search_arg *args,
unsigned int *first_uid,
unsigned int *last_uid)
{
@@ -809,8 +789,10 @@
return FALSE;
}
- (void)mail_modifylog_seq_get_expunges(ibox->index->modifylog, seq, seq,
- &expunges_before);
+ if (mail_modifylog_seq_get_expunges(ibox->index->modifylog, seq, seq,
+ &expunges_before) == NULL)
+ return FALSE;
+
seq -= expunges_before;
rec = ibox->index->lookup(ibox->index, seq);
@@ -819,7 +801,7 @@
}
static int search_get_uid_range(struct index_mailbox *ibox,
- struct mail_search_arg *args,
+ const struct mail_search_arg *args,
unsigned int *first_uid, unsigned int *last_uid)
{
unsigned int first_seq, last_seq, uid;
@@ -868,180 +850,143 @@
return 1;
}
-static int search_messages(struct index_mailbox *ibox, const char *charset,
- struct mail_search_arg *args,
- struct mail_sort_context *sort_ctx,
- struct mail_thread_context *thread_ctx,
- struct index_sort_context *index_sort_ctx,
- struct ostream *output, int uid_result)
+int index_storage_search_get_sorting(struct mailbox *box __attr_unused__,
+ enum mail_sort_type *sort_program)
{
- struct search_index_context ctx;
- struct mail_index_record *rec;
- struct mail_search_arg *arg;
- const struct modify_log_expunge *expunges;
- unsigned int first_uid, last_uid, client_seq, expunges_before;
- const char *str;
- int found, failed;
+ /* currently we don't support sorting */
+ *sort_program = MAIL_SORT_END;
+ return TRUE;
+}
+
+struct mail_search_context *
+index_storage_search_init(struct mailbox *box, const char *charset,
+ struct mail_search_arg *args,
+ const enum mail_sort_type *sort_program,
+ enum mail_fetch_field wanted_fields,
+ const char *const wanted_headers[])
+{
+ struct index_mailbox *ibox = (struct index_mailbox *) box;
+ struct mail_search_context *ctx;
+ unsigned int first_uid, last_uid;
+
+ if (sort_program != NULL && *sort_program != MAIL_SORT_END) {
+ i_error("BUG: index_storage_search_init(): "
+ "invalid sort_program");
+ return NULL;
+ }
+
+ if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
+ return NULL;
+
+ ctx = i_new(struct mail_search_context, 1);
+ ctx->ibox = ibox;
+ ctx->charset = i_strdup(charset);
+ ctx->args = args;
+
+ ctx->mail = (struct mail *) &ctx->imail;
+ index_mail_init(ibox, &ctx->imail, wanted_fields, wanted_headers);
if (ibox->synced_messages_count == 0)
- return TRUE;
+ return ctx;
/* see if we can limit the records we look at */
switch (search_get_uid_range(ibox, args, &first_uid, &last_uid)) {
case -1:
/* error */
- return FALSE;
+ ctx->failed = TRUE;
+ return ctx;
case 0:
/* nothing found */
- return TRUE;
+ return ctx;
}
- rec = ibox->index->lookup_uid_range(ibox->index, first_uid, last_uid,
- &client_seq);
- if (rec == NULL)
- return TRUE;
-
- expunges = mail_modifylog_uid_get_expunges(ibox->index->modifylog,
- rec->uid, last_uid,
- &expunges_before);
- client_seq += expunges_before;
- index_sort_ctx->synced_sequences = expunges->uid1 == 0;
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.ibox = ibox;
- ctx.charset = charset;
- ctx.threading = thread_ctx != NULL;
-
- for (; rec != NULL && rec->uid <= last_uid; client_seq++) {
- while (expunges->uid1 != 0 && expunges->uid1 < rec->uid) {
- i_assert(expunges->uid2 < rec->uid);
-
- client_seq += expunges->seq_count;
- expunges++;
- }
- i_assert(!(expunges->uid1 <= rec->uid &&
- expunges->uid2 >= rec->uid));
-
- ctx.rec = rec;
- ctx.client_seq = client_seq;
- ctx.cached = FALSE;
-
- ctx.message_id = ctx.in_reply_to = ctx.references = NULL;
-
- mail_search_args_reset(args);
+ ctx->msgset_ctx =
+ index_messageset_init_range(ibox, first_uid, last_uid, TRUE);
+ return ctx;
+}
- t_push();
+int index_storage_search_deinit(struct mail_search_context *ctx)
+{
+ int ret;
- mail_search_args_foreach(args, search_index_arg, &ctx);
- mail_search_args_foreach(args, search_cached_arg, &ctx);
- mail_search_args_foreach(args, search_envelope_arg, &ctx);
- failed = !search_arg_match_text(args, &ctx);
- imap_msgcache_close(ibox->cache);
+ ret = !ctx->failed && ctx->error == NULL;
- if (ctx.error != NULL) {
- t_pop();
- break;
- }
+ if (ctx->msgset_ctx != NULL) {
+ if (index_messageset_deinit(ctx->msgset_ctx) < 0)
+ ret = FALSE;
+ }
- if (!failed) {
- found = TRUE;
- for (arg = args; arg != NULL; arg = arg->next) {
- if (arg->result != 1) {
- found = FALSE;
- break;
- }
- }
+ if (!index_storage_lock(ctx->ibox, MAIL_LOCK_UNLOCK))
+ ret = FALSE;
- if (found) {
- unsigned int id = uid_result ?
- rec->uid : client_seq;
+ if (ctx->error != NULL) {
+ mail_storage_set_error(ctx->ibox->box.storage,
+ "%s", ctx->error);
+ }
- index_sort_ctx->current_client_seq = client_seq;
- index_sort_ctx->current_rec = rec;
+ if (ctx->hdr_pool != NULL)
+ pool_unref(ctx->hdr_pool);
- if (sort_ctx != NULL)
- mail_sort_input(sort_ctx, id);
- else if (thread_ctx != NULL) {
- mail_thread_input(thread_ctx, id,
- ctx.message_id,
- ctx.in_reply_to,
- ctx.references,
- ctx.sent_date);
- } else {
- o_stream_send(output, " ", 1);
+ if (ctx->ibox->fetch_mail.pool != NULL)
+ index_mail_deinit(&ctx->ibox->fetch_mail);
+ index_mail_deinit(&ctx->imail);
+ i_free(ctx);
+ return ret;
+}
- str = dec2str(id);
- o_stream_send_str(output, str);
- }
- }
- }
- t_pop();
+struct mail *index_storage_search_next(struct mail_search_context *ctx)
+{
+ const struct messageset_mail *msgset_mail;
+ struct mail_search_arg *arg;
+ int found, ret;
- rec = ibox->index->next(ibox->index, rec);
+ if (ctx->msgset_ctx == NULL) {
+ /* initialization failed or didn't found any messages */
+ return NULL;
}
- if (ctx.hdr_pool != NULL)
- pool_unref(ctx.hdr_pool);
-
- if (ctx.error != NULL)
- mail_storage_set_error(ibox->box.storage, "%s", ctx.error);
- return ctx.error == NULL;
-}
+ do {
+ msgset_mail = index_messageset_next(ctx->msgset_ctx);
+ if (msgset_mail == NULL)
+ return NULL;
-int index_storage_search(struct mailbox *box, const char *charset,
- struct mail_search_arg *args,
- enum mail_sort_type *sorting,
- enum mail_thread_type threading,
- struct ostream *output, int uid_result)
-{
- struct index_mailbox *ibox = (struct index_mailbox *) box;
- struct mail_sort_context *sort_ctx;
- struct mail_thread_context *thread_ctx;
- struct index_sort_context index_sort_ctx;
- int failed;
+ ctx->mail->seq = msgset_mail->client_seq;
+ ctx->mail->uid = msgset_mail->rec->uid;
+ ret = index_mail_next(&ctx->imail, msgset_mail->rec);
- if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
- return FALSE;
+ if (ret < 0)
+ return NULL;
- if (sorting != NULL) {
- memset(&index_sort_ctx, 0, sizeof(index_sort_ctx));
- index_sort_ctx.ibox = ibox;
- index_sort_ctx.output = output;
- index_sort_ctx.id_is_uid = uid_result;
+ if (ret == 0)
+ found = FALSE;
+ else {
+ mail_search_args_reset(ctx->args);
- thread_ctx = NULL;
- sort_ctx = mail_sort_init(sort_unsorted, sorting, output,
- &index_sort_callbacks,
- &index_sort_ctx);
- o_stream_send_str(output, "* SORT");
- } else if (threading != MAIL_THREAD_NONE) {
- memset(&index_sort_ctx, 0, sizeof(index_sort_ctx));
- index_sort_ctx.ibox = ibox;
- index_sort_ctx.id_is_uid = uid_result;
+ t_push();
- sort_ctx = NULL;
- thread_ctx = mail_thread_init(threading, output,
- &index_sort_callbacks,
- &index_sort_ctx);
- o_stream_send_str(output, "* THREAD");
- } else {
- memset(&index_sort_ctx, 0, sizeof(index_sort_ctx));
- sort_ctx = NULL;
- thread_ctx = NULL;
- o_stream_send_str(output, "* SEARCH");
- }
+ mail_search_args_foreach(ctx->args, search_index_arg,
+ ctx);
+ mail_search_args_foreach(ctx->args, search_cached_arg,
+ ctx);
+ mail_search_args_foreach(ctx->args, search_envelope_arg,
+ ctx);
+ found = search_arg_match_text(ctx->args, ctx);
- failed = !search_messages(ibox, charset, args, sort_ctx, thread_ctx,
- &index_sort_ctx, output, uid_result);
- if (sort_ctx != NULL)
- mail_sort_deinit(sort_ctx);
- if (thread_ctx != NULL)
- mail_thread_finish(thread_ctx);
+ t_pop();
- o_stream_send(output, "\r\n", 2);
+ if (ctx->error != NULL)
+ return NULL;
+ }
- if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
- return FALSE;
+ if (found) {
+ for (arg = ctx->args; arg != NULL; arg = arg->next) {
+ if (arg->result != 1) {
+ found = FALSE;
+ break;
+ }
+ }
+ }
+ } while (!found);
- return !failed;
+ return ctx->mail;
}
Index: index-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-storage.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- index-storage.c 10 Jan 2003 11:29:24 -0000 1.25
+++ index-storage.c 20 Jan 2003 14:52:51 -0000 1.26
@@ -227,7 +227,6 @@
ibox->box.allow_custom_flags = TRUE;
ibox->index = index;
- ibox->cache = imap_msgcache_alloc(&index_msgcache_iface);
ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
index->set_lock_notify_callback(index, lock_notify, ibox);
@@ -266,7 +265,6 @@
struct index_mailbox *ibox = (struct index_mailbox *) box;
index_mailbox_check_remove(ibox);
- imap_msgcache_free(ibox->cache);
if (ibox->index != NULL)
index_storage_unref(ibox->index);
@@ -316,13 +314,14 @@
int index_mailbox_fix_custom_flags(struct index_mailbox *ibox,
enum mail_flags *flags,
- const char *custom_flags[])
+ const char *custom_flags[],
+ unsigned int custom_flags_count)
{
int ret;
ret = mail_custom_flags_fix_list(ibox->index->custom_flags,
flags, custom_flags,
- MAIL_CUSTOM_FLAGS_COUNT);
+ custom_flags_count);
switch (ret) {
case 1:
return TRUE;
Index: index-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-storage.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- index-storage.h 10 Jan 2003 11:29:24 -0000 1.28
+++ index-storage.h 20 Jan 2003 14:52:51 -0000 1.29
@@ -3,7 +3,7 @@
#include "mail-storage.h"
#include "mail-index.h"
-#include "imap-message-cache.h"
+#include "index-mail.h"
struct index_mailbox {
struct mailbox box;
@@ -13,13 +13,13 @@
int (*expunge_locked)(struct index_mailbox *ibox, int notify);
struct mail_index *index;
- struct imap_message_cache *cache;
char *check_path;
struct timeout *check_to;
time_t check_file_stamp;
time_t last_check;
+ struct index_mail fetch_mail; /* fetch_uid() or fetch_seq() */
unsigned int synced_messages_count;
time_t next_lock_notify; /* temporary */
@@ -28,8 +28,6 @@
unsigned int delay_save_unlocking:1; /* For COPYing inside mailbox */
};
-extern struct imap_message_cache_iface index_msgcache_iface;
-
int mail_storage_set_index_error(struct index_mailbox *ibox);
void index_storage_init_lock_notify(struct index_mailbox *ibox);
int index_storage_lock(struct index_mailbox *ibox,
@@ -51,7 +49,8 @@
int index_mailbox_fix_custom_flags(struct index_mailbox *ibox,
enum mail_flags *flags,
- const char *custom_flags[]);
+ const char *custom_flags[],
+ unsigned int custom_flags_count);
unsigned int index_storage_get_recent_count(struct mail_index *index);
@@ -65,10 +64,6 @@
struct istream *input, struct ostream *output,
uoff_t data_size);
-int index_msgcache_open(struct imap_message_cache *cache,
- struct mail_index *index, struct mail_index_record *rec,
- enum imap_cache_field fields);
-
void index_mailbox_check_add(struct index_mailbox *ibox, const char *path);
void index_mailbox_check_remove(struct index_mailbox *ibox);
@@ -84,16 +79,31 @@
struct mailbox_status *status);
int index_storage_sync(struct mailbox *box, int sync_expunges);
int index_storage_update_flags(struct mailbox *box, const char *messageset,
- int uidset, enum mail_flags flags,
- const char *custom_flags[],
+ int uidset, const struct mail_full_flags *flags,
enum modify_type modify_type, int notify,
int *all_found);
-int index_storage_fetch(struct mailbox *box, struct mail_fetch_data *fetch_data,
- struct ostream *output, int *all_found);
-int index_storage_search(struct mailbox *box, const char *charset,
- struct mail_search_arg *args,
- enum mail_sort_type *sorting,
- enum mail_thread_type threading,
- struct ostream *output, int uid_result);
+
+struct mail_fetch_context *
+index_storage_fetch_init(struct mailbox *box,
+ enum mail_fetch_field wanted_fields, int *update_seen,
+ const char *messageset, int uidset);
+int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found);
+struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx);
+
+struct mail *index_storage_fetch_uid(struct mailbox *box, unsigned int uid,
+ enum mail_fetch_field wanted_fields);
+struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
+ enum mail_fetch_field wanted_fields);
+
+int index_storage_search_get_sorting(struct mailbox *box,
+ enum mail_sort_type *sort_program);
+struct mail_search_context *
+index_storage_search_init(struct mailbox *box, const char *charset,
+ struct mail_search_arg *args,
+ const enum mail_sort_type *sort_program,
+ enum mail_fetch_field wanted_fields,
+ const char *const wanted_headers[]);
+int index_storage_search_deinit(struct mail_search_context *ctx);
+struct mail *index_storage_search_next(struct mail_search_context *ctx);
#endif
Index: index-update-flags.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-update-flags.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- index-update-flags.c 11 Jan 2003 19:55:57 -0000 1.17
+++ index-update-flags.c 20 Jan 2003 14:52:51 -0000 1.18
@@ -5,78 +5,76 @@
#include "index-messageset.h"
#include "mail-custom-flags.h"
-struct update_context {
- struct index_mailbox *ibox;
- enum mail_flags flags;
- enum modify_type modify_type;
- int notify;
-};
-
-static int update_cb(struct mail_index *index, struct mail_index_record *rec,
- unsigned int client_seq, unsigned int idx_seq,
- void *context)
+static int update_messageset(struct messageset_context *ctx,
+ struct index_mailbox *ibox, enum mail_flags flags,
+ enum modify_type modify_type, int notify)
{
- struct update_context *ctx = context;
struct mail_storage *storage;
- enum mail_flags flags;
+ const struct messageset_mail *mail;
const char **custom_flags;
+ enum mail_flags new_flags;
- switch (ctx->modify_type) {
- case MODIFY_ADD:
- flags = rec->msg_flags | ctx->flags;
- break;
- case MODIFY_REMOVE:
- flags = rec->msg_flags & ~ctx->flags;
- break;
- case MODIFY_REPLACE:
- flags = ctx->flags;
- break;
- default:
- i_unreached();
- }
+ storage = ibox->box.storage;
+ custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
- if (!index->update_flags(index, rec, idx_seq, flags, FALSE))
- return FALSE;
+ while ((mail = index_messageset_next(ctx)) != NULL) {
+ switch (modify_type) {
+ case MODIFY_ADD:
+ new_flags = mail->rec->msg_flags | flags;
+ break;
+ case MODIFY_REMOVE:
+ new_flags = mail->rec->msg_flags & ~flags;
+ break;
+ case MODIFY_REPLACE:
+ new_flags = flags;
+ break;
+ default:
+ i_unreached();
+ }
- storage = ctx->ibox->box.storage;
- if (mail_custom_flags_has_changes(index->custom_flags)) {
- storage->callbacks->new_custom_flags(&ctx->ibox->box,
- mail_custom_flags_list_get(index->custom_flags),
- MAIL_CUSTOM_FLAGS_COUNT, storage->callback_context);
- }
+ if (!ibox->index->update_flags(ibox->index, mail->rec,
+ mail->idx_seq, new_flags, FALSE))
+ return -1;
- if (ctx->notify) {
- if (rec->uid >= index->first_recent_uid)
- flags |= MAIL_RECENT;
+ if (mail_custom_flags_has_changes(ibox->index->custom_flags)) {
+ storage->callbacks->new_custom_flags(&ibox->box,
+ custom_flags, MAIL_CUSTOM_FLAGS_COUNT,
+ storage->callback_context);
+ }
- custom_flags = mail_custom_flags_list_get(index->custom_flags);
- storage->callbacks->update_flags(&ctx->ibox->box,
- client_seq, rec->uid,
- flags, custom_flags,
- MAIL_CUSTOM_FLAGS_COUNT,
- storage->callback_context);
+ if (notify) {
+ if (mail->rec->uid >= ibox->index->first_recent_uid)
+ new_flags |= MAIL_RECENT;
+
+ storage->callbacks->update_flags(&ibox->box,
+ mail->client_seq, mail->rec->uid, new_flags,
+ custom_flags, MAIL_CUSTOM_FLAGS_COUNT,
+ storage->callback_context);
+ }
}
- return TRUE;
+ return 1;
}
-int index_storage_update_flags(struct mailbox *box,
- const char *messageset, int uidset,
- enum mail_flags flags,
- const char *custom_flags[],
+int index_storage_update_flags(struct mailbox *box, const char *messageset,
+ int uidset, const struct mail_full_flags *flags,
enum modify_type modify_type, int notify,
int *all_found)
{
struct index_mailbox *ibox = (struct index_mailbox *) box;
- struct update_context ctx;
- int ret;
+ struct messageset_context *ctx;
+ enum mail_flags mail_flags;
+ int ret, ret2;
if (box->readonly) {
mail_storage_set_error(box->storage, "Mailbox is read-only");
return FALSE;
}
- if (!index_mailbox_fix_custom_flags(ibox, &flags, custom_flags))
+ mail_flags = flags->flags;
+ if (!index_mailbox_fix_custom_flags(ibox, &mail_flags,
+ flags->custom_flags,
+ flags->custom_flags_count))
return FALSE;
if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
@@ -85,18 +83,16 @@
if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_UNLOCK))
return FALSE;
- ctx.ibox = ibox;
- ctx.flags = flags & ~MAIL_RECENT; /* \Recent can't be changed */
- ctx.modify_type = modify_type;
- ctx.notify = notify;
+ mail_flags &= ~MAIL_RECENT; /* \Recent can't be changed */
- ret = index_messageset_foreach(ibox, messageset, uidset,
- update_cb, &ctx);
+ ctx = index_messageset_init(ibox, messageset, uidset);
+ ret = update_messageset(ctx, ibox, mail_flags, modify_type, notify);
+ ret2 = index_messageset_deinit(ctx);
if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
return FALSE;
if (all_found != NULL)
- *all_found = ret == 1;
- return ret >= 0;
+ *all_found = ret2 > 0;
+ return ret >= 0 && ret2 >= 0;
}
--- index-fetch-section.c DELETED ---
--- index-msgcache.c DELETED ---
--- index-sort.c DELETED ---
--- index-sort.h DELETED ---
More information about the dovecot-cvs
mailing list