summaryrefslogtreecommitdiffstats
path: root/src/lib-storage/list/mailbox-list-index.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-storage/list/mailbox-list-index.h')
-rw-r--r--src/lib-storage/list/mailbox-list-index.h240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/lib-storage/list/mailbox-list-index.h b/src/lib-storage/list/mailbox-list-index.h
new file mode 100644
index 0000000..a2ca620
--- /dev/null
+++ b/src/lib-storage/list/mailbox-list-index.h
@@ -0,0 +1,240 @@
+#ifndef MAILBOX_LIST_INDEX_H
+#define MAILBOX_LIST_INDEX_H
+
+/* Mailbox list index basically contains:
+
+ Header contains ID => name mapping. The name isn't the full mailbox name,
+ but rather each hierarchy level has its own ID and name. For example a
+ mailbox name "foo/bar" (with '/' as separator) would have separate IDs for
+ "foo" and "bar" names.
+
+ The records contain { parent_uid, uid, name_id } field that can be used to
+ build the whole mailbox tree. parent_uid=0 means root, otherwise it's the
+ parent node's uid.
+
+ Each record also contains GUID for each selectable mailbox. If a mailbox
+ is recreated using the same name, its GUID also changes. Note however that
+ the UID doesn't change, because the UID refers to the mailbox name, not to
+ the mailbox itself.
+
+ The records may contain also extensions for allowing mailbox_get_status()
+ to return values directly from the mailbox list index. Storage backends
+ may also add their own extensions to figure out if a record is up to date.
+*/
+
+#include "module-context.h"
+#include "mail-types.h"
+#include "mail-storage.h"
+#include "mailbox-list-private.h"
+
+#include <sys/time.h>
+
+#define MAILBOX_LIST_INDEX_HIERARCHY_SEP '~'
+#define MAILBOX_LIST_INDEX_HIERARCHY_ALT_SEP '^'
+
+#define INDEX_LIST_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, mailbox_list_index_module)
+#define INDEX_LIST_CONTEXT_REQUIRE(obj) \
+ MODULE_CONTEXT_REQUIRE(obj, mailbox_list_index_module)
+
+/* Should the STATUS information for this mailbox not be written to the
+ mailbox list index? */
+#define MAILBOX_IS_NEVER_IN_INDEX(box) \
+ ((box)->inbox_any && !(box)->storage->set->mailbox_list_index_include_inbox)
+
+struct mail_index_view;
+struct mailbox_index_vsize;
+struct mailbox_vfuncs;
+
+/* stored in mail_index_record.flags: */
+enum mailbox_list_index_flags {
+ MAILBOX_LIST_INDEX_FLAG_NONEXISTENT = MAIL_DELETED,
+ MAILBOX_LIST_INDEX_FLAG_NOSELECT = MAIL_DRAFT,
+ MAILBOX_LIST_INDEX_FLAG_NOINFERIORS = MAIL_ANSWERED,
+ MAILBOX_LIST_INDEX_FLAG_CORRUPTED_NAME = MAIL_SEEN,
+
+ /* set during syncing for mailboxes that still exist */
+ MAILBOX_LIST_INDEX_FLAG_SYNC_EXISTS = MAIL_FLAGGED
+};
+
+struct mailbox_list_index_header {
+ uint8_t refresh_flag;
+ /* array of { uint32_t id; char name[]; } */
+};
+
+struct mailbox_list_index_record {
+ /* points to given id in header */
+ uint32_t name_id;
+ /* parent mailbox's UID, 0 = root */
+ uint32_t parent_uid;
+
+ /* the following fields are temporarily zero while unknown,
+ also permanently zero for \NoSelect and \Nonexistent mailboxes: */
+
+ guid_128_t guid;
+ uint32_t uid_validity;
+};
+
+struct mailbox_list_index_msgs_record {
+ uint32_t messages;
+ uint32_t unseen;
+ uint32_t recent;
+ uint32_t uidnext;
+};
+
+struct mailbox_list_index_node {
+ struct mailbox_list_index_node *parent;
+ struct mailbox_list_index_node *next;
+ struct mailbox_list_index_node *children;
+
+ uint32_t name_id, uid;
+ enum mailbox_list_index_flags flags;
+ /* extension data is corrupted on disk - need to update it */
+ bool corrupted_ext;
+ /* flags are corrupted on disk - need to update it */
+ bool corrupted_flags;
+ const char *raw_name;
+};
+
+struct mailbox_list_index {
+ union mailbox_list_module_context module_ctx;
+
+ const char *path;
+ struct mail_index *index;
+ uint32_t ext_id, msgs_ext_id, hmodseq_ext_id, subs_hdr_ext_id;
+ uint32_t vsize_ext_id, first_saved_ext_id;
+ struct timeval last_refresh_timeval;
+
+ pool_t mailbox_pool;
+ /* uin32_t id => name */
+ HASH_TABLE(void *, char *) mailbox_names;
+ uint32_t highest_name_id;
+
+ struct mailbox_list_index_sync_context *sync_ctx;
+ uint32_t sync_log_file_seq;
+ uoff_t sync_log_file_offset;
+ uint32_t sync_stamp;
+ struct timeout *to_refresh;
+
+ /* uint32_t uid => node */
+ HASH_TABLE(void *, struct mailbox_list_index_node *) mailbox_hash;
+ struct mailbox_list_index_node *mailbox_tree;
+
+ bool pending_init:1;
+ bool opened:1;
+ bool syncing:1;
+ bool updating_status:1;
+ bool has_backing_store:1;
+ bool index_last_check_changed:1;
+ bool corrupted_names_or_parents:1;
+ bool handling_corruption:1;
+ bool call_corruption_callback:1;
+ bool rebuild_on_missing_inbox:1;
+ bool force_resynced:1;
+ bool force_resync_failed:1;
+};
+
+struct mailbox_list_index_iterate_context {
+ struct mailbox_list_iterate_context ctx;
+ pool_t mailbox_pool;
+
+ struct mailbox_info info;
+ pool_t info_pool;
+
+ size_t parent_len;
+ string_t *path;
+ struct mailbox_list_index_node *next_node;
+
+ bool failed:1;
+ bool prefix_inbox_list:1;
+};
+
+extern MODULE_CONTEXT_DEFINE(mailbox_list_index_module,
+ &mailbox_list_module_register);
+
+void mailbox_list_index_set_index_error(struct mailbox_list *list);
+struct mailbox_list_index_node *
+mailbox_list_index_lookup(struct mailbox_list *list, const char *name);
+struct mailbox_list_index_node *
+mailbox_list_index_lookup_uid(struct mailbox_list_index *ilist, uint32_t uid);
+void mailbox_list_index_node_get_path(const struct mailbox_list_index_node *node,
+ char sep, string_t *str);
+void mailbox_list_index_node_unlink(struct mailbox_list_index *ilist,
+ struct mailbox_list_index_node *node);
+
+int mailbox_list_index_index_open(struct mailbox_list *list);
+bool mailbox_list_index_need_refresh(struct mailbox_list_index *ilist,
+ struct mail_index_view *view);
+/* Refresh the index, but only if it hasn't been refreshed "recently"
+ (= within this same ioloop run) */
+int mailbox_list_index_refresh(struct mailbox_list *list);
+/* Refresh the index regardless of when the last refresh was done. */
+int mailbox_list_index_refresh_force(struct mailbox_list *list);
+void mailbox_list_index_refresh_later(struct mailbox_list *list);
+int mailbox_list_index_handle_corruption(struct mailbox_list *list);
+int mailbox_list_index_set_uncorrupted(struct mailbox_list *list);
+
+/* Returns TRUE and index_r if mailbox list index exists, FALSE if not. */
+bool mailbox_list_index_get_index(struct mailbox_list *list,
+ struct mail_index **index_r);
+/* Open mailbox list index's view and get the given mailbox's sequence number
+ in it. If require_refreshed is TRUE, the mailbox must have up-to-date
+ information in the mailbox list index. Returns 1 if ok, 0 if mailbox wasn't
+ found or it wasn't up-to-date as requested, -1 if there was an error. The
+ error is stored to the mailbox storage. */
+int mailbox_list_index_view_open(struct mailbox *box, bool require_refreshed,
+ struct mail_index_view **view_r,
+ uint32_t *seq_r);
+
+struct mailbox_list_index_node *
+mailbox_list_index_node_find_sibling(const struct mailbox_list *list,
+ struct mailbox_list_index_node *node,
+ const char *name);
+void mailbox_list_index_reset(struct mailbox_list_index *ilist);
+int mailbox_list_index_parse(struct mailbox_list *list,
+ struct mail_index_view *view, bool force);
+
+struct mailbox_list_iterate_context *
+mailbox_list_index_iter_init(struct mailbox_list *list,
+ const char *const *patterns,
+ enum mailbox_list_iter_flags flags);
+const struct mailbox_info *
+mailbox_list_index_iter_next(struct mailbox_list_iterate_context *ctx);
+int mailbox_list_index_iter_deinit(struct mailbox_list_iterate_context *ctx);
+
+bool mailbox_list_index_status(struct mailbox_list *list,
+ struct mail_index_view *view,
+ uint32_t seq, enum mailbox_status_items items,
+ struct mailbox_status *status_r,
+ uint8_t *mailbox_guid,
+ struct mailbox_index_vsize *vsize_r,
+ const char **reason_r);
+void mailbox_list_index_status_set_info_flags(struct mailbox *box, uint32_t uid,
+ enum mailbox_info_flags *flags);
+void mailbox_list_index_update_mailbox_index(struct mailbox *box,
+ const struct mailbox_update *update);
+
+int mailbox_list_index_notify_init(struct mailbox_list *list,
+ enum mailbox_list_notify_event mask,
+ struct mailbox_list_notify **notify_r);
+void mailbox_list_index_notify_deinit(struct mailbox_list_notify *notify);
+int mailbox_list_index_notify_next(struct mailbox_list_notify *notify,
+ const struct mailbox_list_notify_rec **rec_r);
+void mailbox_list_index_notify_wait(struct mailbox_list_notify *notify,
+ void (*callback)(void *context),
+ void *context);
+void mailbox_list_index_notify_flush(struct mailbox_list_notify *notify);
+
+void mailbox_list_index_status_init_mailbox(struct mailbox_vfuncs *v);
+bool mailbox_list_index_backend_init_mailbox(struct mailbox *box,
+ struct mailbox_vfuncs *v);
+void mailbox_list_index_status_init_finish(struct mailbox_list *list);
+
+void mailbox_list_index_status_sync_init(struct mailbox *box);
+void mailbox_list_index_status_sync_deinit(struct mailbox *box);
+
+void mailbox_list_index_backend_sync_init(struct mailbox *box,
+ enum mailbox_sync_flags flags);
+int mailbox_list_index_backend_sync_deinit(struct mailbox *box);
+
+#endif