mail-index.h revision 810c9bb5f61307df1a79cd011ee29c0e58e0e262
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano#ifndef __MAIL_INDEX_H
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano#define __MAIL_INDEX_H
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano#include "message-parser.h"
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano#include "imap-util.h"
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano
9afe19d634946d50eab30e3b90cb5cebcde39eeaDaniel Lezcano#define MAIL_INDEX_VERSION 1
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano#define INDEX_FILE_PREFIX ".imap.index"
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcanoenum {
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano MAIL_INDEX_COMPAT_LITTLE_ENDIAN = 0x01
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano};
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcanoenum {
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano /* Rebuild flag is set while index is being rebuilt or when
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano some error is noticed in the index file. If this flag is set,
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano the index shouldn't be used before rebuilding it. */
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano MAIL_INDEX_FLAG_REBUILD = 0x01,
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano MAIL_INDEX_FLAG_FSCK = 0x02,
250b1eec71b074acdff1c5f6b5a1f0d7d2c20b77Stéphane Graber MAIL_INDEX_FLAG_CACHE_FIELDS = 0x04,
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano MAIL_INDEX_FLAG_COMPRESS = 0x08,
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano MAIL_INDEX_FLAG_COMPRESS_DATA = 0x10,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MAIL_INDEX_FLAG_REBUILD_TREE = 0x20,
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner MAIL_INDEX_FLAG_DIRTY_MESSAGES = 0x40,
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS = 0x80
b515981702133b9aaea1aff378493f054c14d46cDwight Engen};
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcanotypedef enum {
8173e600ef80d3f3685a6f1f933ab92f09a160c9Stéphane Graber FIELD_TYPE_LOCATION = 0x0001,
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner FIELD_TYPE_ENVELOPE = 0x0002,
d3e3b1885a13dbe97433f11c26dbcc9d70dd9d4fChristian Brauner FIELD_TYPE_BODY = 0x0004,
d3e3b1885a13dbe97433f11c26dbcc9d70dd9d4fChristian Brauner FIELD_TYPE_BODYSTRUCTURE = 0x0008,
b0a33c1eb65d2c87e886c740a0dadd8ad5f8d87ddlezcano FIELD_TYPE_MD5 = 0x0010,
948955a2d6f8e4e28bceada9666c5831de4a6bb8Stéphane Graber FIELD_TYPE_MESSAGEPART = 0x0020,
f2363e38d07db2ad4796b5580b95e3665ed34a88S.Çağlar Onur
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner FIELD_TYPE_LAST = 0x0040,
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner FIELD_TYPE_MAX_BITS = 6
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner} MailField;
00dbc43e308bcccf5b2147e7fdb37bf9ca693fdcDaniel Lezcano
e827ff7e2f3c1c18e5823312482f0f45e03cb6a8Stéphane Grabertypedef enum {
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner /* If binary flags are set, it's not checked whether mail is
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner missing CRs. So this flag may be set as an optimization for
b515981702133b9aaea1aff378493f054c14d46cDwight Engen regular non-binary mails as well if it's known that it contains
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner valid CR+LF line breaks. */
9395937a965ad3a777a3008c0615d9d5722e4460Christian Brauner INDEX_MAIL_FLAG_BINARY_HEADER = 0x0001,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen INDEX_MAIL_FLAG_BINARY_BODY = 0x0002,
36eb9bdef1123a93f9e441a5df386c4bd0168f27Cedric Le Goater
e827ff7e2f3c1c18e5823312482f0f45e03cb6a8Stéphane Graber /* Currently this means with mbox format that message flags have
e827ff7e2f3c1c18e5823312482f0f45e03cb6a8Stéphane Graber been changed in index, but not written into mbox file yet. */
e827ff7e2f3c1c18e5823312482f0f45e03cb6a8Stéphane Graber INDEX_MAIL_FLAG_DIRTY = 0x0004
e827ff7e2f3c1c18e5823312482f0f45e03cb6a8Stéphane Graber} MailIndexMailFlags;
e827ff7e2f3c1c18e5823312482f0f45e03cb6a8Stéphane Graber
e827ff7e2f3c1c18e5823312482f0f45e03cb6a8Stéphane Graber#define IS_HEADER_FIELD(field) \
36eb9bdef1123a93f9e441a5df386c4bd0168f27Cedric Le Goater (((field) & (FIELD_TYPE_FROM | FIELD_TYPE_TO | FIELD_TYPE_CC | \
36eb9bdef1123a93f9e441a5df386c4bd0168f27Cedric Le Goater FIELD_TYPE_BCC | FIELD_TYPE_SUBJECT)) != 0)
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
724e753cb0055b84f896522e8c5ec45ad996c195Michel Normand#define IS_BODYSTRUCTURE_FIELD(field) \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen (((field) & (FIELD_TYPE_BODY|FIELD_TYPE_BODYSTRUCTURE| \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen FIELD_TYPE_MESSAGEPART)) != 0)
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef enum {
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MAIL_LOCK_UNLOCK = 0,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MAIL_LOCK_SHARED,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MAIL_LOCK_EXCLUSIVE
724e753cb0055b84f896522e8c5ec45ad996c195Michel Normand} MailLockType;
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailIndex MailIndex;
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailIndexData MailIndexData;
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailTree MailTree;
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailModifyLog MailModifyLog;
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailCustomFlags MailCustomFlags;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
724e753cb0055b84f896522e8c5ec45ad996c195Michel Normandtypedef struct _MailIndexHeader MailIndexHeader;
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailIndexDataHeader MailIndexDataHeader;
724e753cb0055b84f896522e8c5ec45ad996c195Michel Normand
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailIndexRecord MailIndexRecord;
b515981702133b9aaea1aff378493f054c14d46cDwight Engentypedef struct _MailIndexDataRecord MailIndexDataRecord;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Braunertypedef struct _MailIndexUpdate MailIndexUpdate;
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner
724e753cb0055b84f896522e8c5ec45ad996c195Michel Normandstruct _MailIndexHeader {
724e753cb0055b84f896522e8c5ec45ad996c195Michel Normand unsigned char compat_data[8];
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* 0 = version
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano 1 = flags,
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn 2 = sizeof(unsigned int),
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn 3 = sizeof(time_t),
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano 4 = sizeof(uoff_t),
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn 5 = MEM_ALIGN_SIZE */
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn unsigned int indexid;
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano unsigned int sync_id; /* re-mmap() when changed, required only
b515981702133b9aaea1aff378493f054c14d46cDwight Engen if file size is changed */
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner unsigned int flags;
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner unsigned int cache_fields;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen uoff_t used_file_size;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int first_hole_index;
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner unsigned int first_hole_records;
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int uid_validity;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int next_uid;
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano unsigned int messages_count;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int seen_messages_count;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int deleted_messages_count;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int last_nonrecent_uid;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner /* these UIDs may not exist and may not even be unseen */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int first_unseen_uid_lowwater;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int first_deleted_uid_lowwater;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen};
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engenstruct _MailIndexDataHeader {
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int indexid;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int reserved; /* for alignment mostly */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen uoff_t used_file_size;
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner uoff_t deleted_space;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen};
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner
b515981702133b9aaea1aff378493f054c14d46cDwight Engenstruct _MailIndexRecord {
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* remember to keep uoff_t's 8 byte aligned so we don't waste space */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int uid;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int msg_flags; /* MailFlags */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen time_t internal_date;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int index_flags; /* MailIndexMailFlags */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int cached_fields; /* MailField */
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner unsigned int data_size;
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner uoff_t data_position;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen uoff_t header_size; /* 0 if not known yet */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen uoff_t body_size; /* if header_size == 0, the size of full message */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen};
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner
e73bcbbee9bf040512585099cd68677bff02c130Christian Braunerstruct _MailIndexDataRecord {
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner unsigned int field; /* MailField */
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner unsigned int full_field_size;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen char data[MEM_ALIGN_SIZE]; /* variable size */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen};
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define SIZEOF_MAIL_INDEX_DATA \
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano (sizeof(MailIndexDataRecord) - MEM_ALIGN_SIZE)
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner#define DATA_RECORD_SIZE(rec) \
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano (SIZEOF_MAIL_INDEX_DATA + (rec)->full_field_size)
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner
b515981702133b9aaea1aff378493f054c14d46cDwight Engenstruct _MailIndex {
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner /* If fast is TRUE, compressing and cache updates are not performed.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen Note that opening same index twice in the same process is a bad
b515981702133b9aaea1aff378493f054c14d46cDwight Engen idea since they share the same file locks. As soon one of the
b515981702133b9aaea1aff378493f054c14d46cDwight Engen indexes is closed, the locks in second index are dropped which
b515981702133b9aaea1aff378493f054c14d46cDwight Engen especially hurts modify log since it keeps locks all the time. */
1560f6c9a7c822fd625914eefa0b985f67d76a0aDaniel Lezcano int (*open)(MailIndex *index, int update_recent, int fast);
84c92abdd1c59de02f446e02ff7fd3e1d70b4811Dwight Engen int (*open_or_create)(MailIndex *index, int update_recent, int fast);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Free index from memory. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen void (*free)(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
32bf178747090118fc6fcc25ae6550643cd521f8Christian Brauner /* Lock/unlock index. May block. Note that unlocking must not
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano reset error from get_last_error() as unlocking can be done as
32bf178747090118fc6fcc25ae6550643cd521f8Christian Brauner a cleanup after some other function failed. Index is always
32bf178747090118fc6fcc25ae6550643cd521f8Christian Brauner mmap()ed after set_lock() succeeds.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen Trying to change a shared lock into exclusive lock is a fatal
b515981702133b9aaea1aff378493f054c14d46cDwight Engen error, since it may create a deadlock. Even though operating
32bf178747090118fc6fcc25ae6550643cd521f8Christian Brauner system should detect it and fail, it's not a good idea to even
33fcb7a0477ed37523f05e0a083046eea166acf0Daniel Lezcano let it happen. Better ways to do this would be to a) mark the
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano data to be updated later, b) use try_lock() if the update is
b515981702133b9aaea1aff378493f054c14d46cDwight Engen preferred but not required, c) unlock + lock again, but make
32bf178747090118fc6fcc25ae6550643cd521f8Christian Brauner sure that won't create race conditions */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int (*set_lock)(MailIndex *index, MailLockType lock_type);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Try locking the index. Returns TRUE if the lock was got and
32bf178747090118fc6fcc25ae6550643cd521f8Christian Brauner FALSE if lock isn't possible to get currently or some other error
b515981702133b9aaea1aff378493f054c14d46cDwight Engen occured. Never blocks. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int (*try_lock)(MailIndex *index, MailLockType lock_type);
32bf178747090118fc6fcc25ae6550643cd521f8Christian Brauner
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano /* Rebuild the whole index. Note that this changes the indexid
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano so all the other files must also be rebuilt after this call.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen Index MUST NOT have shared lock, but exclusive lock or no lock at
b515981702133b9aaea1aff378493f054c14d46cDwight Engen all is fine. Note that this function may leave the index
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner exclusively locked, and always sets index->inconsistent = TRUE. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int (*rebuild)(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Verify that the index is valid. If anything invalid is found,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen index is set inconsistent and to be rebuilt at next open.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen Same locking issues as with rebuild(). */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int (*fsck)(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Synchronize the index with the mailbox. Same locking issues as
b515981702133b9aaea1aff378493f054c14d46cDwight Engen with rebuild(). */
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano int (*sync)(MailIndex *index);
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner /* Returns the index header (never fails). The index needs to be
b515981702133b9aaea1aff378493f054c14d46cDwight Engen locked before calling this function, and must be kept locked as
b515981702133b9aaea1aff378493f054c14d46cDwight Engen long as you keep using the returned structure. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailIndexHeader *(*get_header)(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* sequence -> data lookup. The index needs to be locked before calling
b515981702133b9aaea1aff378493f054c14d46cDwight Engen this function, and must be kept locked as long as you keep using
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen the returned structure. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailIndexRecord *(*lookup)(MailIndex *index, unsigned int seq);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Return the next record after specified record, or NULL if it was
d3e3b1885a13dbe97433f11c26dbcc9d70dd9d4fChristian Brauner last record. The index must be locked all the time between
d3e3b1885a13dbe97433f11c26dbcc9d70dd9d4fChristian Brauner lookup() and last next() call. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailIndexRecord *(*next)(MailIndex *index, MailIndexRecord *rec);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Find first existing UID in range. Sequence number is also retrieved
37903589a2de0cbd62f94c5fd06d0aa8d57ca140Serge Hallyn if seq_r is non-NULL. */
37903589a2de0cbd62f94c5fd06d0aa8d57ca140Serge Hallyn MailIndexRecord *(*lookup_uid_range)(MailIndex *index,
37903589a2de0cbd62f94c5fd06d0aa8d57ca140Serge Hallyn unsigned int first_uid,
37903589a2de0cbd62f94c5fd06d0aa8d57ca140Serge Hallyn unsigned int last_uid,
37903589a2de0cbd62f94c5fd06d0aa8d57ca140Serge Hallyn unsigned int *seq_r);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Find field from specified record, or NULL if it's not in index.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen Makes sure that the field ends with \0. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen const char *(*lookup_field)(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailField field);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Find field from specified record, or NULL if it's not in index. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen const void *(*lookup_field_raw)(MailIndex *index, MailIndexRecord *rec,
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen MailField field, size_t *size);
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Mark the fields to be cached later. If any of them is already
b515981702133b9aaea1aff378493f054c14d46cDwight Engen set in hdr->cache_fields, mark the caching to happen next time
b515981702133b9aaea1aff378493f054c14d46cDwight Engen index is opened. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen void (*cache_fields_later)(MailIndex *index, MailField field);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
28a4b0e55c659428bc8f495fde2e774fbd0fb03cDaniel Lezcano /* Open mail file and return it as mmap()ed IBuffer. If we fails,
28a4b0e55c659428bc8f495fde2e774fbd0fb03cDaniel Lezcano we return NULL and set deleted = TRUE if failure was because the
b515981702133b9aaea1aff378493f054c14d46cDwight Engen mail was just deleted (ie. not an error). */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen IBuffer *(*open_mail)(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int *deleted);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Expunge a mail from index. Tree and modifylog is also updated. The
cd453b38b778652cb341062fbf3c38edefc3a478Daniel Lezcano index must be exclusively locked before calling this function.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen If seq is 0, the modify log isn't updated. This is useful if
b515981702133b9aaea1aff378493f054c14d46cDwight Engen after append() something goes wrong and you wish to delete the
28a4b0e55c659428bc8f495fde2e774fbd0fb03cDaniel Lezcano mail immediately. If external_change is TRUE, the modify log is
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner always written.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen Note that the sequence numbers also update immediately after this
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano call, so if you want to delete messages 1..4 just call this
b515981702133b9aaea1aff378493f054c14d46cDwight Engen function 4 times with seq being 1. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int (*expunge)(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int seq, int external_change);
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano /* Update mail flags. The index must be exclusively locked before
b515981702133b9aaea1aff378493f054c14d46cDwight Engen calling this function. This shouldn't be called in the middle of
b515981702133b9aaea1aff378493f054c14d46cDwight Engen update_begin() as it may modify location field. */
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano int (*update_flags)(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int seq, MailFlags flags,
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano int external_change);
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Append a new record to index. The index must be exclusively
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano locked before calling this function. The record pointer is
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner updated to the mmap()ed record. rec->uid is updated in
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner append_end(). */
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner int (*append_begin)(MailIndex *index, MailIndexRecord **rec);
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner int (*append_end)(MailIndex *index, MailIndexRecord *rec);
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner /* Updating fields happens by calling update_begin(), one or more
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner update_field()s and finally update_end() which does the actual
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner updating. The index must be exclusively locked all this time.
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner update_begin() and update_field() functions cannot fail.
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner
3aec413b1db19ba45ef0c5cd3c5a05c76ffeda4cAndrey Jr. Melnikov The extra_space parameter for update_field() specifies the amount
b515981702133b9aaea1aff378493f054c14d46cDwight Engen of extra empty space we should leave after the value, so that if
b515981702133b9aaea1aff378493f054c14d46cDwight Engen the field grows in future it could be expanded without copying it
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano to end of file. When the field already exists, the extra_space
41d080b9c523087b07db577552d7aa261064eb75Christian Brauner is ignored.
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano The files may not actually be updated until after you've unlocked
b515981702133b9aaea1aff378493f054c14d46cDwight Engen the file. */
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano MailIndexUpdate *(*update_begin)(MailIndex *index,
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano MailIndexRecord *rec);
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano int (*update_end)(MailIndexUpdate *update);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
e0dc0de76ed1ad9e284a37bd01268227d4eae8c9Daniel Lezcano void (*update_field)(MailIndexUpdate *update, MailField field,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen const char *value, size_t extra_space);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Just remember that full_field_size will be MEM_ALIGNed, so
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner it may differer from the given size parameter. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen void (*update_field_raw)(MailIndexUpdate *update, MailField field,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen const void *value, size_t size);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Returns last error message */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen const char *(*get_last_error)(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Returns TRUE if last error was because we ran out of available
b515981702133b9aaea1aff378493f054c14d46cDwight Engen disk space. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int (*is_diskspace_error)(MailIndex *index);
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* Returns TRUE if index is now in inconsistent state with the
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen previous known state, meaning that the message IDs etc. may
b515981702133b9aaea1aff378493f054c14d46cDwight Engen have changed - only way to recover this would be to fully close
b515981702133b9aaea1aff378493f054c14d46cDwight Engen the mailbox and reopen it. With IMAP connection this would mean
b515981702133b9aaea1aff378493f054c14d46cDwight Engen a forced disconnection since we can't do forced CLOSE. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int (*is_inconsistency_error)(MailIndex *index);
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* private: */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailIndexData *data;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailTree *tree;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailModifyLog *modifylog;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailCustomFlags *custom_flags;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen char *dir; /* directory where to place the index files */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen char *filepath; /* index file path */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int indexid;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int sync_id;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen char *mbox_path; /* mbox-specific path to the actual mbox file */
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen uoff_t mbox_size; /* last synced size of mbox file */
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen int mbox_fd;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int mbox_locks;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen int mbox_lock_type;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn int fd; /* opened index file */
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn char *error; /* last error message */
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn void *mmap_base;
025ed0f3911836b71f498d8368725c77a7e1932aSerge Hallyn size_t mmap_used_length;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen size_t mmap_full_length;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailLockType lock_type;
596a818d4b8b55586d36af518b745cd96b24c67aDwight Engen
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner MailIndexHeader *header;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int first_recent_uid;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int modifylog_id;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen time_t file_sync_stamp;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen /* these fields are OR'ed to the fields in index header once we
b515981702133b9aaea1aff378493f054c14d46cDwight Engen get around grabbing exclusive lock */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int set_flags;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int set_cache_fields;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int anon_mmap:1;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int opened:1;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int inconsistent:1;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int nodiskspace:1;
b515981702133b9aaea1aff378493f054c14d46cDwight Engen};
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano/* needed to remove annoying warnings about not initializing all struct
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano members.. */
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcano#define MAIL_INDEX_PRIVATE_FILL \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen 0, 0, 0, 0, 0, 0, 0, 0, 0 \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* defaults - same as above but prefixed with mail_index_. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_open(MailIndex *index, int update_recent, int fast);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_open_or_create(MailIndex *index, int update_recent, int fast);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_set_lock(MailIndex *index, MailLockType lock_type);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_try_lock(MailIndex *index, MailLockType lock_type);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_fsck(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight EngenMailIndexHeader *mail_index_get_header(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight EngenMailIndexRecord *mail_index_lookup(MailIndex *index, unsigned int seq);
b515981702133b9aaea1aff378493f054c14d46cDwight EngenMailIndexRecord *mail_index_next(MailIndex *index, MailIndexRecord *rec);
b515981702133b9aaea1aff378493f054c14d46cDwight EngenMailIndexRecord *mail_index_lookup_uid_range(MailIndex *index,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int first_uid,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int last_uid,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int *seq_r);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenconst char *mail_index_lookup_field(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailField field);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenconst void *mail_index_lookup_field_raw(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailField field, size_t *size);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenvoid mail_index_cache_fields_later(MailIndex *index, MailField field);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_expunge(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int seq, int external_change);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_update_flags(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen unsigned int seq, MailFlags flags,
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Brauner int external_change);
0d4137ccb25910b27e0e648a3aa7506f2541c4e6Christian Braunerint mail_index_append_begin(MailIndex *index, MailIndexRecord **rec);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_append_end(MailIndex *index, MailIndexRecord *rec);
b515981702133b9aaea1aff378493f054c14d46cDwight EngenMailIndexUpdate *mail_index_update_begin(MailIndex *index,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailIndexRecord *rec);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_update_end(MailIndexUpdate *update);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenvoid mail_index_update_field(MailIndexUpdate *update, MailField field,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen const char *value, size_t extra_space);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenvoid mail_index_update_field_raw(MailIndexUpdate *update, MailField field,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen const void *value, size_t size);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenconst char *mail_index_get_last_error(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_is_diskspace_error(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_is_inconsistency_error(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* INTERNAL: */
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_mmap_update(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenvoid mail_index_init_header(MailIndexHeader *hdr);
63376d7db32acf2f8582627e5ff01d8d3f0d46d1Daniel Lezcanovoid mail_index_close(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_fmsync(MailIndex *index, size_t size);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_verify_hole_range(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenvoid mail_index_mark_flag_changes(MailIndex *index, MailIndexRecord *rec,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailFlags old_flags, MailFlags new_flags);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenvoid mail_index_update_headers(MailIndexUpdate *update, IBuffer *inbuf,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MailField cache_fields,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen MessageHeaderFunc header_func, void *context);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_update_cache(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_compress(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_compress_data(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engenint mail_index_truncate(MailIndex *index);
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* Max. mmap()ed size for a message */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define MAIL_MMAP_BLOCK_SIZE (1024*256)
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* Delete unused non-local temp files after 24h. Just to be sure we don't
b515981702133b9aaea1aff378493f054c14d46cDwight Engen delete it too early. The temp files don't harm much anyway. */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define TEMP_FILE_TIMEOUT (60*24)
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* number of records to always keep allocated in index file,
b515981702133b9aaea1aff378493f054c14d46cDwight Engen either used or unused */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_MIN_RECORDS_COUNT 64
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* when empty space in index file gets full, grow the file n% larger */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_GROW_PERCENTAGE 10
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* ftruncate() the index file when only n% of it is in use */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_TRUNCATE_PERCENTAGE 30
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* don't truncate whole file anyway, keep n% of the empty space */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_TRUNCATE_KEEP_PERCENTAGE 10
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* Compress the file when deleted space reaches n% of total size */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_COMPRESS_PERCENTAGE 50
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* uoff_t to index file for given record */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_FILE_POSITION(index, ptr) \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen ((uoff_t) ((char *) (ptr) - (char *) ((index)->mmap_base)))
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* index number for uoff_t position */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_POSITION_INDEX(pos) \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen (((pos) - sizeof(MailIndexHeader)) / sizeof(MailIndexRecord))
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* index number for given record */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_RECORD_INDEX(index, ptr) \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen INDEX_POSITION_INDEX(INDEX_FILE_POSITION(index, ptr))
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* mark the index corrupted */
0d9acb997fcb22ca6493535fd53ef0c4ee5bd156Dwight Engen#define INDEX_MARK_CORRUPTED(index) \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen STMT_START { (index)->set_flags |= MAIL_INDEX_FLAG_REBUILD; } STMT_END
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* get number of records in mmaped index */
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner#define MAIL_INDEX_RECORD_COUNT(index) \
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner ((index->mmap_used_length - sizeof(MailIndexHeader)) / \
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner sizeof(MailIndexRecord))
e73bcbbee9bf040512585099cd68677bff02c130Christian Brauner
b515981702133b9aaea1aff378493f054c14d46cDwight Engen/* minimum size for index file */
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#define INDEX_FILE_MIN_SIZE \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen (sizeof(MailIndexHeader) + \
b515981702133b9aaea1aff378493f054c14d46cDwight Engen INDEX_MIN_RECORDS_COUNT * sizeof(MailIndexRecord))
b515981702133b9aaea1aff378493f054c14d46cDwight Engen
b515981702133b9aaea1aff378493f054c14d46cDwight Engen#endif
b515981702133b9aaea1aff378493f054c14d46cDwight Engen