c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#ifndef MAIL_TRANSACTION_LOG_VIEW_H
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#define MAIL_TRANSACTION_LOG_VIEW_H
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainenstruct dotlock_settings;
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen
cc833a7a4e2258afdc834ace4bfe6579820a1df3Timo Sirainen/* Synchronization can take a while sometimes, especially when copying lots of
cc833a7a4e2258afdc834ace4bfe6579820a1df3Timo Sirainen mails. */
97cb20eb77d486ef67eac50567e3080faca025c1Timo Sirainen#define MAIL_TRANSACTION_LOG_LOCK_TIMEOUT (3*60)
97cb20eb77d486ef67eac50567e3080faca025c1Timo Sirainen#define MAIL_TRANSACTION_LOG_LOCK_CHANGE_TIMEOUT (3*60)
cc833a7a4e2258afdc834ace4bfe6579820a1df3Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen#define MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file) ((file)->fd == -1)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen#define LOG_FILE_MODSEQ_CACHE_SIZE 10
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenstruct modseq_cache {
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen uoff_t offset;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen uint64_t highest_modseq;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen};
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_transaction_log_file {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log *log;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_file *next;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen /* refcount=0 is a valid state. files start that way, and they're
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen freed only when mail_transaction_logs_clean() is called. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int refcount;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *filepath;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ino_t st_ino;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dev_t st_dev;
55a210942dc7da58b2fd0b11bed8da6b030af5c1Timo Sirainen time_t last_mtime;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen uoff_t last_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
52d2b356e3ddb4e59ee09c10d47add9d3280284bAki Tuomi time_t last_mmap_error_time;
52d2b356e3ddb4e59ee09c10d47add9d3280284bAki Tuomi
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_transaction_log_header hdr;
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen buffer_t mmap_buffer;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_t *buffer;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t buffer_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *mmap_base;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t mmap_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* points to the next uncommitted transaction. usually same as EOF. */
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen uoff_t sync_offset;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen /* highest modseq at sync_offset */
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen uint64_t sync_highest_modseq;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen /* saved_tail_offset is the offset that was last written to transaction
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen log. max_tail_offset is what should be written to the log the next
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen time a transaction is written. transaction log handling may update
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen max_tail_offset automatically by making it skip external transactions
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi after the last saved offset (to avoid re-reading them needlessly). */
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen uoff_t saved_tail_offset, max_tail_offset;
88b8aea03a24ef7a9efc30399080487b7eb03537Timo Sirainen /* don't give warnings about saved_tail_offset shrinking if
88b8aea03a24ef7a9efc30399080487b7eb03537Timo Sirainen sync_offset is less than this. */
88b8aea03a24ef7a9efc30399080487b7eb03537Timo Sirainen uoff_t saved_tail_sync_offset;
44ff75ca53188056ff5a3e50428e3f2078800b3cTimo Sirainen
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen /* if we've seen _INDEX_[UN9DELETED transaction in this file,
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen this is the offset. otherwise (uoff_t)-1 */
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen uoff_t index_deleted_offset, index_undeleted_offset;
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen struct modseq_cache modseq_cache[LOG_FILE_MODSEQ_CACHE_SIZE];
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct file_lock *file_lock;
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen time_t lock_created;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool locked:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool locked_sync_offset_updated:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool corrupted:1;
5e03576913a0030de6f8d22c79e353a968a6a35fTimo Sirainen bool need_rotate:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_transaction_log {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_index *index;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_transaction_log_view *views;
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen char *filepath, *filepath2;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
45e62043058738e294f89504c319d852e25943ccTimo Sirainen /* files is a linked list of all the opened log files. the list is
45e62043058738e294f89504c319d852e25943ccTimo Sirainen sorted by the log file sequence, so that transaction views can use
45e62043058738e294f89504c319d852e25943ccTimo Sirainen them easily. head contains a pointer to the newest log file. */
45e62043058738e294f89504c319d852e25943ccTimo Sirainen struct mail_transaction_log_file *files, *head;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* open_file is used temporarily while opening the log file.
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if _open() failed, it's left there for _create(). */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_transaction_log_file *open_file;
d5960ce1c0adda5c9e259bc429123ebc29c60baeTimo Sirainen
d5960ce1c0adda5c9e259bc429123ebc29c60baeTimo Sirainen unsigned int dotlock_count;
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen struct dotlock *dotlock;
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool nfs_flush:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool log_2_unlink_checked:1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_transaction_log_file_set_corrupted(struct mail_transaction_log_file *file,
6eb30032b4a50c383dea4c9c74342d906de6ad36Timo Sirainen const char *fmt, ...)
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen ATTR_FORMAT(2, 3);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainenvoid mail_transaction_log_get_dotlock_set(struct mail_transaction_log *log,
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen struct dotlock_settings *set_r);
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct mail_transaction_log_file *
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenmail_transaction_log_file_alloc_in_memory(struct mail_transaction_log *log);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstruct mail_transaction_log_file *
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenmail_transaction_log_file_alloc(struct mail_transaction_log *log,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const char *path);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid mail_transaction_log_file_free(struct mail_transaction_log_file **file);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
c0d1bfc45e224251cb549de8d8804861e8acb517Timo Sirainen/* Returns 1 if log was opened, 0 if it didn't exist or was already open,
c0d1bfc45e224251cb549de8d8804861e8acb517Timo Sirainen -1 if error. */
c0d1bfc45e224251cb549de8d8804861e8acb517Timo Sirainenint mail_transaction_log_file_open(struct mail_transaction_log_file *file,
c0d1bfc45e224251cb549de8d8804861e8acb517Timo Sirainen const char **reason_r);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenint mail_transaction_log_file_create(struct mail_transaction_log_file *file,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen bool reset);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint mail_transaction_log_file_lock(struct mail_transaction_log_file *file);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenint mail_transaction_log_find_file(struct mail_transaction_log *log,
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen uint32_t file_seq, bool nfs_flush,
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen struct mail_transaction_log_file **file_r,
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen const char **reason_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen/* Returns 1 if ok, 0 if file is corrupted or offset range is invalid,
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainen -1 if I/O error */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_transaction_log_file_map(struct mail_transaction_log_file *file,
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen uoff_t start_offset, uoff_t end_offset,
ce9d23c7c1e621398d2572a1d95171136f7ef6a2Timo Sirainen const char **reason_r);
5b809b97673fb0a73aa5b9d82122612d699f6c5bTimo Sirainenint mail_transaction_log_file_move_to_memory(struct mail_transaction_log_file *file);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid mail_transaction_logs_clean(struct mail_transaction_log *log);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenbool mail_transaction_log_want_rotate(struct mail_transaction_log *log);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenint mail_transaction_log_rotate(struct mail_transaction_log *log, bool reset);
6ded8819b9002150a95a7615e4f64f091c250464Timo Sirainenint mail_transaction_log_lock_head(struct mail_transaction_log *log,
6ded8819b9002150a95a7615e4f64f091c250464Timo Sirainen const char *lock_reason);
2f8da04d700cc23fcd6630226a4866e828b761bdTimo Sirainenvoid mail_transaction_log_file_unlock(struct mail_transaction_log_file *file,
2f8da04d700cc23fcd6630226a4866e828b761bdTimo Sirainen const char *lock_reason);
b87a4156eca6dcf6b29c504eb0cb9be2fdb11b63Timo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenvoid mail_transaction_update_modseq(const struct mail_transaction_header *hdr,
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen const void *data, uint64_t *cur_modseq,
92dab926b2f2270057b40a907a00cf8eb2309ed6Timo Sirainen unsigned int version);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenint mail_transaction_log_file_get_highest_modseq_at(
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen struct mail_transaction_log_file *file,
a0c8af555ec481ab12c2a99518cf7b20debd1627Timo Sirainen uoff_t offset, uint64_t *highest_modseq_r,
a0c8af555ec481ab12c2a99518cf7b20debd1627Timo Sirainen const char **error_r);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenint mail_transaction_log_file_get_modseq_next_offset(
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen struct mail_transaction_log_file *file,
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen uint64_t modseq, uoff_t *next_offset_r);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif