mail-index-open.c revision 406a92a344f789e6ec763104b03de3f0b8fcfdb7
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic int mail_index_open_init(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen (hdr->flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((hdr->flags & MAIL_INDEX_FLAG_DIRTY_MESSAGES) != 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* update \Recent message counters */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT) != 0 &&
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* keep last_recent_uid to next_uid-1 */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen index->first_recent_uid = index->header->last_nonrecent_uid+1;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen index->header->last_nonrecent_uid = index->header->next_uid-1;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen index->first_recent_uid = hdr->last_nonrecent_uid+1;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (hdr->next_uid >= MAX_ALLOWED_UID - 1000) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen /* UID values are getting too high, rebuild index */
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen /* finally reset the modify log marks, fsck or syncing might
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen have deleted some messages, and since we're only just
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen opening the index, there's no need to remember them */
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (!mail_modifylog_mark_synced(index->modifylog))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic int index_open_and_fix(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* open/create the index files */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen if ((index->set_flags & MAIL_INDEX_FLAG_REBUILD) == 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* data file is corrupted, need to rebuild index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* custom flags file needs to be open before
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen rebuilding index */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0 ||
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen (index->header->flags & MAIL_INDEX_FLAG_REBUILD) != 0) {
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen /* no inconsistency problems since we're still opening
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_FSCK) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen /* index needs fscking */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((index->header->flags & MAIL_INDEX_FLAG_REBUILD_TREE) != 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* sync ourself. do it before updating cache and compression
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen which may happen because of this. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->sync_and_lock(index, MAIL_LOCK_SHARED, NULL) &&
156736910057b280cb9999d4c6c7221c4c80f5c2Timo Sirainen /* we never want to keep shared lock if syncing happens to set it.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen either exclusive or nothing (NOTE: drop it directly, not through
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->set_lock() so mbox lock won't be affected). */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_UNLOCK))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_FAST) == 0) {
81b1d14891415fef0c2f37ef1ef3680cdcc600f1Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* remove deleted blocks from index file */
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_CACHE_FIELDS) {
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen /* need to update cached fields */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS_DATA) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* remove unused space from index data file.
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen keep after cache updates which may move data
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen and create unused space */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenstatic int mail_index_read_header(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* missing data */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenstatic int mail_index_is_compatible(const struct mail_index_header *hdr)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return hdr->compat_data[0] == MAIL_INDEX_VERSION &&
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[1] == MAIL_INDEX_COMPAT_FLAGS &&
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[2] == sizeof(unsigned int) &&
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainenstatic int mail_index_init_file(struct mail_index *index,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen index_set_syscall_error(index, "write_full()");
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (file_set_size(index->fd, (off_t)file_size) < 0) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen index_set_syscall_error(index, "file_set_size()");
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid mail_index_init_header(struct mail_index *index,
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen hdr->compat_data[1] = MAIL_INDEX_COMPAT_FLAGS;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* mark the index requiring rebuild - rebuild() removes this flag
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen when it succeeds */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* set the fields we always want to cache,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen but not if we're building into memory */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen hdr->cache_fields |= index->default_cache_fields;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->used_file_size = sizeof(struct mail_index_header);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic void mail_index_cleanup_temp_files(const char *dir)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen unlink_lockfiles(dir, t_strconcat("temp.", my_hostname, NULL),
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenvoid mail_index_init(struct mail_index *index, const char *dir)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->mail_read_mmaped = getenv("MAIL_READ_MMAPED") != NULL;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic int mail_index_create_memory(struct mail_index *index,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen index->mmap_full_length = INDEX_FILE_MIN_SIZE;
4da70fe8c9cb6e57b36103d78ab1e9c8654f76d9Timo Sirainen index->mmap_base = mmap_anon(index->mmap_full_length);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return index_set_error(index, "mmap_anon() failed: %m");
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen mail_index_init_header(index, index->mmap_base);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->mmap_used_length = index->header->used_file_size;
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen index->filepath = i_strdup_printf("(in-memory index for %s)",
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainenstatic int mail_index_open_index(struct mail_index *index,
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0)
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen /* if index is being created, we'll wait here until it's finished */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_wait_lock(index, MAIL_LOCK_TO_FLOCK(index->lock_type)))
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen mprotect(index->mmap_base, index->mmap_used_length,
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen if ((ret = mail_index_read_header(index, &hdr)) < 0)
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen if (ret == 0 || !mail_index_is_compatible(&hdr) ||
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen /* so, we're creating the index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (index->lock_type != MAIL_LOCK_EXCLUSIVE) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* have to get exclusive lock first */
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen /* we don't want to keep the shared lock while opening
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen indexes. opening should work unlocked and some
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen things want exclusive lock */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((index->set_flags & MAIL_INDEX_FLAG_REBUILD) == 0 ||
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen (flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* needs a rebuild */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen return mail_index_create_memory(index, flags);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen /* open/create the file */
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen path = t_strconcat(index->dir, "/", INDEX_FILE_PREFIX, NULL);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) != 0)
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen index->fd = open(path, O_RDWR | O_CREAT, 0660);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen index_file_set_syscall_error(index, path, "open()");
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen return mail_index_create_memory(index, flags);