mail-cache-transaction.c revision 8aacc9e7c84f8376822823ec98c2f551d4919b2e
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainenstatic const unsigned char *null4[] = { 0, 0, 0, 0 };
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainenint mail_cache_transaction_begin(struct mail_cache_view *view, int nonblock,
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen ctx = i_new(struct mail_cache_transaction_ctx, 1);
20b2d47ed762ca2c009aa37e360af6f223ac71bdTimo Sirainen ctx->cache_data = buffer_create_dynamic(system_pool, 8192, (size_t)-1);
20b2d47ed762ca2c009aa37e360af6f223ac71bdTimo Sirainen ctx->used_file_size = nbo_to_uint32(ctx->cache->hdr->used_file_size);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenint mail_cache_transaction_end(struct mail_cache_transaction_ctx *ctx)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic void mail_cache_transaction_flush(struct mail_cache_transaction_ctx *ctx)
20b2d47ed762ca2c009aa37e360af6f223ac71bdTimo Sirainen memset(&ctx->cache_rec, 0, sizeof(ctx->cache_rec));
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen ctx->first_seq = ctx->last_seq = ctx->prev_seq = 0;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic void mark_update(buffer_t **buf, uint32_t offset, uint32_t data)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen *buf = buffer_create_dynamic(system_pool, 1024, (size_t)-1);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic int write_mark_updates(struct mail_cache *cache)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen data = buffer_get_data(cache->trans_ctx->cache_marks, &size);
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainen if (pwrite(cache->fd, data+1, sizeof(*data), data[0]) < 0) {
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen mail_cache_set_syscall_error(cache, "pwrite()");
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainenstatic int commit_all_changes(struct mail_cache_transaction_ctx *ctx)
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainen /* write everything to disk */
4020006405eab97087f985a64b505d3cf48ceac7Timo Sirainen if (msync(cache->mmap_base, cache->mmap_length, MS_SYNC) < 0) {
4020006405eab97087f985a64b505d3cf48ceac7Timo Sirainen mail_cache_set_syscall_error(cache, "msync()");
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainen mail_cache_set_syscall_error(cache, "fdatasync()");
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen /* now that we're sure it's written, set on all the used-bits */
20b2d47ed762ca2c009aa37e360af6f223ac71bdTimo Sirainen /* update continued records count */
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen cont = nbo_to_uint32(cache->hdr->continued_record_count);
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainen cont += buffer_get_used_size(ctx->cache_marks) /
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen if (cont * 100 / cache->index->hdr->messages_count >=
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen /* too many continued rows, compress */
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainen cache->hdr->continued_record_count = uint32_to_nbo(cont);
0a1ec0f2a38370e8a073a60023b4365491947f6fTimo Sirainenmail_cache_grow(struct mail_cache_transaction_ctx *ctx, uint32_t size)
d798962a54c5cda054d57a0cfc7e5f47dfa20f6eTimo Sirainen grow_size = new_fsize / 100 * MAIL_CACHE_GROW_PERCENTAGE;
4fc52b7b25c3d3f42348903e0154840f8761f306Timo Sirainen mail_cache_set_syscall_error(cache, "fstat()");
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen if (ctx->used_file_size + size <= (uoff_t)st.st_size) {
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen /* no need to grow, just update mmap */
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen i_assert(cache->mmap_length >= (uoff_t)st.st_size);
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen if (file_set_size(cache->fd, (off_t)new_fsize) < 0) {
896093ae6961612ac6ef8722d79dd457f1b43dd0Timo Sirainen mail_cache_set_syscall_error(cache, "file_set_size()");
55058d5f50f7e53bb22df4fa6ae951c8001416abTimo Sirainenstatic uint32_t mail_cache_append_space(struct mail_cache_transaction_ctx *ctx,
1176124297af5c56e932c0863c6637ff21d8a0efTimo Sirainen /* NOTE: must be done within transaction or rollback would break it */
55058d5f50f7e53bb22df4fa6ae951c8001416abTimo Sirainen "Cache file too large: %s",
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (offset + size > ctx->cache->mmap_length) {
55058d5f50f7e53bb22df4fa6ae951c8001416abTimo Sirainenstatic int mail_cache_write(struct mail_cache_transaction_ctx *ctx)
d798962a54c5cda054d57a0cfc7e5f47dfa20f6eTimo Sirainen const void *buf;
d798962a54c5cda054d57a0cfc7e5f47dfa20f6eTimo Sirainen buf = buffer_get_data(ctx->cache_data, &buf_size);
d798962a54c5cda054d57a0cfc7e5f47dfa20f6eTimo Sirainen ret = mail_index_lookup_full(ctx->view->view, ctx->prev_seq,
d798962a54c5cda054d57a0cfc7e5f47dfa20f6eTimo Sirainen if (map->hdr->cache_file_seq != cache->hdr->file_seq) {
d798962a54c5cda054d57a0cfc7e5f47dfa20f6eTimo Sirainen /* FIXME: we should check if newer file is available? */
d798962a54c5cda054d57a0cfc7e5f47dfa20f6eTimo Sirainen /* it's been expunged already, do nothing */
0a1ec0f2a38370e8a073a60023b4365491947f6fTimo Sirainen write_offset = mail_cache_append_space(ctx, size);
TRUE);
int ret = 0;
return ret;
headers++;
t_push();
if (idx != 0) {
t_pop();
return FALSE;
if (offset != 0) {
t_pop();
return offset > 0;
const unsigned char *buf;
unsigned int mask;
return offset;
sizeof(data_size));
i_unreached();
return offset;
unsigned int mask;
unsigned char *buf;
int field_num;