summaryrefslogtreecommitdiffstats
path: root/src/doveadm/dsync/dsync-mailbox-tree.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/doveadm/dsync/dsync-mailbox-tree.h')
-rw-r--r--src/doveadm/dsync/dsync-mailbox-tree.h205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/doveadm/dsync/dsync-mailbox-tree.h b/src/doveadm/dsync/dsync-mailbox-tree.h
new file mode 100644
index 0000000..6969813
--- /dev/null
+++ b/src/doveadm/dsync/dsync-mailbox-tree.h
@@ -0,0 +1,205 @@
+#ifndef DSYNC_MAILBOX_TREE_H
+#define DSYNC_MAILBOX_TREE_H
+
+#include "guid.h"
+#include "mail-error.h"
+
+struct mail_namespace;
+struct dsync_brain;
+
+enum dsync_mailbox_trees_sync_type {
+ /* two-way sync for both mailboxes */
+ DSYNC_MAILBOX_TREES_SYNC_TYPE_TWOWAY,
+ /* make remote tree look exactly like the local tree */
+ DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_LOCAL,
+ /* make local tree look exactly like the remote tree */
+ DSYNC_MAILBOX_TREES_SYNC_TYPE_PRESERVE_REMOTE
+};
+
+enum dsync_mailbox_trees_sync_flags {
+ /* Enable debugging */
+ DSYNC_MAILBOX_TREES_SYNC_FLAG_DEBUG = 0x01,
+ /* Show ourself as "master brain" in the debug output */
+ DSYNC_MAILBOX_TREES_SYNC_FLAG_MASTER_BRAIN = 0x02,
+ /* Disable mailbox renaming logic. This is just a kludge that should
+ be removed once the renaming logic has no more bugs.. */
+ DSYNC_MAILBOX_TREES_SYNC_FLAG_NO_RENAMES = 0x04
+};
+
+enum dsync_mailbox_node_existence {
+ /* this is just a filler node for children or for
+ subscription deletion */
+ DSYNC_MAILBOX_NODE_NONEXISTENT = 0,
+ /* if mailbox GUID is set, the mailbox exists.
+ otherwise the directory exists. */
+ DSYNC_MAILBOX_NODE_EXISTS,
+ /* if mailbox GUID is set, the mailbox has been deleted.
+ otherwise the directory has been deleted. */
+ DSYNC_MAILBOX_NODE_DELETED
+};
+
+struct dsync_mailbox_node {
+ struct dsync_mailbox_node *parent, *next, *first_child;
+
+ /* namespace where this node belongs to */
+ struct mail_namespace *ns;
+ /* this node's name (not including parents) */
+ const char *name;
+ /* mailbox GUID, or full of zeros if this is about a directory name */
+ guid_128_t mailbox_guid;
+ /* mailbox's UIDVALIDITY/UIDNEXT (may be 0 if not assigned yet) */
+ uint32_t uid_validity, uid_next;
+
+ /* existence of this mailbox/directory.
+ doesn't affect subscription state. */
+ enum dsync_mailbox_node_existence existence;
+ /* last time the mailbox/directory was created/renamed,
+ 0 if not known */
+ time_t last_renamed_or_created;
+
+ /* last time the subscription state was changed, 0 if not known */
+ time_t last_subscription_change;
+ /* is this mailbox or directory subscribed? */
+ bool subscribed:1;
+
+ /* Internal syncing flags: */
+ bool sync_delayed_guid_change:1;
+ bool sync_temporary_name:1;
+};
+ARRAY_DEFINE_TYPE(dsync_mailbox_node, struct dsync_mailbox_node *);
+
+#define dsync_mailbox_node_guids_equal(node1, node2) \
+ (memcmp((node1)->mailbox_guid, (node2)->mailbox_guid, \
+ sizeof(guid_128_t)) == 0)
+
+#define dsync_mailbox_node_is_dir(node) \
+ guid_128_is_empty((node)->mailbox_guid)
+
+enum dsync_mailbox_delete_type {
+ /* Delete mailbox by given GUID */
+ DSYNC_MAILBOX_DELETE_TYPE_MAILBOX = 1,
+ /* Delete mailbox directory by given SHA1 name */
+ DSYNC_MAILBOX_DELETE_TYPE_DIR,
+ /* Unsubscribe mailbox by given SHA1 name */
+ DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE,
+};
+
+struct dsync_mailbox_delete {
+ enum dsync_mailbox_delete_type type;
+ guid_128_t guid;
+ time_t timestamp;
+};
+
+enum dsync_mailbox_tree_sync_type {
+ DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_BOX,
+ DSYNC_MAILBOX_TREE_SYNC_TYPE_CREATE_DIR,
+ DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_BOX,
+ DSYNC_MAILBOX_TREE_SYNC_TYPE_DELETE_DIR,
+ /* Rename given mailbox name and its children */
+ DSYNC_MAILBOX_TREE_SYNC_TYPE_RENAME,
+ DSYNC_MAILBOX_TREE_SYNC_TYPE_SUBSCRIBE,
+ DSYNC_MAILBOX_TREE_SYNC_TYPE_UNSUBSCRIBE
+};
+
+struct dsync_mailbox_tree_sync_change {
+ enum dsync_mailbox_tree_sync_type type;
+
+ /* for all types: */
+ struct mail_namespace *ns;
+ const char *full_name;
+
+ /* for create_box and delete_box: */
+ guid_128_t mailbox_guid;
+ /* for create_box: */
+ uint32_t uid_validity;
+ /* for rename: */
+ const char *rename_dest_name;
+};
+
+struct dsync_mailbox_tree *
+dsync_mailbox_tree_init(char sep, char escape_char, char alt_char);
+void dsync_mailbox_tree_deinit(struct dsync_mailbox_tree **tree);
+
+/* Lookup a mailbox node by name. Returns NULL if not known. */
+struct dsync_mailbox_node *
+dsync_mailbox_tree_lookup(struct dsync_mailbox_tree *tree,
+ const char *full_name);
+/* Lookup a mailbox node by GUID. Returns NULL if not known.
+ The mailbox GUID hash must have been build before calling this. */
+struct dsync_mailbox_node *
+dsync_mailbox_tree_lookup_guid(struct dsync_mailbox_tree *tree,
+ const guid_128_t guid);
+/* Lookup or create a mailbox node by name. */
+struct dsync_mailbox_node *
+dsync_mailbox_tree_get(struct dsync_mailbox_tree *tree, const char *full_name);
+
+/* Returns full name for the given mailbox node. */
+const char *dsync_mailbox_node_get_full_name(const struct dsync_mailbox_tree *tree,
+ const struct dsync_mailbox_node *node);
+void dsync_mailbox_node_append_full_name(string_t *str,
+ const struct dsync_mailbox_tree *tree,
+ const struct dsync_mailbox_node *node);
+
+/* Copy everything from src to dest, except name and hierarchy pointers */
+void dsync_mailbox_node_copy_data(struct dsync_mailbox_node *dest,
+ const struct dsync_mailbox_node *src);
+
+/* Add nodes to tree from the given namespace. If box_name or box_guid is
+ non-NULL, add only that mailbox to the tree. */
+int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree,
+ struct mail_namespace *ns, const char *box_name,
+ const guid_128_t box_guid,
+ const char *const *exclude_mailboxes,
+ enum mail_error *error_r);
+
+/* Return all known deleted mailboxes and directories. */
+const struct dsync_mailbox_delete *
+dsync_mailbox_tree_get_deletes(struct dsync_mailbox_tree *tree,
+ unsigned int *count_r);
+/* Return mailbox node for a given delete record, or NULL if it doesn't exist.
+ The delete record is intended to come from another tree, possibly with
+ a different hierarchy separator. dsync_mailbox_tree_build_guid_hash() must
+ have been called before this. */
+struct dsync_mailbox_node *
+dsync_mailbox_tree_find_delete(struct dsync_mailbox_tree *tree,
+ const struct dsync_mailbox_delete *del);
+/* Build GUID lookup hash, if it's not already built. Returns 0 if ok, -1 if
+ there are duplicate GUIDs. The nodes with the duplicate GUIDs are
+ returned. */
+int dsync_mailbox_tree_build_guid_hash(struct dsync_mailbox_tree *tree,
+ struct dsync_mailbox_node **dup_node1_r,
+ struct dsync_mailbox_node **dup_node2_r);
+/* Manually add a new node to hash. */
+int dsync_mailbox_tree_guid_hash_add(struct dsync_mailbox_tree *tree,
+ struct dsync_mailbox_node *node,
+ struct dsync_mailbox_node **old_node_r);
+/* Set remote separator used for directory deletions in
+ dsync_mailbox_tree_find_delete() */
+void dsync_mailbox_tree_set_remote_chars(struct dsync_mailbox_tree *tree,
+ char remote_sep,
+ char remote_escape_char);
+
+/* Iterate through all nodes in a tree (depth-first) */
+struct dsync_mailbox_tree_iter *
+dsync_mailbox_tree_iter_init(struct dsync_mailbox_tree *tree);
+bool dsync_mailbox_tree_iter_next(struct dsync_mailbox_tree_iter *iter,
+ const char **full_name_r,
+ struct dsync_mailbox_node **node_r);
+void dsync_mailbox_tree_iter_deinit(struct dsync_mailbox_tree_iter **iter);
+
+/* Sync local and remote trees so at the end they're exactly the same.
+ Return changes done to local tree. */
+struct dsync_mailbox_tree_sync_ctx *
+dsync_mailbox_trees_sync_init(struct dsync_mailbox_tree *local_tree,
+ struct dsync_mailbox_tree *remote_tree,
+ enum dsync_mailbox_trees_sync_type sync_type,
+ enum dsync_mailbox_trees_sync_flags sync_flags);
+const struct dsync_mailbox_tree_sync_change *
+dsync_mailbox_trees_sync_next(struct dsync_mailbox_tree_sync_ctx *ctx);
+int dsync_mailbox_trees_sync_deinit(struct dsync_mailbox_tree_sync_ctx **ctx);
+
+const char *dsync_mailbox_node_to_string(const struct dsync_mailbox_node *node);
+const char *
+dsync_mailbox_delete_type_to_string(enum dsync_mailbox_delete_type type);
+
+#endif