~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

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;