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