printf("log file head offset ..... = %u\n", hdr->log_file_head_offset);
}
if (hdr->minor_version >= 3) {
+ printf("log2 rotate time ......... = %u (%s)\n", hdr->log2_rotate_time, unixdate2str(hdr->log2_rotate_time));
printf("last temp file scan ...... = %u (%s)\n", hdr->last_temp_file_scan, unixdate2str(hdr->last_temp_file_scan));
}
printf("day stamp ................ = %u (%s)\n", hdr->day_stamp, unixdate2str(hdr->day_stamp));
case 2:
/* pre-v2.2 (although should have been done in v2.1 already):
make sure the old unused fields are cleared */
- map->hdr.unused_old_sync_size = 0;
+ map->hdr.unused_old_sync_size_part1 = 0;
+ map->hdr.log2_rotate_time = 0;
map->hdr.last_temp_file_scan = 0;
}
if (hdr->first_recent_uid == 0) {
uoff_t log_rotate_min_size, log_rotate_max_size;
unsigned int log_rotate_min_created_ago_secs;
unsigned int log_rotate_log2_stale_secs;
+ uint32_t pending_log2_rotate_time;
pool_t extension_pool;
ARRAY(struct mail_index_registered_ext) extensions;
&next_uid, sizeof(next_uid), FALSE);
}
}
+ if (index->pending_log2_rotate_time != 0) {
+ uint32_t log2_rotate_time = index->pending_log2_rotate_time;
+
+ mail_index_update_header(ctx->ext_trans,
+ offsetof(struct mail_index_header, log2_rotate_time),
+ &log2_rotate_time, sizeof(log2_rotate_time), TRUE);
+ index->pending_log2_rotate_time = 0;
+ }
ret2 = mail_index_transaction_commit(&ctx->ext_trans);
if (cache_lock != NULL)
hdr->log_file_seq = file->hdr.file_seq;
hdr->log_file_head_offset =
hdr->log_file_tail_offset = file->hdr.hdr_size;
+ /* Assume .log.2 was created successfully. If it
+ wasn't, it just causes an extra stat() and gets
+ fixed later on. */
+ hdr->log2_rotate_time = ioloop_time;
}
}
uint32_t log_file_tail_offset;
uint32_t log_file_head_offset;
- uint64_t unused_old_sync_size;
+ uint32_t unused_old_sync_size_part1;
+ /* Timestamp of when .log was rotated into .log.2. This can be used to
+ optimize checking when it's time to unlink it without stat()ing it.
+ 0 = unknown, -1 = .log.2 doesn't exists. */
+ uint32_t log2_rotate_time;
uint32_t last_temp_file_scan;
/* daily first UIDs that have been added to index. */
static void mail_transaction_log_2_unlink_old(struct mail_transaction_log *log)
{
struct stat st;
+ uint32_t log2_rotate_time = log->index->map->hdr.log2_rotate_time;
if (MAIL_INDEX_IS_IN_MEMORY(log->index))
return;
- if (nfs_safe_stat(log->filepath2, &st) < 0) {
- if (errno != ENOENT) {
+ if (log2_rotate_time == 0) {
+ if (nfs_safe_stat(log->filepath2, &st) == 0)
+ log2_rotate_time = st.st_mtime;
+ else if (errno == ENOENT)
+ log2_rotate_time = (uint32_t)-1;
+ else {
mail_index_set_error(log->index,
"stat(%s) failed: %m", log->filepath2);
+ return;
}
- return;
}
- if (ioloop_time - st.st_mtime >= (time_t)log->index->log_rotate_log2_stale_secs &&
- !log->index->readonly)
+ if (log2_rotate_time != (uint32_t)-1 &&
+ ioloop_time - log2_rotate_time >= (time_t)log->index->log_rotate_log2_stale_secs &&
+ !log->index->readonly) {
i_unlink_if_exists(log->filepath2);
+ log2_rotate_time = (uint32_t)-1;
+ }
+
+ if (log2_rotate_time != log->index->map->hdr.log2_rotate_time) {
+ /* Write this as part of the next sync's transaction. We're
+ here because we're already opening a sync lock, so it'll
+ always happen. It's also required especially with mdbox map
+ index, which doesn't like changes done outside syncing. */
+ log->index->pending_log2_rotate_time = log2_rotate_time;
+ }
}
int mail_transaction_log_open(struct mail_transaction_log *log)