~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/lib-index/mail-transaction-log-append.c

  • Committer: Package Import Robot
  • Author(s): Jaldhar H. Vyas
  • Date: 2013-09-09 00:57:32 UTC
  • mfrom: (1.13.11)
  • mto: (4.8.5 experimental) (1.16.1)
  • mto: This revision was merged to the branch mainline in revision 97.
  • Revision ID: package-import@ubuntu.com-20130909005732-dn1eell8srqbhh0e
Tags: upstream-2.2.5
ImportĀ upstreamĀ versionĀ 2.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2003-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "array.h"
19
19
                return;
20
20
 
21
21
        memset(&hdr, 0, sizeof(hdr));
22
 
        hdr.type = type;
 
22
        hdr.type = type | ctx->trans_flags;
23
23
        if (type == MAIL_TRANSACTION_EXPUNGE ||
24
24
            type == MAIL_TRANSACTION_EXPUNGE_GUID)
25
25
                hdr.type |= MAIL_TRANSACTION_EXPUNGE_PROT;
26
 
        if (ctx->external || type == MAIL_TRANSACTION_BOUNDARY)
 
26
        if (type == MAIL_TRANSACTION_BOUNDARY)
27
27
                hdr.type |= MAIL_TRANSACTION_EXTERNAL;
28
28
        hdr.size = sizeof(hdr) + size;
29
29
        hdr.size = mail_index_uint32_to_offset(hdr.size);
32
32
        buffer_append(ctx->output, data, size);
33
33
 
34
34
        mail_transaction_update_modseq(&hdr, data, &ctx->new_highest_modseq);
 
35
        ctx->transaction_count++;
35
36
}
36
37
 
37
38
static int
60
61
static int log_buffer_write(struct mail_transaction_log_append_ctx *ctx)
61
62
{
62
63
        struct mail_transaction_log_file *file = ctx->log->head;
63
 
        struct mail_transaction_header *hdr;
64
 
        uint32_t first_size;
65
64
 
66
65
        if (ctx->output->used == 0)
67
66
                return 0;
76
75
                return 0;
77
76
        }
78
77
 
79
 
        /* size will be written later once everything is in disk */
80
 
        hdr = buffer_get_space_unsafe(ctx->output, 0, sizeof(*hdr));
81
 
        first_size = hdr->size;
82
 
        i_assert(first_size != 0);
83
 
        hdr->size = 0;
84
 
 
85
 
        if (pwrite_full(file->fd, ctx->output->data, ctx->output->used,
86
 
                        file->sync_offset) < 0) {
 
78
        if (write_full(file->fd, ctx->output->data, ctx->output->used) < 0) {
87
79
                /* write failure, fallback to in-memory indexes. */
88
 
                hdr->size = first_size;
89
80
                mail_index_file_set_syscall_error(ctx->log->index,
90
81
                                                  file->filepath,
91
 
                                                  "pwrite_full()");
 
82
                                                  "write_full()");
92
83
                return log_buffer_move_to_memory(ctx);
93
84
        }
94
85
 
96
87
                 file->sync_offset + ctx->output->used ==
97
88
                 file->max_tail_offset);
98
89
 
99
 
        /* now that the whole transaction has been written, rewrite the first
100
 
           record's size so the transaction becomes visible */
101
 
        hdr->size = first_size;
102
 
        if (pwrite_full(file->fd, &first_size, sizeof(uint32_t),
103
 
                        file->sync_offset +
104
 
                        offsetof(struct mail_transaction_header, size)) < 0) {
105
 
                mail_index_file_set_syscall_error(ctx->log->index,
106
 
                                                  file->filepath,
107
 
                                                  "pwrite_full()");
108
 
                return log_buffer_move_to_memory(ctx);
109
 
        }
110
 
 
111
90
        if ((ctx->want_fsync &&
112
91
             file->log->index->fsync_mode != FSYNC_MODE_NEVER) ||
113
92
            file->log->index->fsync_mode == FSYNC_MODE_ALWAYS) {
119
98
                }
120
99
        }
121
100
 
122
 
        /* FIXME: when we're relying on O_APPEND and someone else wrote a
123
 
           transaction, we'll need to wait for it to commit its transaction.
124
 
           if it crashes before doing that, we'll need to overwrite it with
125
 
           a dummy record */
126
 
 
127
101
        if (file->mmap_base == NULL && file->buffer != NULL) {
128
102
                /* we're reading from a file. avoid re-reading the data that
129
103
                   we just wrote. this is also important for some NFS clients,
170
144
                return;
171
145
        i_assert(offset > file->saved_tail_offset);
172
146
 
173
 
        buffer_create_data(&buf, update_data, sizeof(update_data));
 
147
        buffer_create_from_data(&buf, update_data, sizeof(update_data));
174
148
        u = buffer_append_space_unsafe(&buf, sizeof(*u));
175
149
        u->offset = offsetof(struct mail_index_header, log_file_tail_offset);
176
150
        u->size = sizeof(offset);
184
158
mail_transaction_log_append_locked(struct mail_transaction_log_append_ctx *ctx)
185
159
{
186
160
        struct mail_transaction_log_file *file = ctx->log->head;
 
161
        struct mail_transaction_boundary *boundary;
187
162
 
188
163
        if (file->sync_offset < file->last_size) {
189
164
                /* there is some garbage at the end of the transaction log
199
174
                }
200
175
        }
201
176
 
 
177
        /* don't include log_file_tail_offset update in the transaction */
 
178
        boundary = buffer_get_space_unsafe(ctx->output,
 
179
                                sizeof(struct mail_transaction_header),
 
180
                                sizeof(*boundary));
 
181
        boundary->size = ctx->output->used;
 
182
 
 
183
        if (ctx->transaction_count <= 2) {
 
184
                /* 0-1 changes. don't bother with the boundary */
 
185
                unsigned int boundary_size =
 
186
                        sizeof(struct mail_transaction_header) +
 
187
                        sizeof(*boundary);
 
188
 
 
189
                buffer_delete(ctx->output, 0, boundary_size);
 
190
        }
 
191
 
202
192
        if (ctx->append_sync_offset)
203
193
                log_append_sync_offset_if_needed(ctx);
204
194
 
208
198
        return 0;
209
199
}
210
200
 
211
 
int mail_transaction_log_append_begin(struct mail_index *index, bool external,
 
201
int mail_transaction_log_append_begin(struct mail_index *index,
 
202
                                      enum mail_transaction_type flags,
212
203
                                      struct mail_transaction_log_append_ctx **ctx_r)
213
204
{
214
205
        struct mail_transaction_log_append_ctx *ctx;
 
206
        struct mail_transaction_boundary boundary;
215
207
 
216
208
        if (!index->log_sync_locked) {
217
209
                if (mail_transaction_log_lock_head(index->log) < 0)
220
212
        ctx = i_new(struct mail_transaction_log_append_ctx, 1);
221
213
        ctx->log = index->log;
222
214
        ctx->output = buffer_create_dynamic(default_pool, 1024);
223
 
        ctx->external = external;
 
215
        ctx->trans_flags = flags;
 
216
 
 
217
        memset(&boundary, 0, sizeof(boundary));
 
218
        mail_transaction_log_append_add(ctx, MAIL_TRANSACTION_BOUNDARY,
 
219
                                        &boundary, sizeof(boundary));
224
220
 
225
221
        *ctx_r = ctx;
226
222
        return 0;