mail-index.h revision a4663ce76645f28d521c7461abecb44537207cb2
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen#ifndef __MAIL_INDEX_H
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#define __MAIL_INDEX_H
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "file-dotlock.h"
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen#include "message-parser.h"
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen#include "imap-util.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#define MAIL_INDEX_VERSION 2
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#define INDEX_FILE_PREFIX ".imap.index"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenenum mail_index_open_flags {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Create index if it doesn't exist */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_OPEN_FLAG_CREATE = 0x01,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Update \Recent flag counters */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT = 0x02,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* Compressing and cache updates are not performed */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_OPEN_FLAG_FAST = 0x04,
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* internal: we're creating the index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen _MAIL_INDEX_OPEN_FLAG_CREATING = 0x10
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen};
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainenenum mail_index_header_compat {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_COMPAT_LITTLE_ENDIAN = 0x01
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen};
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenenum mail_index_header_flag {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Rebuild flag is set while index is being rebuilt or when
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen some error is noticed in the index file. If this flag is set,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen the index shouldn't be used before rebuilding it. */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen MAIL_INDEX_FLAG_REBUILD = 0x01,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_FLAG_FSCK = 0x02,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_FLAG_CACHE_FIELDS = 0x04,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_FLAG_COMPRESS = 0x08,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_FLAG_COMPRESS_DATA = 0x10,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_FLAG_REBUILD_TREE = 0x20,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_FLAG_DIRTY_MESSAGES = 0x40,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS = 0x80
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen};
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenenum mail_data_field {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_FIELD_LOCATION = 0x00000001,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen DATA_FIELD_ENVELOPE = 0x00000002,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_FIELD_BODY = 0x00000004,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_FIELD_BODYSTRUCTURE = 0x00000008,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_FIELD_MD5 = 0x00000010,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_FIELD_MESSAGEPART = 0x00000020,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen DATA_FIELD_LAST = 0x00000040,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_FIELD_MAX_BITS = 6,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* separate from above, but in same bitmask */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen DATA_HDR_INTERNAL_DATE = 0x40000000,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_HDR_VIRTUAL_SIZE = 0x20000000,
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen DATA_HDR_HEADER_SIZE = 0x10000000,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_HDR_BODY_SIZE = 0x08000000
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen};
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen#define IS_BODYSTRUCTURE_FIELD(field) \
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen (((field) & (DATA_FIELD_BODY | DATA_FIELD_BODYSTRUCTURE | \
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen DATA_FIELD_MESSAGEPART)) != 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenenum mail_index_mail_flag {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* If binary flags are set, it's not checked whether mail is
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen missing CRs. So this flag may be set as an optimization for
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen regular non-binary mails as well if it's known that it contains
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen valid CR+LF line breaks. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen INDEX_MAIL_FLAG_BINARY_HEADER = 0x0001,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen INDEX_MAIL_FLAG_BINARY_BODY = 0x0002,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Currently this means with mbox format that message flags have
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen been changed in index, but not written into mbox file yet. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen INDEX_MAIL_FLAG_DIRTY = 0x0004
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen};
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainenenum mail_lock_type {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen MAIL_LOCK_UNLOCK = 0,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_LOCK_SHARED,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_LOCK_EXCLUSIVE
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen};
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenenum mail_lock_notify_type {
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen /* Mailbox is locked, will abort in secs_left */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_LOCK_NOTIFY_MAILBOX_ABORT,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Mailbox lock looks stale, will override in secs_left */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen MAIL_LOCK_NOTIFY_MAILBOX_OVERRIDE,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Index is locked, will abort in secs_left */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen MAIL_LOCK_NOTIFY_INDEX_ABORT
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen};
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenenum mail_index_error {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* No errors */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_ERROR_NONE,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Internal error, see get_error_text() for more information. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen MAIL_INDEX_ERROR_INTERNAL,
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen /* Index is now in inconsistent state with the previous known state,
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen meaning that the message IDs etc. may have changed - only way to
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen recover this would be to fully close the mailbox and reopen it.
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen With IMAP this would mean a forced disconnection since we can't do
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen forced CLOSE. */
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen MAIL_INDEX_ERROR_INCONSISTENT,
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen /* We ran out of available disk space. */
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen MAIL_INDEX_ERROR_DISKSPACE,
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen /* Mail index locking timeouted */
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen MAIL_INDEX_ERROR_INDEX_LOCK_TIMEOUT,
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen /* Mailbox locking timeouted */
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen MAIL_INDEX_ERROR_MAILBOX_LOCK_TIMEOUT
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen};
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainentypedef void mail_lock_notify_callback_t(enum mail_lock_notify_type notify_type,
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen unsigned int secs_left, void *context);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainenstruct mail_index_header {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen unsigned char compat_data[8];
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen /* 0 = version
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen 1 = flags,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen 2 = sizeof(unsigned int),
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen 3 = sizeof(time_t),
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen 4 = sizeof(uoff_t),
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen 5 = MEM_ALIGN_SIZE */
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int indexid;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int sync_id; /* re-mmap() when changed, required only
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if file size is changed */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int flags;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int cache_fields;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen uoff_t used_file_size;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen unsigned int first_hole_index;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int first_hole_records;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen unsigned int uid_validity;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int next_uid;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int messages_count;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int seen_messages_count;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int deleted_messages_count;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int last_nonrecent_uid;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* these UIDs may not exist and may not even be unseen */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int first_unseen_uid_lowwater;
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen unsigned int first_deleted_uid_lowwater;
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen};
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainenstruct mail_index_data_header {
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen unsigned int indexid;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int reserved; /* for alignment mostly */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen uoff_t used_file_size;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen uoff_t deleted_space;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen};
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstruct mail_index_record {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int uid;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int msg_flags; /* enum mail_flags */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
5297aa3ceddf3a4ecc09f49c832bc424eff8f906Timo Sirainen unsigned int index_flags; /* enum mail_index_mail_flag */
5297aa3ceddf3a4ecc09f49c832bc424eff8f906Timo Sirainen unsigned int data_fields; /* enum mail_data_field */
5297aa3ceddf3a4ecc09f49c832bc424eff8f906Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen uoff_t data_position;
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen};
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstruct mail_index_data_record_header {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen unsigned int data_size; /* including this header */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen time_t internal_date;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen uoff_t virtual_size;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen uoff_t header_size;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen uoff_t body_size;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen};
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenstruct mail_index_data_record {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int field; /* enum mail_data_field */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int full_field_size;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen char data[MEM_ALIGN_SIZE]; /* variable size */
5297aa3ceddf3a4ecc09f49c832bc424eff8f906Timo Sirainen};
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#define SIZEOF_MAIL_INDEX_DATA \
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen (sizeof(struct mail_index_data_record) - MEM_ALIGN_SIZE)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#define DATA_RECORD_SIZE(rec) \
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen (SIZEOF_MAIL_INDEX_DATA + (rec)->full_field_size)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstruct mail_index {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* Note that opening same index twice in the same process is a bad
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen idea since they share the same file locks. As soon one of the
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen indexes is closed, the locks in second index are dropped which
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen especially hurts modify log since it keeps locks all the time. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen int (*open)(struct mail_index *index, enum mail_index_open_flags flags);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Free index from memory. */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen void (*free)(struct mail_index *index);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Lock/unlock index. May block. Note that unlocking must not
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen reset error from get_last_error() as unlocking can be done as
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen a cleanup after some other function failed. Index is always
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen mmap()ed after set_lock() succeeds.
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen Trying to change a shared lock into exclusive lock is a fatal
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen error, since it may create a deadlock. Even though operating
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen system should detect it and fail, it's not a good idea to even
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen let it happen. Better ways to do this would be to a) mark the
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen data to be updated later, b) use try_lock() if the update is
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen preferred but not required, c) unlock + lock again, but make
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen sure that won't create race conditions. */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen int (*set_lock)(struct mail_index *index,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen enum mail_lock_type lock_type);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Try locking the index. Returns TRUE if the lock was got and
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen FALSE if lock isn't possible to get currently or some other error
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen occured. Never blocks. */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen int (*try_lock)(struct mail_index *index,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen enum mail_lock_type lock_type);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* If we have to wait for the lock, the given lock notify function
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen is called once in a while. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen void (*set_lock_notify_callback)(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mail_lock_notify_callback_t *callback,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen void *context);
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Rebuild the whole index. Note that this changes the indexid
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen so all the other files must also be rebuilt after this call.
8d235b34022f0bf0f7db54fdbda2d4fd204ed864Timo Sirainen Index MUST NOT have shared lock, but exclusive lock or no lock at
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen all is fine. Note that this function may leave the index
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen exclusively locked, and always sets index->inconsistent = TRUE. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen int (*rebuild)(struct mail_index *index);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Verify that the index is valid. If anything invalid is found,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index is set inconsistent and to be rebuilt at next open.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen Same locking issues as with rebuild(). */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen int (*fsck)(struct mail_index *index);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Synchronize the index with the mailbox. Index must not have shared
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen lock when calling this function. The data_lock_type specifies what
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen lock should be set to data file (mbox file). This function may
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen leave the index in ANY locking state. If changes is non-NULL, it's
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen set to TRUE if any changes were noticed. */
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen int (*sync_and_lock)(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen enum mail_lock_type data_lock_type, int *changes);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Returns the index header (never fails). The index needs to be
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen locked before calling this function, and must be kept locked as
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen long as you keep using the returned structure. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_index_header *(*get_header)(struct mail_index *index);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* sequence -> data lookup. The index needs to be locked before calling
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen this function, and must be kept locked as long as you keep using
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen the returned structure. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_index_record *(*lookup)(struct mail_index *index,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen unsigned int seq);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Return the next record after specified record, or NULL if it was
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen last record. The index must be locked all the time between
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen lookup() and last next() call. */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen struct mail_index_record *(*next)(struct mail_index *index,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen struct mail_index_record *rec);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* Find first existing UID in range. Sequence number is also retrieved
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if seq_r is non-NULL. */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen struct mail_index_record *(*lookup_uid_range)(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int first_uid,
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen unsigned int last_uid,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen unsigned int *seq_r);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Find field from specified record, or NULL if it's not in index.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen Makes sure that the field ends with \0. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen const char *(*lookup_field)(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_index_record *rec,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen enum mail_data_field field);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Find field from specified record, or NULL if it's not in index. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen const void *(*lookup_field_raw)(struct mail_index *index,
1b9aae1cb53708b5a3d861b4db6ba96ac2eb35b4Timo Sirainen struct mail_index_record *rec,
1b9aae1cb53708b5a3d861b4db6ba96ac2eb35b4Timo Sirainen enum mail_data_field field,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen size_t *size);
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen /* Mark the fields to be cached later. If any of them is already
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen set in hdr->cache_fields, mark the caching to happen next time
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen index is opened. */
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen void (*cache_fields_later)(struct mail_index *index,
4da70fe8c9cb6e57b36103d78ab1e9c8654f76d9Timo Sirainen enum mail_data_field field);
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Open mail file and return it as mmap()ed IStream. If we fail,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen we return NULL and set deleted = TRUE if failure was because the
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mail was just deleted (ie. not an error). internal_date is set
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if it's non-NULL. */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen struct istream *(*open_mail)(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_index_record *rec,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen time_t *internal_date, int *deleted);
8d235b34022f0bf0f7db54fdbda2d4fd204ed864Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Returns internal date of message, or (time_t)-1 if error occured. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen time_t (*get_internal_date)(struct mail_index *index,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen struct mail_index_record *rec);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Expunge a mail from index. Tree and modifylog is also updated. The
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index must be exclusively locked before calling this function.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen If seq is 0, the modify log isn't updated. This is useful if
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen after append() something goes wrong and you wish to delete the
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen mail immediately. If external_change is TRUE, the modify log is
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen always written.
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen Note that the sequence numbers also update immediately after this
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen call, so if you want to delete messages 1..4 just call this
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen function 4 times with seq being 1. */
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainen int (*expunge)(struct mail_index *index, struct mail_index_record *rec,
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainen unsigned int seq, int external_change);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Update mail flags. The index must be exclusively locked before
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen calling this function. This shouldn't be called in the middle of
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen update_begin() as it may modify location field. */
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen int (*update_flags)(struct mail_index *index,
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen struct mail_index_record *rec,
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainen unsigned int seq, enum mail_flags flags,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen int external_change);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Append a new record to index. The index must be exclusively
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen locked before calling this function. rec->uid is updated in
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen append_end(). */
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen struct mail_index_record *(*append_begin)(struct mail_index *index);
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen int (*append_end)(struct mail_index *index,
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen struct mail_index_record *rec);
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen void (*append_abort)(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_index_record *rec);
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen /* Updating fields happens by calling update_begin(), one or more
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen update_field()s and finally update_end() which does the actual
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen updating. The index must be exclusively locked all this time.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen update_begin() and update_field() functions cannot fail.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen The extra_space parameter for update_field() specifies the amount
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen of extra empty space we should leave after the value, so that if
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen the field grows in future it could be expanded without copying it
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen to end of file. When the field already exists, the extra_space
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen is ignored.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen The files may not actually be updated until after you've unlocked
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen the file. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_index_update *
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen (*update_begin)(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_index_record *rec);
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen int (*update_end)(struct mail_index_update *update);
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen void (*update_field)(struct mail_index_update *update,
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen enum mail_data_field field,
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen const char *value, size_t extra_space);
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen /* Just remember that full_field_size will be MEM_ALIGNed, so
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen it may differer from the given size parameter. */
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen void (*update_field_raw)(struct mail_index_update *update,
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen enum mail_data_field field,
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen const void *value, size_t size);
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen /* Returns the last error code. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen enum mail_index_error (*get_last_error)(struct mail_index *index);
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* Returns the full error message for last error. This message may
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen contain paths etc. so it shouldn't be shown to users. */
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen const char *(*get_last_error_text)(struct mail_index *index);
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen/* private: */
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen struct mail_index_data *data;
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen struct mail_tree *tree;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen struct mail_modify_log *modifylog;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct mail_custom_flags *custom_flags;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen char *dir; /* directory where to place the index files */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen char *filepath; /* index file path */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen char *mailbox_path; /* file/directory for mailbox location */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen char *custom_flags_dir; /* destination for .customflags file */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen enum mail_data_field default_cache_fields, never_cache_fields;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int indexid;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned int sync_id;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen /* updated whenever exclusive lock is set/unset */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen unsigned int excl_lock_counter;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen int mbox_fd;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct istream *mbox_stream;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen enum mail_lock_type mbox_lock_type;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen struct dotlock mbox_dotlock;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* these counters can be used to check that we've synced the mailbox
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen after locking it */
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen unsigned int mbox_lock_counter;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen unsigned int mbox_sync_counter;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* last mbox sync: */
uoff_t mbox_size;
dev_t mbox_dev;
ino_t mbox_ino;
int fd; /* opened index file */
char *error; /* last error message */
void *mmap_base;
size_t mmap_used_length;
size_t mmap_full_length;
struct mail_index_header *header;
enum mail_lock_type lock_type;
time_t file_sync_stamp;
unsigned int first_recent_uid;
mail_lock_notify_callback_t *lock_notify_cb;
void *lock_notify_context;
/* these fields are OR'ed to the fields in index header once we
get around grabbing exclusive lock */
unsigned int set_flags;
enum mail_data_field set_cache_fields;
unsigned int anon_mmap:1;
unsigned int opened:1;
unsigned int mail_read_mmaped:1;
unsigned int inconsistent:1;
unsigned int nodiskspace:1;
unsigned int index_lock_timeout:1;
unsigned int allow_new_custom_flags:1;
unsigned int mailbox_lock_timeout:1;
};
#ifdef DEV_T_STRUCT
/* we can't initialize dev_t as 0, and we don't know what it actually
contains, so don't initialize them. gcc's -W option should be disabled
with this or we get warnings.. */
# define MAIL_INDEX_PRIVATE_FILL 0
#else
/* needed to remove annoying warnings about not initializing all struct
members.. */
#define MAIL_INDEX_PRIVATE_FILL \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, { 0, 0, 0 }, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0
#endif
/* defaults - same as above but prefixed with mail_index_. */
int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags);
int mail_index_set_lock(struct mail_index *index,
enum mail_lock_type lock_type);
int mail_index_try_lock(struct mail_index *index,
enum mail_lock_type lock_type);
void mail_index_set_lock_notify_callback(struct mail_index *index,
mail_lock_notify_callback_t *callback,
void *context);
int mail_index_fsck(struct mail_index *index);
struct mail_index_header *mail_index_get_header(struct mail_index *index);
struct mail_index_record *mail_index_lookup(struct mail_index *index,
unsigned int seq);
struct mail_index_record *mail_index_next(struct mail_index *index,
struct mail_index_record *rec);
struct mail_index_record *
mail_index_lookup_uid_range(struct mail_index *index, unsigned int first_uid,
unsigned int last_uid, unsigned int *seq_r);
const char *mail_index_lookup_field(struct mail_index *index,
struct mail_index_record *rec,
enum mail_data_field field);
const void *mail_index_lookup_field_raw(struct mail_index *index,
struct mail_index_record *rec,
enum mail_data_field field,
size_t *size);
void mail_index_cache_fields_later(struct mail_index *index,
enum mail_data_field field);
int mail_index_expunge(struct mail_index *index, struct mail_index_record *rec,
unsigned int seq, int external_change);
int mail_index_update_flags(struct mail_index *index,
struct mail_index_record *rec,
unsigned int seq, enum mail_flags flags,
int external_change);
struct mail_index_record *mail_index_append_begin(struct mail_index *index);
int mail_index_append_end(struct mail_index *index,
struct mail_index_record *rec);
void mail_index_append_abort(struct mail_index *index,
struct mail_index_record *rec);
struct mail_index_update *
mail_index_update_begin(struct mail_index *index,
struct mail_index_record *rec);
int mail_index_update_end(struct mail_index_update *update);
void mail_index_update_field(struct mail_index_update *update,
enum mail_data_field field,
const char *value, size_t extra_space);
void mail_index_update_field_raw(struct mail_index_update *update,
enum mail_data_field field,
const void *value, size_t size);
time_t mail_get_internal_date(struct mail_index *index,
struct mail_index_record *rec);
enum mail_index_error mail_index_get_last_error(struct mail_index *index);
const char *mail_index_get_last_error_text(struct mail_index *index);
/* INTERNAL: */
void mail_index_init(struct mail_index *index, const char *dir);
int mail_index_mmap_update(struct mail_index *index);
void mail_index_init_header(struct mail_index *index,
struct mail_index_header *hdr);
void mail_index_close(struct mail_index *index);
int mail_index_fmdatasync(struct mail_index *index, size_t size);
int mail_index_verify_hole_range(struct mail_index *index);
void mail_index_mark_flag_changes(struct mail_index *index,
struct mail_index_record *rec,
enum mail_flags old_flags,
enum mail_flags new_flags);
void mail_index_update_headers(struct mail_index_update *update,
struct istream *input,
enum mail_data_field cache_fields,
message_header_callback_t *header_cb,
void *context);
int mail_index_update_cache(struct mail_index *index);
int mail_index_compress(struct mail_index *index);
int mail_index_compress_data(struct mail_index *index);
int mail_index_truncate(struct mail_index *index);
/* Maximum allowed UID number. */
#define MAX_ALLOWED_UID 4294967295U /* 2^32 - 1 */
/* Max. mmap()ed size for a message */
#define MAIL_MMAP_BLOCK_SIZE (1024*256)
/* Block size when read()ing message. */
#define MAIL_READ_BLOCK_SIZE (1024*8)
/* Delete unused non-local temp files after 24h. Just to be sure we don't
delete it too early. The temp files don't harm much anyway. */
#define TEMP_FILE_TIMEOUT (60*24)
/* number of records to always keep allocated in index file,
either used or unused */
#define INDEX_MIN_RECORDS_COUNT 64
/* when empty space in index file gets full, grow the file n% larger */
#define INDEX_GROW_PERCENTAGE 10
/* ftruncate() the index file when only n% of it is in use */
#define INDEX_TRUNCATE_PERCENTAGE 30
/* don't truncate whole file anyway, keep n% of the empty space */
#define INDEX_TRUNCATE_KEEP_PERCENTAGE 10
/* Compress the file when deleted space reaches n% of total size */
#define INDEX_COMPRESS_PERCENTAGE 50
/* uoff_t to index file for given record */
#define INDEX_FILE_POSITION(index, ptr) \
((uoff_t) ((char *) (ptr) - (char *) ((index)->mmap_base)))
/* record for given index */
#define INDEX_RECORD_AT(index, idx) \
((struct mail_index_record *) \
((char *) index->mmap_base + sizeof(struct mail_index_header)) + (idx))
/* returns the next record after last one */
#define INDEX_END_RECORD(index) \
((struct mail_index_record *) \
((char *) (index)->mmap_base + (index)->mmap_used_length))
/* index number for uoff_t position */
#define INDEX_POSITION_INDEX(pos) \
(((pos) - sizeof(struct mail_index_header)) / \
sizeof(struct mail_index_record))
/* index number for given record */
#define INDEX_RECORD_INDEX(index, ptr) \
INDEX_POSITION_INDEX(INDEX_FILE_POSITION(index, ptr))
/* mark the index corrupted */
#define INDEX_MARK_CORRUPTED(index) \
STMT_START { (index)->set_flags |= MAIL_INDEX_FLAG_REBUILD; } STMT_END
/* get number of records in mmaped index */
#define MAIL_INDEX_RECORD_COUNT(index) \
((index->mmap_used_length - sizeof(struct mail_index_header)) / \
sizeof(struct mail_index_record))
/* minimum size for index file */
#define INDEX_FILE_MIN_SIZE \
(sizeof(struct mail_index_header) + \
INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record))
/* enum mail_lock_type to fcntl() lock type */
#define MAIL_LOCK_TO_FLOCK(lock_type) \
((lock_type) == MAIL_LOCK_EXCLUSIVE ? F_WRLCK : \
(lock_type) == MAIL_LOCK_SHARED ? F_RDLCK : F_UNLCK)
#define INDEX_IS_IN_MEMORY(index) \
((index)->anon_mmap)
#endif