mail-tree.c revision c7b3f8406f77d95bcc2480deebbde86e165263ae
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "mmap-util.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "file-set-size.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "write-full.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-index.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-index-util.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "mail-tree.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <unistd.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <fcntl.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define MAIL_TREE_MIN_SIZE \
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen (sizeof(struct mail_tree_header) + \
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_tree_node))
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstatic int tree_set_syscall_error(struct mail_tree *tree, const char *function)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen i_assert(function != NULL);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen index_set_error(tree->index, "%s failed with binary tree file %s: %m",
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen function, tree->filepath);
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen return FALSE;
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen}
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainenint _mail_tree_set_corrupted(struct mail_tree *tree, const char *fmt, ...)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen{
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen va_list va;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen va_start(va, fmt);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen t_push();
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen index_set_error(tree->index, "Corrupted binary tree file %s: %s",
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen tree->filepath, t_strdup_vprintf(fmt, va));
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen t_pop();
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen va_end(va);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* make sure we don't get back here */
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen tree->index->inconsistent = TRUE;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen (void)unlink(tree->filepath);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return FALSE;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic int mmap_update(struct mail_tree *tree)
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen{
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen i_assert(!tree->anon_mmap);
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen if (tree->mmap_base != NULL) {
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen /* make sure we're synced before munmap() */
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen if (tree->modified &&
59e26ff34b05cd971a111f8a42fc60c13d9f688bTimo Sirainen msync(tree->mmap_base, tree->mmap_highwater, MS_SYNC) < 0)
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen return tree_set_syscall_error(tree, "msync()");
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen tree->modified = FALSE;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen if (munmap(tree->mmap_base, tree->mmap_full_length) < 0)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen tree_set_syscall_error(tree, "munmap()");
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen }
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen tree->mmap_used_length = 0;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen tree->header = NULL;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen tree->node_base = NULL;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen tree->mmap_base = mmap_rw_file(tree->fd, &tree->mmap_full_length);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen if (tree->mmap_base == MAP_FAILED) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen tree->mmap_base = NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return tree_set_syscall_error(tree, "mmap()");
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen debug_mprotect(tree->mmap_base, tree->mmap_full_length, tree->index);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenstatic int mmap_verify(struct mail_tree *tree)
571fd6ff94570ee11a72a20b649acfdac2495919Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct mail_tree_header *hdr;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen unsigned int extra;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (tree->mmap_full_length <
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen sizeof(struct mail_tree_header) + sizeof(struct mail_tree_node)) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen index_set_error(tree->index, "Too small binary tree file %s",
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen tree->filepath);
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen (void)unlink(tree->filepath);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen extra = (tree->mmap_full_length - sizeof(struct mail_tree_header)) %
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen sizeof(struct mail_tree_node);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (extra != 0) {
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen /* partial write or corrupted -
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen truncate the file to valid length */
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen tree->mmap_full_length -= extra;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (ftruncate(tree->fd, (off_t)tree->mmap_full_length) < 0)
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen tree_set_syscall_error(tree, "ftruncate()");
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen }
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen hdr = tree->mmap_base;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (hdr->used_file_size > tree->mmap_full_length) {
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen _mail_tree_set_corrupted(tree,
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen "used_file_size larger than real file size "
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen "(%"PRIuUOFF_T" vs %"PRIuSIZE_T")",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen hdr->used_file_size, tree->mmap_full_length);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen if (hdr->used_file_size < sizeof(struct mail_tree_header) ||
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen (hdr->used_file_size - sizeof(struct mail_tree_header)) %
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen sizeof(struct mail_tree_node) != 0) {
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen _mail_tree_set_corrupted(tree,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen "Invalid used_file_size in header (%"PRIuUOFF_T")",
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen hdr->used_file_size);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return FALSE;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen tree->header = tree->mmap_base;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen tree->node_base = (struct mail_tree_node *)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen ((char *) tree->mmap_base + sizeof(struct mail_tree_header));
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen tree->sync_id = hdr->sync_id;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen tree->mmap_used_length = hdr->used_file_size;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen tree->mmap_highwater = tree->mmap_used_length;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen return TRUE;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen}
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint _mail_tree_mmap_update(struct mail_tree *tree, int forced)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen debug_mprotect(tree->mmap_base, tree->mmap_full_length,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tree->index);
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen if (!forced && tree->header != NULL &&
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen tree->sync_id == tree->header->sync_id) {
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen /* make sure file size hasn't changed */
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen tree->mmap_used_length = tree->header->used_file_size;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (tree->mmap_used_length > tree->mmap_full_length) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_panic("Tree file size was grown without "
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen "updating sync_id");
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return TRUE;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return mmap_update(tree) && mmap_verify(tree);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic struct mail_tree *mail_tree_open(struct mail_index *index)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_tree *tree;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen const char *path;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int fd;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen path = t_strconcat(index->filepath, ".tree", NULL);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen fd = open(path, O_RDWR | O_CREAT, 0660);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (fd == -1) {
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen if (errno == ENOSPC)
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen index->nodiskspace = TRUE;
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen index_file_set_syscall_error(index, path, "open()");
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen return NULL;
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen }
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen tree = i_new(struct mail_tree, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tree->fd = fd;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen tree->index = index;
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen tree->filepath = i_strdup(path);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen index->tree = tree;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen return tree;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic struct mail_tree *mail_tree_create_anon(struct mail_index *index)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct mail_tree *tree;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen tree = i_new(struct mail_tree, 1);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen tree->anon_mmap = TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tree->fd = -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tree->index = index;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen tree->filepath = i_strdup("(in-memory tree)");
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen index->tree = tree;
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen return tree;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen}
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainenint mail_tree_create(struct mail_index *index)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen struct mail_tree *tree;
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen tree = !index->nodiskspace ? mail_tree_open(index) :
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_tree_create_anon(index);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (tree == NULL)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen if (!mail_tree_rebuild(tree)) {
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen mail_tree_free(tree);
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen return FALSE;
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen }
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen return TRUE;
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen}
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic int mail_tree_open_init(struct mail_tree *tree)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (!mmap_update(tree))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return FALSE;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (tree->mmap_full_length == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* just created it */
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (!mmap_verify(tree)) {
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen /* broken header */
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen return FALSE;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (tree->header->indexid != tree->index->indexid) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen index_set_error(tree->index,
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen "IndexID mismatch for binary tree file %s",
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen tree->filepath);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return FALSE;
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen }
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return TRUE;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenint mail_tree_open_or_create(struct mail_index *index)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen struct mail_tree *tree;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree = mail_tree_open(index);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (tree == NULL)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen return FALSE;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (!mail_tree_open_init(tree)) {
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen /* lock and check again, just to avoid rebuilding it twice
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if two processes notice the error at the same time */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (!tree->index->set_lock(tree->index, MAIL_LOCK_EXCLUSIVE)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_tree_free(tree);
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen return FALSE;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen }
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen if (!mail_tree_open_init(tree)) {
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (!mail_tree_rebuild(tree)) {
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen mail_tree_free(tree);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen return FALSE;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen }
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
8b2cf1c1bd8ddcea0525b62fd35ba76e136828a1Timo Sirainen return TRUE;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen}
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainenstatic void mail_tree_close(struct mail_tree *tree)
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen{
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (tree->anon_mmap) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (munmap_anon(tree->mmap_base, tree->mmap_full_length) < 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tree_set_syscall_error(tree, "munmap_anon()");
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen } else if (tree->mmap_base != NULL) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (munmap(tree->mmap_base, tree->mmap_full_length) < 0)
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree_set_syscall_error(tree, "munmap()");
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree->mmap_base = NULL;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree->mmap_full_length = 0;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree->mmap_used_length = 0;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree->header = NULL;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (tree->fd != -1) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (close(tree->fd) < 0)
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree_set_syscall_error(tree, "close()");
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen tree->fd = -1;
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen }
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen i_free(tree->filepath);
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenvoid mail_tree_free(struct mail_tree *tree)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen tree->index->tree = NULL;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail_tree_close(tree);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen i_free(tree);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
4e8d6d03c2ff85448df79b181a2ea850fb5d4199Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenstatic int mail_tree_init(struct mail_tree *tree)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct mail_tree_header hdr;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* first node is always used, and is the RBNULL node */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen memset(&hdr, 0, sizeof(struct mail_tree_header));
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen hdr.indexid = tree->index->indexid;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen hdr.used_file_size = sizeof(struct mail_tree_header) +
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen sizeof(struct mail_tree_node);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (tree->anon_mmap) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree->mmap_full_length = MAIL_TREE_MIN_SIZE;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen tree->mmap_base = mmap_anon(tree->mmap_full_length);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen memcpy(tree->mmap_base, &hdr, sizeof(struct mail_tree_header));
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return mmap_verify(tree);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (lseek(tree->fd, 0, SEEK_SET) < 0)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return tree_set_syscall_error(tree, "lseek()");
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (write_full(tree->fd, &hdr, sizeof(hdr)) < 0) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (errno == ENOSPC)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen tree->index->nodiskspace = TRUE;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return tree_set_syscall_error(tree, "write_full()");
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (file_set_size(tree->fd, MAIL_TREE_MIN_SIZE) < 0) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (errno == ENOSPC)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen tree->index->nodiskspace = TRUE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return tree_set_syscall_error(tree, "file_set_size()");
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen return TRUE;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen}
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainenint mail_tree_rebuild(struct mail_tree *tree)
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen{
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen struct mail_index_record *rec;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (!tree->index->set_lock(tree->index, MAIL_LOCK_EXCLUSIVE))
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return FALSE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen if (!mail_tree_init(tree) ||
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen (!tree->anon_mmap && !_mail_tree_mmap_update(tree, TRUE))) {
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen tree->index->header->flags |= MAIL_INDEX_FLAG_REBUILD_TREE;
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen return FALSE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen rec = tree->index->lookup(tree->index, 1);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen while (rec != NULL) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (!mail_tree_insert(tree, rec->uid,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen INDEX_RECORD_INDEX(tree->index, rec))) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen tree->index->header->flags |=
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen MAIL_INDEX_FLAG_REBUILD_TREE;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return FALSE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen rec = tree->index->next(tree->index, rec);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen return TRUE;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainenint mail_tree_sync_file(struct mail_tree *tree, int *fsync_fd)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen *fsync_fd = -1;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen if (!tree->modified || tree->anon_mmap)
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen return TRUE;
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen i_assert(tree->mmap_base != NULL);
63866b7a81355543832d3fe01cd744ddd4ea197bTimo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (msync(tree->mmap_base, tree->mmap_highwater, MS_SYNC) < 0)
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen return tree_set_syscall_error(tree, "msync()");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen tree->mmap_highwater = tree->mmap_used_length;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen tree->modified = FALSE;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen *fsync_fd = tree->fd;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen return TRUE;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen}
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainenint _mail_tree_grow(struct mail_tree *tree)
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen{
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen uoff_t new_fsize;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen unsigned int grow_count;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen void *base;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen grow_count = tree->index->header->messages_count *
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen INDEX_GROW_PERCENTAGE / 100;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (grow_count < 16)
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen grow_count = 16;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen new_fsize = (uoff_t)tree->mmap_full_length +
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen (grow_count * sizeof(struct mail_tree_node));
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainen i_assert(new_fsize < OFF_T_MAX);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen if (tree->anon_mmap) {
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen i_assert(new_fsize < SSIZE_T_MAX);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen base = mremap_anon(tree->mmap_base, tree->mmap_full_length,
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen (size_t)new_fsize, MREMAP_MAYMOVE);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen if (base == MAP_FAILED)
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainen return tree_set_syscall_error(tree, "mremap_anon()");
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen tree->mmap_base = base;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen tree->mmap_full_length = (size_t)new_fsize;
db3ebf659c17fc5ca348a997e6311d20cfbb78e9Timo Sirainen return mmap_verify(tree);
db3ebf659c17fc5ca348a997e6311d20cfbb78e9Timo Sirainen }
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen if (file_set_size(tree->fd, (off_t)new_fsize) < 0) {
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen if (errno == ENOSPC)
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen tree->index->nodiskspace = TRUE;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen return tree_set_syscall_error(tree, "file_set_size()");
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen }
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen /* file size changed, let others know about it too by changing
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen sync_id in header. */
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen tree->header->sync_id++;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen tree->modified = TRUE;
46631c1d903c409444b1b1c4a1d41a033c09ee37Timo Sirainen
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen if (!_mail_tree_mmap_update(tree, TRUE))
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen return FALSE;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen
71da447014454c84828d9dface77219875554d7dTimo Sirainen return TRUE;
71da447014454c84828d9dface77219875554d7dTimo Sirainen}
71da447014454c84828d9dface77219875554d7dTimo Sirainen
71da447014454c84828d9dface77219875554d7dTimo Sirainenvoid _mail_tree_truncate(struct mail_tree *tree)
71da447014454c84828d9dface77219875554d7dTimo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* pretty much copy&pasted from mail_index_compress() */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uoff_t empty_space, truncate_threshold;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen i_assert(tree->index->lock_type == MAIL_LOCK_EXCLUSIVE);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (tree->mmap_full_length <= MAIL_TREE_MIN_SIZE || tree->anon_mmap)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen empty_space = tree->mmap_full_length - tree->mmap_used_length;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen truncate_threshold =
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen tree->mmap_full_length / 100 * INDEX_TRUNCATE_PERCENTAGE;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (empty_space > truncate_threshold) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen tree->mmap_full_length = tree->mmap_used_length +
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen (empty_space * INDEX_TRUNCATE_KEEP_PERCENTAGE / 100);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* keep the size record-aligned */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen tree->mmap_full_length -= (tree->mmap_full_length -
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen sizeof(struct mail_tree_header)) %
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen sizeof(struct mail_tree_node);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (tree->mmap_full_length < MAIL_TREE_MIN_SIZE)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen tree->mmap_full_length = MAIL_TREE_MIN_SIZE;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (ftruncate(tree->fd, (off_t)tree->mmap_full_length) < 0)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen tree_set_syscall_error(tree, "ftruncate()");
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen tree->header->sync_id++;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen