mail-storage-private.h revision f90cbe597c41d5cc91debd371f8648bd8e6ffbc2
#ifndef MAIL_STORAGE_PRIVATE_H
#define MAIL_STORAGE_PRIVATE_H
#include "module-context.h"
#include "unichar.h"
#include "file-lock.h"
#include "mail-storage.h"
#include "mail-storage-hooks.h"
#include "mail-storage-settings.h"
#include "mail-index-private.h"
/* Default prefix for indexes */
#define MAIL_INDEX_PREFIX "dovecot.index"
/* Block size when read()ing message header. */
/* Block size when read()ing message (header and) body. */
#define MAIL_SHARED_STORAGE_NAME "shared"
struct mail_storage_module_register {
unsigned int id;
};
struct mail_module_register {
unsigned int id;
};
struct mail_storage_vfuncs {
const struct setting_parser_info *(*get_setting_parser_info)(void);
struct mail_storage *(*alloc)(void);
const char **error_r);
struct mailbox_list *list);
struct mailbox_list_settings *set);
struct mailbox_list_settings *set);
struct mailbox_list *list,
const char *vname,
enum mailbox_flags flags);
};
union mail_storage_module_context {
struct mail_storage_vfuncs super;
struct mail_storage_module_register *reg;
};
enum mail_storage_class_flags {
/* mailboxes are files, not directories */
/* root_dir points to a unique directory */
/* mailbox_open_stream() is supported */
/* never use quota for this storage (e.g. virtual mailboxes) */
MAIL_STORAGE_CLASS_FLAG_NOQUOTA = 0x08,
/* Storage doesn't need a mail root directory */
MAIL_STORAGE_CLASS_FLAG_NO_ROOT = 0x10,
/* Storage uses one file per message */
/* Messages have GUIDs (always set mailbox_status.have_guids=TRUE) */
/* mailbox_save_set_guid() works (always set
mailbox_status.have_save_guids=TRUE) */
/* message content can be unstructured binary data
(e.g. zlib plugin is allowed to compress/decompress mails) */
MAIL_STORAGE_CLASS_FLAG_BINARY_DATA = 0x100,
/* Message GUIDs can only be 128bit (always set
mailbox_status.have_only_guid128) */
};
struct mail_binary_cache {
bool include_hdr;
};
struct mail_storage_error {
char *error_string;
enum mail_error error;
};
struct mail_storage {
const char *name;
struct mail_storage_vfuncs v, *vlast;
/* private: */
/* counting number of times mail_storage_create() has returned this
same storage. */
int refcount;
/* counting number of objects (e.g. mailbox) that have a pointer
to this storage. */
int obj_refcount;
/* Linked list of all mailboxes in the storage */
const char *unique_root_dir;
char *error_string;
enum mail_error error;
const struct mail_storage *storage_class;
const char *temp_path_prefix;
const struct mail_storage_settings *set;
enum mail_storage_flags flags;
struct mail_storage_callbacks callbacks;
void *callback_context;
struct mail_binary_cache binary_cache;
/* Filled lazily by mailbox_attribute_*() when accessing shared
attributes. */
struct dict *_shared_attr_dict;
/* Module-specific contexts. See mail_storage_module_id. */
/* Failed to create shared attribute dict, don't try again */
unsigned int shared_attr_dict_failed:1;
};
struct mail_attachment_part {
struct message_part *part;
const char *content_type, *content_disposition;
};
struct mailbox_vfuncs {
enum mailbox_existence *existence_r);
const struct mailbox_update *update);
struct mailbox_status *status_r);
enum mailbox_metadata_items items,
struct mailbox_metadata *metadata_r);
int (*attribute_set)(struct mailbox_transaction_context *t,
const struct mail_attribute_value *value);
int (*attribute_get)(struct mailbox_transaction_context *t,
struct mail_attribute_value *value_r);
struct mailbox_attribute_iter *
enum mail_attribute_type type,
const char *prefix);
/* Lookup sync extension record and figure out if it mailbox has
changed since. Returns 1 = yes, 0 = no, -1 = error. */
struct mail_index_view *list_view,
/* Update the sync extension record. */
struct mail_index_transaction *trans,
struct mailbox_sync_context *
enum mailbox_sync_flags flags);
struct mailbox_sync_rec *sync_rec_r);
struct mailbox_sync_status *status_r);
/* Called once for each expunge. Called one or more times for
uid=0 and sync_type=0. */
enum mailbox_sync_type sync_type);
struct mailbox_transaction_context *
enum mailbox_transaction_flags flags);
int (*transaction_commit)(struct mailbox_transaction_context *t,
struct mail_transaction_commit_changes *changes_r);
void (*transaction_rollback)(struct mailbox_transaction_context *t);
struct mail *
(*mail_alloc)(struct mailbox_transaction_context *t,
struct mailbox_header_lookup_ctx *wanted_headers);
struct mail_search_context *
(*search_init)(struct mailbox_transaction_context *t,
struct mail_search_args *args,
const enum mail_sort_type *sort_program,
struct mailbox_header_lookup_ctx *wanted_headers);
/* Internal search function which updates ctx->seq */
struct mail_save_context *
(*save_alloc)(struct mailbox_transaction_context *t);
void (*transaction_save_commit_post)
(struct mail_save_context *save_ctx,
struct mail_index_transaction_commit_result *result_r);
};
union mailbox_module_context {
struct mailbox_vfuncs super;
struct mail_storage_module_register *reg;
};
struct mail_msgpart_partial_cache {
};
struct mailbox {
const char *name;
/* mailbox's virtual name (from mail_namespace_get_vname()) */
const char *vname;
struct mail_storage *storage;
struct mailbox_list *list;
struct mailbox_vfuncs v, *vlast;
/* private: */
/* Linked list of all mailboxes in this storage */
/* these won't be set until mailbox is opened: */
struct mail_index *index;
struct mail_index_view *view;
struct mail_cache *cache;
against the primary index and used to store per-user flags.
These are non-NULL only when mailbox has per-user flags. */
struct mail_index *index_pvt;
struct mail_index_view *view_pvt;
/* Filled lazily by mailbox_get_permissions() */
struct mailbox_permissions _perm;
/* Filled lazily when mailbox is opened, use mailbox_get_path()
to access it */
const char *_path;
/* default vfuncs for new struct mails. */
const struct mail_vfuncs *mail_vfuncs;
/* Mailbox settings, or NULL if defaults */
const struct mailbox_settings *set;
/* If non-zero, fail mailbox_open() with this error. mailbox_alloc()
can set this to force open to fail. */
enum mail_error open_error;
const char *index_prefix;
enum mailbox_flags flags;
unsigned int transaction_count;
struct mail_index_view *tmp_sync_view;
/* Mailbox notification settings: */
void *notify_context;
/* Increased by one for each new struct mailbox. */
unsigned int generation_sequence;
/* Saved search results */
/* Module-specific contexts. See mail_storage_module_id. */
/* When FAST open flag is used, the mailbox isn't actually opened until
it's synced for the first time. */
unsigned int opened:1;
/* Mailbox was deleted while we had it open. */
unsigned int mailbox_deleted:1;
/* Mailbox is being created */
unsigned int creating:1;
/* Mailbox is being deleted */
unsigned int deleting:1;
/* Don't use MAIL_INDEX_SYNC_FLAG_DELETING_INDEX for sync flag */
unsigned int delete_sync_check:1;
/* Delete mailbox only if it's empty */
unsigned int deleting_must_be_empty:1;
/* The backend wants to skip checking if there are 0 messages before
calling mailbox_list.delete_mailbox() */
unsigned int delete_skip_empty_check:1;
/* Mailbox was already marked as deleted within this allocation. */
unsigned int marked_deleted:1;
/* TRUE if this is an INBOX for this user */
unsigned int inbox_user:1;
/* TRUE if this is an INBOX for this namespace (user or shared) */
unsigned int inbox_any:1;
/* When copying to this mailbox, require that mailbox_copy() uses
mailbox_save_*() to actually save a new physical copy rather than
simply incrementing a reference count (e.g. via hard link) */
unsigned int disable_reflink_copy_to:1;
/* Don't allow creating any new keywords */
unsigned int disallow_new_keywords:1;
/* Mailbox has been synced at least once */
unsigned int synced:1;
/* Updating cache file is disabled */
unsigned int mail_cache_disabled:1;
};
struct mail_vfuncs {
enum mail_fetch_field fields,
struct mailbox_header_lookup_ctx *headers);
const ARRAY_TYPE(keyword_indexes) *
struct message_part **parts_r);
bool decode_to_utf8, const char **value_r);
bool decode_to_utf8, const char *const **value_r);
struct mailbox_header_lookup_ctx *headers,
struct message_size *hdr_size,
struct message_size *body_size,
const struct message_part *part,
const char **value_r);
/* FIXME: v2.3 API should change this to return -1 on failure.
for now NULL means failure so we don't break backwards
compatibility. */
enum mail_flags flags);
struct mail_keywords *keywords);
enum mail_fetch_field field);
};
union mail_module_context {
struct mail_vfuncs super;
struct mail_module_register *reg;
};
struct mail_private {
struct mail_vfuncs v, *vlast;
/* normally NULL, but in case this is a "backend mail" for a mail
created by virtual storage, this points back to the original virtual
mail. at least mailbox_copy() bypasses the virtual storage, so this
allows mail_log plugin to log the copy operation using the original
mailbox name. */
struct mailbox_header_lookup_ctx *wanted_headers;
};
struct mailbox_list_context {
struct mail_storage *storage;
enum mailbox_list_flags flags;
bool failed;
};
struct mail_storage_module_register *reg;
};
struct mailbox_transaction_stats {
unsigned long open_lookup_count;
unsigned long stat_lookup_count;
unsigned long fstat_lookup_count;
/* number of files we've opened and read */
unsigned long files_read_count;
/* number of bytes we've had to read from files */
unsigned long long files_read_bytes;
/* number of cache lookup hits */
unsigned long cache_hit_count;
};
struct mail_save_private_changes {
/* first saved mail is 0, second is 1, etc. we'll map these to UIDs
using struct mail_transaction_commit_changes. */
unsigned int mailnum;
enum mail_flags flags;
};
struct mailbox_transaction_context {
struct mail_index_transaction_vfuncs super;
int mail_ref_count;
struct mail_index_transaction *itrans;
/* view contains all changes done within this transaction */
struct mail_index_view *view;
/* for private index updates: */
struct mail_index_transaction *itrans_pvt;
struct mail_index_view *view_pvt;
struct mail_cache_view *cache_view;
struct mail_cache_transaction_ctx *cache_trans;
struct mail_transaction_commit_changes *changes;
struct mail_save_context *save_ctx;
unsigned int save_count;
private index after committing the mails to the shared index. */
/* these statistics are never reset by mail-storage API: */
struct mailbox_transaction_stats stats;
/* Set to TRUE to update stats_* fields */
unsigned int stats_track:1;
/* We've done some non-transactional (e.g. dovecot-uidlist updates) */
unsigned int nontransactional_changes:1;
};
union mail_search_module_context {
struct mail_storage_module_register *reg;
};
struct mail_search_context {
struct mailbox_transaction_context *transaction;
struct mail_search_args *args;
struct mail_search_sort_program *sort_program;
struct mailbox_header_lookup_ctx *wanted_headers;
/* if non-NULL, specifies that a search resulting is being updated.
this can be used as a search optimization: if searched message
already exists in search result, it's not necessary to check if
static data matches. */
struct mail_search_result *update_result;
/* add matches to these search results */
unsigned int seen_lost_data:1;
unsigned int progress_hidden:1;
};
struct mail_save_data {
enum mail_flags flags;
enum mail_flags pvt_flags;
struct mail_keywords *keywords;
int received_tz_offset;
unsigned int pop3_order;
struct mail_save_attachment *attach;
};
struct mail_save_context {
struct mailbox_transaction_context *transaction;
/* data that changes for each saved mail */
struct mail_save_data data;
/* returns TRUE if message part is an attachment. */
const struct mail_attachment_part *part);
the same context is usually returned by the backends for reuse. */
unsigned int unfinished:1;
/* mailbox_save_finish() or mailbox_copy() is being called. */
unsigned int finishing:1;
/* mail was copied using saving */
unsigned int copying_via_save:1;
/* mail is being saved, not copied */
unsigned int saving:1;
/* mail is being moved - ignore quota */
unsigned int moving:1;
};
struct mailbox_sync_context {
enum mailbox_sync_flags flags;
};
struct mailbox_header_lookup_ctx {
int refcount;
unsigned int count;
const char *const *name;
unsigned int *idx;
};
struct mailbox_attribute_iter {
};
/* Modules should use do "my_id = mail_storage_module_id++" and
use objects' module_contexts[id] for their own purposes. */
extern struct mail_storage_module_register mail_storage_module_register;
/* Storage's module_id for mail_index. */
extern struct mail_module_register mail_module_register;
#define MAIL_STORAGE_CONTEXT(obj) \
/* Set error message in storage. Critical errors are logged with i_error(),
but user sees only "internal error" message. */
struct mailbox_list *list);
struct mail_storage *src);
/* Returns TRUE if everything should already be in memory after this call
or if prefetching is not supported, i.e. the caller shouldn't do more
prefetching before this message is handled. */
/* Easy wrapper for getting mailbox's MAILBOX_LIST_PATH_TYPE_MAILBOX.
The mailbox must already be opened and the caller must know that the
/* Wrapper to mailbox_list_get_path() */
const char **path_r);
/* Get mailbox permissions. */
/* Force permissions to be refreshed on next lookup */
/* Open private index files for mailbox. Returns 1 if opened, 0 if there
are no private indexes (or flags) in this mailbox, -1 if error. */
/* Create path's directory with proper permissions. The root directory is also
created if necessary. Returns 1 if created, 0 if it already existed,
-1 if error. */
enum mailbox_list_path_type type);
/* Create a non-mailbox type directory for mailbox if it's missing (e.g. index).
Optimized for case where the directory usually exists. */
enum mailbox_list_path_type type);
/* Returns -1 if error, 0 if failed with EEXIST, 1 if ok */
int *fd_r);
unsigned int secs);
const struct mail_attribute_value *value,
const char **str_r);
#endif