mail-index.h revision 6825360d446542046757b06064282301c4c6b27c
#ifndef __MAIL_INDEX_H
#define __MAIL_INDEX_H
#include "mail-types.h"
#include "seq-range-array.h"
#define MAIL_INDEX_MAJOR_VERSION 7
#define MAIL_INDEX_MINOR_VERSION 1
#define MAIL_INDEX_HEADER_MIN_SIZE 120
enum file_lock_method;
enum mail_index_open_flags {
/* Create index if it doesn't exist */
MAIL_INDEX_OPEN_FLAG_CREATE = 0x01,
/* Don't try to mmap() index files */
/* Rely on O_EXCL when creating dotlocks */
/* Don't fsync() or fdatasync() */
MAIL_INDEX_OPEN_FLAG_NFS_FLUSH = 0x40,
};
};
enum mail_index_header_flag {
/* Index file is corrupted, reopen or recreate it. */
MAIL_INDEX_HDR_FLAG_CORRUPTED = 0x0001,
MAIL_INDEX_HDR_FLAG_HAVE_DIRTY = 0x0002,
/* fsck the index next time when opening */
MAIL_INDEX_HDR_FLAG_FSCK = 0x0004
};
enum mail_index_mail_flags {
MAIL_INDEX_MAIL_FLAG_DIRTY = 0x80
};
#define MAIL_INDEX_FLAGS_MASK \
struct mail_index_header {
/* major version is increased only when you can't have backwards
compatibility. minor version is increased when header size is
increased to contain new non-critical fields. */
/* non-external records between tail..head haven't been committed to
mailbox yet. */
/* daily first UIDs that have been added to index. */
};
struct mail_index_record {
};
struct mail_keywords {
struct mail_index *index;
unsigned int count;
/* variable sized list of keyword indexes */
unsigned int idx[1];
};
enum mail_index_transaction_flags {
/* If transaction is marked as hidden, the changes won't be listed
when the view is synchronized. */
MAIL_INDEX_TRANSACTION_FLAG_HIDE = 0x01,
/* External transactions describe changes to mailbox that have already
happened. */
/* Don't add flag updates unless they actually change something.
This is reliable only when syncing, otherwise someone else might
have already committed a transaction that had changed the flags. */
};
enum mail_index_sync_type {
MAIL_INDEX_SYNC_TYPE_APPEND = 0x01,
MAIL_INDEX_SYNC_TYPE_EXPUNGE = 0x02,
MAIL_INDEX_SYNC_TYPE_FLAGS = 0x04,
MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD = 0x08,
};
enum mail_index_sync_flags {
/* Resync all dirty messages' flags. */
MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY = 0x01,
/* Drop recent flags from all messages */
MAIL_INDEX_SYNC_FLAG_DROP_RECENT = 0x02,
/* Create the transaction with AVOID_FLAG_UPDATES flag */
};
enum mail_index_view_sync_flags {
/* Don't sync expunges */
};
struct mail_index_sync_rec {
enum mail_index_sync_type type;
/* MAIL_INDEX_SYNC_TYPE_FLAGS: */
/* MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD, .._REMOVE: */
unsigned int keyword_idx;
};
struct mail_index_view_sync_rec {
/* keyword appends and removes are packed into one and same
MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD */
enum mail_index_sync_type type;
};
ARRAY_DEFINE_TYPE(keyword_indexes, unsigned int);
struct mail_index;
struct mail_index_map;
struct mail_index_view;
struct mail_index_transaction;
struct mail_index_sync_ctx;
struct mail_index_view_sync_ctx;
enum file_lock_method lock_method);
/* Move the index into memory. Returns 0 if ok, -1 if error occurred. */
/* Refresh index so mail_index_lookup*() will return latest values. Note that
immediately after this call there may already be changes, so if you need to
rely on validity of the returned values, use some external locking for it. */
/* View can be used to look into index. Sequence numbers inside view change
only when you synchronize it. The view acquires required locks
automatically, but you'll have to drop them manually. */
/* Returns the index for given view. */
/* Returns number of mails in view. */
/* Returns TRUE if we lost track of changes for some reason. */
/* Transaction has to be opened to be able to modify index. You can have
multiple transactions open simultaneously. Committed transactions won't
show up until you've synchronized the view. Expunges won't show up until
you've synchronized the mailbox (mail_index_sync_begin). */
struct mail_index_transaction *
int mail_index_transaction_commit(struct mail_index_transaction **t,
void mail_index_transaction_rollback(struct mail_index_transaction **t);
/* Discard all changes in the transaction. */
void mail_index_transaction_reset(struct mail_index_transaction *t);
/* Returns the view transaction was created for. */
struct mail_index_view *
/* Returns TRUE if the given sequence is being expunged in this transaction. */
bool mail_index_transaction_is_expunged(struct mail_index_transaction *t,
/* Returns a view to transaction. Currently this differs from normal view only
in that it contains newly appended messages in transaction. The view can
still be used after transaction has been committed. */
struct mail_index_view *
/* Begin synchronizing mailbox with index file. Returns 0 if ok, -1 if error.
mail_index_sync_next() returns all changes from previously committed
transactions which haven't yet been committed to the actual mailbox.
They're returned in ascending order and they never overlap (if we add more
sync types, then they might). You must go through all of them and update
the mailbox accordingly.
Changes done to the returned transaction are expected to describe the
mailbox's current state.
The returned view already contains all the changes, so if e.g. a record's
flags are different in view than in the mailbox you can assume that they
were changed externally, and you need to update the index.
Returned expunges are treated as expunge requests. They're not really
removed from the index until you mark them expunged to the returned
transaction. If it's not possible to expunge the message (e.g. permission
denied), simply don't mark them expunged.
Returned sequence numbers describe the mailbox state at the beginning of
synchronization, ie. expunges don't affect them. */
struct mail_index_sync_ctx **ctx_r,
struct mail_index_view **view_r,
struct mail_index_transaction **trans_r,
enum mail_index_sync_flags flags);
/* Like mail_index_sync_begin(), but returns 1 if OK and if index is already
synchronized up to the given log_file_seq+offset, the synchronization isn't
started and this function returns 0. This should be done when you wish to
sync your committed transaction instead of doing a full mailbox
synchronization. */
struct mail_index_sync_ctx **ctx_r,
struct mail_index_view **view_r,
struct mail_index_transaction **trans_r,
enum mail_index_sync_flags flags);
/* Returns -1 if error, 0 if sync is finished, 1 if record was filled. */
struct mail_index_sync_rec *sync_rec);
/* Returns TRUE if there's more to sync. */
/* Reset syncing to initial state after mail_index_sync_begin(), so you can
go through all the sync records again with mail_index_sync_next(). */
/* Commit synchronization by writing all changes to mail index file. */
/* Rollback synchronization - none of the changes listed by sync_next() are
actually written to index file. */
/* Mark index file corrupted. Invalidates all views. */
/* Check and fix any found problems. If index is broken beyond repair, it's
marked corrupted and 0 is returned. Otherwise returns -1 if there was some
I/O error or 1 if everything went ok. */
/* Synchronize changes in view. You have to go through all records, or view
will be marked inconsistent. Only sync_mask type records are
synchronized. */
struct mail_index_view_sync_ctx **ctx_r);
struct mail_index_view_sync_rec *sync_rec);
void
/* Returns the index header. */
const struct mail_index_header *
/* Returns the wanted message record. */
const struct mail_index_record *
const struct mail_index_record *
struct mail_index_map **map_r);
/* Returns TRUE if the given message has already been expunged from index. */
/* Note that returned keyword indexes aren't sorted. */
/* Returns the UID for given message. May be slightly faster than
mail_index_lookup()->uid. */
/* Convert UID range to sequence range. If no UIDs are found, sequences are
set to 0. Note that any of the returned sequences may have been expunged
already. */
/* Find first mail with (mail->flags & flags_mask) == flags. Useful mostly for
taking advantage of lowwater-fields in headers. */
/* Append a new record to index. */
/* Assigns UIDs for appended mails all at once. UID must have been given as 0
for mail_index_append(). Returns the next unused UID. */
void mail_index_append_assign_uids(struct mail_index_transaction *t,
/* Expunge record from index. Note that this doesn't affect sequence numbers
until transaction is committed and mailbox is synced. */
/* Update flags in index. */
enum modify_type modify_type,
enum mail_flags flags);
void mail_index_update_flags_range(struct mail_index_transaction *t,
enum modify_type modify_type,
enum mail_flags flags);
/* Reset the index before committing this transaction. This is usually done
only when UIDVALIDITY changes. */
void mail_index_reset(struct mail_index_transaction *t);
/* Lookup a keyword, returns TRUE if found, FALSE if not. */
const char *keyword,
unsigned int *idx_r);
/* Return a pointer to array of NULL-terminated list of keywords. Note that
the array contents (and thus pointers inside it) may change after calling
mail_index_keywords_create() or mail_index_sync_begin(). */
/* Create a keyword list structure. It's freed automatically at the end of
the transaction. */
struct mail_keywords *
mail_index_keywords_create(struct mail_index_transaction *t,
const char *const keywords[]);
struct mail_keywords *
const ARRAY_TYPE(keyword_indexes)
/* Free the keywords. */
/* Update keywords for given message. */
enum modify_type modify_type,
struct mail_keywords *keywords);
/* Update field in header. If prepend is TRUE, the header change is visible
before message syncing begins. */
void mail_index_update_header(struct mail_index_transaction *t,
bool prepend);
/* Returns the full error message for last error. This message may
contain paths etc. so it shouldn't be shown to users. */
/* Reset the error message. */
/* Apply changes in MAIL_INDEX_SYNC_TYPE_FLAGS typed sync records to given
flags variable. */
/* Apply changes in MAIL_INDEX_SYNC_TYPE_KEYWORD_* typed sync records to given
keywords array. Returns TRUE If something was changed. */
/* register index extension. name is a unique identifier for the extension.
returns unique identifier for the name. */
/* Resize existing extension data. If size is grown, the new data will be
zero-filled. If size is shrinked, the data is simply dropped. */
/* Reset extension records and header. Any updates for this extension which
were issued before the writer had seen this reset are discarded. reset_id is
used to figure this out, so it must be different every time. */
/* Discard existing extension updates and write new updates using the given
reset_id. The difference to mail_index_ext_reset() is that this doesn't
clear any existing record or header data. */
void mail_index_ext_set_reset_id(struct mail_index_transaction *t,
/* Get the current reset_id for given extension. Returns TRUE if it exists. */
struct mail_index_map *map,
/* Returns extension header. */
/* Returns the wanted extension record for given message. If it doesn't exist,
*data_r is set to NULL. expunged_r is TRUE if the message has already been
expunged from the index. */
bool *expunged_r);
const void **data_r, bool *expunged_r);
/* Get current extension sizes. Returns 1 if ok, 0 if extension doesn't exist
in view. Any of the _r parameters may be NULL. */
/* Update extension header field. */
void mail_index_update_header_ext(struct mail_index_transaction *t,
/* Update extension record. If old_data_r is non-NULL and the record extension
was already updated in this transaction, it's set to contain the data it's
now overwriting. */
#endif