mail-index-private.h revision fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#ifndef __MAIL_INDEX_PRIVATE_H
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#define __MAIL_INDEX_PRIVATE_H
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger/* Make sure F_RDLCK, F_WRLCK and F_UNLCK get defined */
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#include <unistd.h>
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#include <fcntl.h>
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#include "mail-index.h"
802014878b7383de536e4fa0ceced1bce3217eadDaniel Couto Vale
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornbergerstruct mail_transaction_header;
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornbergerstruct mail_transaction_log_view;
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornbergerstruct mail_index_sync_map_ctx;
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger/* How many seconds to wait a lock for index file. */
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#define MAIL_INDEX_LOCK_SECS 120
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger/* Index file is grown exponentially when we're adding less than this many
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger records. */
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#define MAIL_INDEX_MAX_POWER_GROW (1024*1024 / sizeof(struct mail_index_record))
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger/* How many times to retry opening index files if read/fstat returns ESTALE.
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger This happens with NFS when the file has been deleted (ie. index file was
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger rewritten by another computer than us). */
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#define MAIL_INDEX_ESTALE_RETRY_COUNT NFS_ESTALE_RETRY_COUNT
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#define MAIL_INDEX_IS_IN_MEMORY(index) \
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger ((index)->dir == NULL)
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#define MAIL_INDEX_MAP_IS_IN_MEMORY(map) \
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger ((map) != NULL && (map)->buffer != NULL)
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger#define MAIL_INDEX_MAP_IDX(map, idx) \
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger ((struct mail_index_record *) \
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger PTR_OFFSET((map)->records, (idx) * (map)->hdr.record_size))
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornbergertypedef int mail_index_expunge_handler_t(struct mail_index_sync_map_ctx *ctx,
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger uint32_t seq, const void *data,
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger void **context);
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornbergertypedef int mail_index_sync_handler_t(struct mail_index_sync_map_ctx *ctx,
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger uint32_t seq, void *old_data,
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger const void *new_data, void **context);
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornbergertypedef void mail_index_sync_lost_handler_t(struct mail_index *index);
736e78aff9e67436c35d4835c24fca667f3cadf3Julian Kornberger
555b7fd96768daf9592e7ddbd4217d784b08e451henning mueller#define MAIL_INDEX_HEADER_SIZE_ALIGN(size) \
b27c7f227c8516589a2bd127c0f74338cf56f0b2Julian Kornberger (((size) + 7) & ~7)
b27c7f227c8516589a2bd127c0f74338cf56f0b2Julian Kornberger
b27c7f227c8516589a2bd127c0f74338cf56f0b2Julian Kornbergerstruct mail_index_ext {
555b7fd96768daf9592e7ddbd4217d784b08e451henning mueller const char *name;
555b7fd96768daf9592e7ddbd4217d784b08e451henning mueller uint32_t index_idx; /* index ext_id */
555b7fd96768daf9592e7ddbd4217d784b08e451henning mueller uint32_t reset_id;
555b7fd96768daf9592e7ddbd4217d784b08e451henning mueller uint32_t hdr_offset; /* points to mail_index_ext_header.data[] */
555b7fd96768daf9592e7ddbd4217d784b08e451henning mueller uint32_t hdr_size; /* size of mail_index_ext_header.data[] */
555b7fd96768daf9592e7ddbd4217d784b08e451henning mueller uint16_t record_offset;
7b8fe34340b2727bb31fe0be67fdf684e47c3609Tim Reddehase uint16_t record_size;
7b8fe34340b2727bb31fe0be67fdf684e47c3609Tim Reddehase uint16_t record_align;
1cbb38d1d07f559b4a1c012a4833513053716007Daniel Couto Vale};
1cbb38d1d07f559b4a1c012a4833513053716007Daniel Couto Vale
c997297b21c83680cdba2953cad369b82a5b8805Tim Reddehasestruct mail_index_ext_header {
1b2e2335372f4737c0aa19da6320f7b5fd58b500Tim Reddehase uint32_t hdr_size; /* size of data[] */
1b2e2335372f4737c0aa19da6320f7b5fd58b500Tim Reddehase uint32_t reset_id;
c997297b21c83680cdba2953cad369b82a5b8805Tim Reddehase uint16_t record_offset;
7cd362a86385a020b8c674cf9199771ae3267359henning mueller uint16_t record_size;
7cd362a86385a020b8c674cf9199771ae3267359henning mueller uint16_t record_align;
291d5c781e5ce4a7c15cfb16fa4a800177135b3ehenning mueller uint16_t name_size;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski /* unsigned char name[name_size] */
2635b9bca67d93aec1bed63d10d5f92fefce06e7Till Mossakowski /* unsigned char data[hdr_size] (starting 64bit aligned) */
0c07cc350bdb8afe9b01b4340b33d89500a43106Till Mossakowski};
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
0c07cc350bdb8afe9b01b4340b33d89500a43106Till Mossakowskistruct mail_index_keyword_header {
0c07cc350bdb8afe9b01b4340b33d89500a43106Till Mossakowski uint32_t keywords_count;
0c07cc350bdb8afe9b01b4340b33d89500a43106Till Mossakowski /* struct mail_index_keyword_header_rec[] */
2635b9bca67d93aec1bed63d10d5f92fefce06e7Till Mossakowski /* char name[][] */
2635b9bca67d93aec1bed63d10d5f92fefce06e7Till Mossakowski};
2635b9bca67d93aec1bed63d10d5f92fefce06e7Till Mossakowski
2635b9bca67d93aec1bed63d10d5f92fefce06e7Till Mossakowskistruct mail_index_keyword_header_rec {
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski uint32_t count;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski uint32_t name_offset; /* relative to beginning of name[] */
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski};
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowskienum mail_index_sync_handler_type {
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski MAIL_INDEX_SYNC_HANDLER_INDEX = 0x01,
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski MAIL_INDEX_SYNC_HANDLER_VIEW = 0x02
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski};
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowskistruct mail_index_sync_handler {
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski mail_index_sync_handler_t *callback;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski enum mail_index_sync_handler_type type;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski};
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowskistruct mail_index_registered_ext {
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski const char *name;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski uint32_t index_idx; /* index ext_id */
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski uint32_t hdr_size; /* size of mail_index_ext_header.data[] */
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski uint16_t record_size;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski uint16_t record_align;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski struct mail_index_sync_handler sync_handler;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski mail_index_expunge_handler_t *expunge_handler;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski};
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
5ad93833caec560945adbce7b6f1342ef731ae83henning muellerstruct mail_index_map {
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski int refcount;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski struct mail_index_header hdr;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski const void *hdr_base;
0c07cc350bdb8afe9b01b4340b33d89500a43106Till Mossakowski void *records; /* struct mail_index_record[] */
0c07cc350bdb8afe9b01b4340b33d89500a43106Till Mossakowski unsigned int records_count;
0c07cc350bdb8afe9b01b4340b33d89500a43106Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski pool_t extension_pool;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski array_t ARRAY_DEFINE(extensions, struct mail_index_ext);
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski array_t ARRAY_DEFINE(ext_id_map, uint32_t); /* index -> file */
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski void *mmap_base;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski size_t mmap_size, mmap_used_size;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski buffer_t *buffer;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski buffer_t *hdr_copy_buf;
291d5c781e5ce4a7c15cfb16fa4a800177135b3ehenning mueller
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski array_t ARRAY_DEFINE(keyword_idx_map, unsigned int); /* file -> index */
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski /* If write_to_disk=TRUE and write_atomic=FALSE, these sequences
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski specify the range that needs to be written. Header should always
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski be rewritten. */
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski uint32_t write_seq_first, write_seq_last;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski unsigned int write_to_disk:1;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski unsigned int write_atomic:1; /* copy to new file and rename() */
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski};
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowskistruct mail_index {
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski char *dir, *prefix;
1543bf02d52779c4bc29f75de1de4d14636d0e47Till Mossakowski
struct mail_cache *cache;
struct mail_transaction_log *log;
mode_t mode;
gid_t gid;
pool_t extension_pool;
array_t ARRAY_DEFINE(extensions, struct mail_index_registered_ext);
array_t ARRAY_DEFINE(sync_lost_handlers,
mail_index_sync_lost_handler_t *);
char *filepath;
int fd;
struct mail_index_map *map;
const struct mail_index_header *hdr;
uint32_t indexid;
int lock_type, shared_lock_count, excl_lock_count;
unsigned int lock_id;
char *copy_lock_path;
struct dotlock *dotlock;
enum mail_index_lock_method lock_method;
/* These are typically same as map->hdr->log_file_*, but with
mmap_disable we may have synced more than index */
uint32_t sync_log_file_seq;
uoff_t sync_log_file_offset;
pool_t keywords_pool;
array_t ARRAY_DEFINE(keywords, const char *);
struct hash_table *keywords_hash; /* name -> idx */
uint32_t keywords_ext_id;
unsigned int last_grow_count;
char *error;
unsigned int nodiskspace:1;
unsigned int index_lock_timeout:1;
unsigned int opened:1;
unsigned int log_locked:1;
unsigned int mmap_disable:1;
unsigned int mmap_no_write:1;
unsigned int readonly:1;
unsigned int fsck:1;
unsigned int sync_update:1;
unsigned int mapping:1;
};
/* Add/replace sync handler for specified extra record. */
void mail_index_register_expunge_handler(struct mail_index *index,
uint32_t ext_id,
mail_index_expunge_handler_t *cb);
void mail_index_unregister_expunge_handler(struct mail_index *index,
uint32_t ext_id);
void mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
mail_index_sync_handler_t *cb,
enum mail_index_sync_handler_type type);
void mail_index_unregister_sync_handler(struct mail_index *index,
uint32_t ext_id);
void mail_index_register_sync_lost_handler(struct mail_index *index,
mail_index_sync_lost_handler_t *cb);
void mail_index_unregister_sync_lost_handler(struct mail_index *index,
mail_index_sync_lost_handler_t *cb);
int mail_index_write_base_header(struct mail_index *index,
const struct mail_index_header *hdr);
int mail_index_reopen(struct mail_index *index, int fd);
int mail_index_create_tmp_file(struct mail_index *index, const char **path_r);
/* Returns 0 = ok, -1 = error. If update_index is TRUE, reopens the index
file if needed to get later version of it (not necessarily latest due to
races, unless transaction log is exclusively locked). */
int mail_index_lock_shared(struct mail_index *index, bool update_index,
unsigned int *lock_id_r);
/* Returns 0 = ok, -1 = error. */
int mail_index_lock_exclusive(struct mail_index *index,
unsigned int *lock_id_r);
void mail_index_unlock(struct mail_index *index, unsigned int lock_id);
/* Returns TRUE if given lock_id is valid. */
bool mail_index_is_locked(struct mail_index *index, unsigned int lock_id);
int mail_index_lock_fd(struct mail_index *index, const char *path, int fd,
int lock_type, unsigned int timeout_secs);
/* Reopen index file if it has changed. */
int mail_index_reopen_if_needed(struct mail_index *index);
/* Map index file to memory, replacing the previous mapping for index.
Returns 1 = ok, 0 = corrupted, -1 = error. If index needs fscking, it
returns 1 but sets index->fsck = TRUE. */
int mail_index_map(struct mail_index *index, bool force);
/* Read the latest available header. Normally this is pretty much the same as
calling mail_index_map(), but with mmap_disable the header can be generated
by reading just log files, so eg. log_file_*_offset values can be wrong.
Returns 1 = ok, 0 = EOF, -1 = error. */
int mail_index_get_latest_header(struct mail_index *index,
struct mail_index_header *hdr_r);
/* Unreference given mapping and unmap it if it's dropped to zero. */
void mail_index_unmap(struct mail_index *index, struct mail_index_map **map);
struct mail_index_map *
mail_index_map_clone(struct mail_index_map *map, uint32_t new_record_size);
uint32_t mail_index_map_lookup_ext(struct mail_index_map *map,
const char *name);
uint32_t
mail_index_map_register_ext(struct mail_index *index,
struct mail_index_map *map, const char *name,
uint32_t hdr_offset, uint32_t hdr_size,
uint32_t record_offset, uint32_t record_size,
uint32_t record_align, uint32_t reset_id);
int mail_index_map_get_ext_idx(struct mail_index_map *map,
uint32_t ext_id, uint32_t *idx_r);
const struct mail_index_ext *
mail_index_view_get_ext(struct mail_index_view *view, uint32_t ext_id);
void mail_index_view_recalc_counters(struct mail_index_view *view);
int mail_index_map_parse_keywords(struct mail_index *index,
struct mail_index_map *map);
int mail_index_fix_header(struct mail_index *index, struct mail_index_map *map,
struct mail_index_header *hdr, const char **error_r);
bool mail_index_is_ext_synced(struct mail_transaction_log_view *log_view,
struct mail_index_map *map);
void mail_index_view_transaction_ref(struct mail_index_view *view);
void mail_index_view_transaction_unref(struct mail_index_view *view);
void mail_index_set_inconsistent(struct mail_index *index);
int mail_index_set_error(struct mail_index *index, const char *fmt, ...)
__attr_format__(2, 3);
/* "%s failed with index file %s: %m" */
int mail_index_set_syscall_error(struct mail_index *index,
const char *function);
/* "%s failed with file %s: %m" */
int mail_index_file_set_syscall_error(struct mail_index *index,
const char *filepath,
const char *function);
uint32_t mail_index_uint32_to_offset(uint32_t offset);
uint32_t mail_index_offset_to_uint32(uint32_t offset);
#endif