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

« back to all changes in this revision

Viewing changes to src/lib-fs/fs-sis-queue.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) 2010-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "str.h"
5
5
#include "istream.h"
 
6
#include "ostream.h"
6
7
#include "fs-sis-common.h"
7
8
 
8
9
#define QUEUE_DIR_NAME "queue"
15
16
 
16
17
struct sis_queue_fs_file {
17
18
        struct fs_file file;
 
19
        struct sis_queue_fs *fs;
18
20
        struct fs_file *super;
19
21
};
20
22
 
30
32
        fs_sis_queue_copy_error(fs);
31
33
}
32
34
 
33
 
static struct fs *
34
 
fs_sis_queue_init(const char *args, const struct fs_settings *set)
 
35
static struct fs *fs_sis_queue_alloc(void)
35
36
{
36
37
        struct sis_queue_fs *fs;
37
 
        const char *p, *parent_fs;
38
38
 
39
39
        fs = i_new(struct sis_queue_fs, 1);
40
40
        fs->fs = fs_class_sis_queue;
 
41
        return &fs->fs;
 
42
}
 
43
 
 
44
static int
 
45
fs_sis_queue_init(struct fs *_fs, const char *args,
 
46
                  const struct fs_settings *set)
 
47
{
 
48
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
 
49
        const char *p, *parent_name, *parent_args, *error;
41
50
 
42
51
        /* <queue_dir>:<parent fs>[:<args>] */
43
52
 
44
53
        p = strchr(args, ':');
45
 
        if (p == NULL || p[1] == '\0')
46
 
                i_fatal("fs-sis-queue: Parent filesystem not given as parameter");
 
54
        if (p == NULL || p[1] == '\0') {
 
55
                fs_set_error(_fs, "Parent filesystem not given as parameter");
 
56
                return -1;
 
57
        }
47
58
 
48
59
        fs->queue_dir = i_strdup_until(args, p);
49
 
        parent_fs = p + 1;
 
60
        parent_name = p + 1;
50
61
 
51
 
        p = strchr(parent_fs, ':');
52
 
        if (p == NULL)
53
 
                fs->super = fs_init(parent_fs, "", set);
 
62
        parent_args = strchr(parent_name, ':');
 
63
        if (parent_args == NULL)
 
64
                parent_args = "";
54
65
        else
55
 
                fs->super = fs_init(t_strdup_until(parent_fs, p), p+1, set);
56
 
        return &fs->fs;
 
66
                parent_name = t_strdup_until(parent_name, parent_args++);
 
67
        if (fs_init(parent_name, parent_args, set, &fs->super, &error) < 0) {
 
68
                fs_set_error(_fs, "%s: %s", parent_name, error);
 
69
                return -1;
 
70
        }
 
71
        return 0;
57
72
}
58
73
 
59
74
static void fs_sis_queue_deinit(struct fs *_fs)
60
75
{
61
76
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
62
77
 
63
 
        fs_deinit(&fs->super);
 
78
        if (fs->super != NULL)
 
79
                fs_deinit(&fs->super);
64
80
        i_free(fs->queue_dir);
65
81
        i_free(fs);
66
82
}
67
83
 
68
 
static int
69
 
fs_sis_queue_open(struct fs *_fs, const char *path, enum fs_open_mode mode,
70
 
                  enum fs_open_flags flags, struct fs_file **file_r)
 
84
static enum fs_properties fs_sis_queue_get_properties(struct fs *_fs)
 
85
{
 
86
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
 
87
 
 
88
        return fs_get_properties(fs->super);
 
89
}
 
90
 
 
91
static struct fs_file *
 
92
fs_sis_queue_file_init(struct fs *_fs, const char *path,
 
93
                       enum fs_open_mode mode, enum fs_open_flags flags)
71
94
{
72
95
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
73
96
        struct sis_queue_fs_file *file;
74
 
        struct fs_file *super;
75
 
 
76
 
        if (mode == FS_OPEN_MODE_APPEND) {
77
 
                fs_set_error(_fs, "APPEND mode not supported");
78
 
                return -1;
79
 
        }
80
 
 
81
 
        if (fs_open(fs->super, path, mode | flags, &super) < 0) {
82
 
                fs_sis_queue_copy_error(fs);
83
 
                return -1;
84
 
        }
85
 
 
86
 
        switch (mode) {
87
 
        case FS_OPEN_MODE_RDONLY:
88
 
                *file_r = super;
89
 
                return 0;
90
 
        case FS_OPEN_MODE_CREATE:
91
 
        case FS_OPEN_MODE_REPLACE:
92
 
                break;
93
 
        case FS_OPEN_MODE_APPEND:
94
 
                i_unreached();
95
 
        }
96
97
 
97
98
        file = i_new(struct sis_queue_fs_file, 1);
98
99
        file->file.fs = _fs;
99
 
        file->file.path = i_strdup(fs_file_path(super));
100
 
        file->super = super;
101
 
        *file_r = &file->file;
102
 
        return 0;
 
100
        file->file.path = i_strdup(path);
 
101
        file->fs = fs;
 
102
 
 
103
        if (mode == FS_OPEN_MODE_APPEND)
 
104
                fs_set_error(_fs, "APPEND mode not supported");
 
105
        else
 
106
                file->super = fs_file_init(fs->super, path, mode | flags);
 
107
        return &file->file;
103
108
}
104
109
 
105
 
static void fs_sis_queue_close(struct fs_file *_file)
 
110
static void fs_sis_queue_file_deinit(struct fs_file *_file)
106
111
{
107
112
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
108
113
 
109
 
        fs_close(&file->super);
 
114
        if (file->super != NULL)
 
115
                fs_file_deinit(&file->super);
110
116
        i_free(file->file.path);
111
117
        i_free(file);
112
118
}
113
119
 
 
120
static void fs_sis_queue_file_close(struct fs_file *_file)
 
121
{
 
122
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
123
 
 
124
        if (file->super != NULL)
 
125
                fs_file_close(file->super);
 
126
}
 
127
 
 
128
static const char *fs_sis_queue_file_get_path(struct fs_file *_file)
 
129
{
 
130
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
131
 
 
132
        return fs_file_path(file->super);
 
133
}
 
134
 
 
135
static void
 
136
fs_sis_queue_set_async_callback(struct fs_file *_file,
 
137
                                fs_file_async_callback_t *callback,
 
138
                                void *context)
 
139
{
 
140
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
141
 
 
142
        fs_file_set_async_callback(file->super, callback, context);
 
143
}
 
144
 
 
145
static int fs_sis_queue_wait_async(struct fs *_fs)
 
146
{
 
147
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
 
148
 
 
149
        return fs_wait_async(fs->super);
 
150
}
 
151
 
 
152
static void
 
153
fs_sis_queue_set_metadata(struct fs_file *_file, const char *key,
 
154
                          const char *value)
 
155
{
 
156
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
157
 
 
158
        fs_set_metadata(file->super, key, value);
 
159
}
 
160
 
 
161
static int
 
162
fs_sis_queue_get_metadata(struct fs_file *_file,
 
163
                          const ARRAY_TYPE(fs_metadata) **metadata_r)
 
164
{
 
165
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
166
 
 
167
        return fs_get_metadata(file->super, metadata_r);
 
168
}
 
169
 
 
170
static bool fs_sis_queue_prefetch(struct fs_file *_file, uoff_t length)
 
171
{
 
172
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
173
 
 
174
        return fs_prefetch(file->super, length);
 
175
}
 
176
 
114
177
static ssize_t fs_sis_queue_read(struct fs_file *_file, void *buf, size_t size)
115
178
{
116
179
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
143
206
                fname = path;
144
207
 
145
208
        queue_path = t_strdup_printf("%s/%s", fs->queue_dir, fname);
146
 
        if (fs_open(fs->super, queue_path,
147
 
                    FS_OPEN_MODE_CREATE | FS_OPEN_FLAG_MKDIR,
148
 
                    &queue_file) < 0) {
149
 
                i_error("fs-sis-queue: %s", fs_last_error(fs->super));
150
 
                return;
151
 
        }
 
209
        queue_file = fs_file_init(fs->super, queue_path, FS_OPEN_MODE_CREATE);
152
210
        if (fs_write(queue_file, "", 0) < 0 && errno != EEXIST)
153
211
                i_error("fs-sis-queue: %s", fs_last_error(fs->super));
154
 
        fs_close(&queue_file);
 
212
        fs_file_deinit(&queue_file);
155
213
}
156
214
 
157
215
static int fs_sis_queue_write(struct fs_file *_file, const void *data, size_t size)
158
216
{
159
217
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
160
218
 
 
219
        if (file->super == NULL)
 
220
                return -1;
161
221
        if (fs_write(file->super, data, size) < 0) {
162
222
                fs_sis_queue_file_copy_error(file);
163
223
                return -1;
174
234
 
175
235
        i_assert(_file->output == NULL);
176
236
 
177
 
        _file->output = fs_write_stream(file->super);
 
237
        if (file->super == NULL)
 
238
                _file->output = o_stream_create_error(EINVAL);
 
239
        else
 
240
                _file->output = fs_write_stream(file->super);
 
241
        o_stream_set_name(_file->output, _file->path);
178
242
}
179
243
 
180
244
static int fs_sis_queue_write_stream_finish(struct fs_file *_file, bool success)
182
246
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
183
247
 
184
248
        if (!success) {
185
 
                fs_write_stream_abort(file->super, &_file->output);
186
 
                fs_sis_queue_file_copy_error(file);
 
249
                if (file->super != NULL) {
 
250
                        fs_write_stream_abort(file->super, &_file->output);
 
251
                        fs_sis_queue_file_copy_error(file);
 
252
                }
187
253
                return -1;
188
254
        }
189
255
 
194
260
        T_BEGIN {
195
261
                fs_sis_queue_add(file);
196
262
        } T_END;
197
 
        return 0;
 
263
        return 1;
198
264
}
199
265
 
200
266
static int
215
281
        i_unreached();
216
282
}
217
283
 
218
 
static int fs_sis_queue_fdatasync(struct fs_file *_file)
219
 
{
220
 
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
221
 
 
222
 
        if (fs_fdatasync(file->super) < 0) {
223
 
                fs_sis_queue_file_copy_error(file);
224
 
                return -1;
225
 
        }
226
 
        return 0;
227
 
}
228
 
 
229
 
static int fs_sis_queue_exists(struct fs *_fs, const char *path)
230
 
{
231
 
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
232
 
 
233
 
        if (fs_exists(fs->super, path) < 0) {
234
 
                fs_sis_queue_copy_error(fs);
235
 
                return -1;
236
 
        }
237
 
        return 0;
238
 
}
239
 
 
240
 
static int fs_sis_queue_stat(struct fs *_fs, const char *path,
241
 
                             struct stat *st_r)
242
 
{
243
 
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
244
 
 
245
 
        if (fs_stat(fs->super, path, st_r) < 0) {
246
 
                fs_sis_queue_copy_error(fs);
247
 
                return -1;
248
 
        }
249
 
        return 0;
250
 
}
251
 
 
252
 
static int fs_sis_queue_link(struct fs *_fs, const char *src, const char *dest)
253
 
{
254
 
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
255
 
 
256
 
        if (fs_link(fs->super, src, dest) < 0) {
257
 
                fs_sis_queue_copy_error(fs);
 
284
static int fs_sis_queue_exists(struct fs_file *_file)
 
285
{
 
286
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
287
 
 
288
        if (fs_exists(file->super) < 0) {
 
289
                fs_sis_queue_copy_error(file->fs);
 
290
                return -1;
 
291
        }
 
292
        return 0;
 
293
}
 
294
 
 
295
static int fs_sis_queue_stat(struct fs_file *_file, struct stat *st_r)
 
296
{
 
297
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
 
298
 
 
299
        if (fs_stat(file->super, st_r) < 0) {
 
300
                fs_sis_queue_copy_error(file->fs);
 
301
                return -1;
 
302
        }
 
303
        return 0;
 
304
}
 
305
 
 
306
static int fs_sis_queue_copy(struct fs_file *_src, struct fs_file *_dest)
 
307
{
 
308
        struct sis_queue_fs_file *src = (struct sis_queue_fs_file *)_src;
 
309
        struct sis_queue_fs_file *dest = (struct sis_queue_fs_file *)_dest;
 
310
 
 
311
        if (fs_copy(src->super, dest->super) < 0) {
 
312
                fs_sis_queue_copy_error(src->fs);
258
313
                return -1;
259
314
        }
260
315
        return 0;
261
316
}
262
317
 
263
318
static int
264
 
fs_sis_queue_rename(struct fs *_fs, const char *src, const char *dest)
 
319
fs_sis_queue_rename(struct fs_file *_src, struct fs_file *_dest)
265
320
{
266
 
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
 
321
        struct sis_queue_fs_file *src = (struct sis_queue_fs_file *)_src;
 
322
        struct sis_queue_fs_file *dest = (struct sis_queue_fs_file *)_dest;
267
323
 
268
 
        if (fs_rename(fs->super, src, dest) < 0) {
269
 
                fs_sis_queue_copy_error(fs);
 
324
        if (fs_rename(src->super, dest->super) < 0) {
 
325
                fs_sis_queue_copy_error(src->fs);
270
326
                return -1;
271
327
        }
272
328
        return 0;
273
329
}
274
330
 
275
 
static int fs_sis_queue_unlink(struct fs *_fs, const char *path)
 
331
static int fs_sis_queue_delete(struct fs_file *_file)
276
332
{
277
 
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
 
333
        struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
278
334
 
279
335
        T_BEGIN {
280
 
                fs_sis_try_unlink_hash_file(&fs->fs, fs->super, path);
 
336
                fs_sis_try_unlink_hash_file(_file->fs, file->super);
281
337
        } T_END;
282
 
        if (fs_unlink(fs->super, path) < 0) {
283
 
                fs_sis_queue_copy_error(fs);
 
338
        if (fs_delete(file->super) < 0) {
 
339
                fs_sis_queue_copy_error(file->fs);
284
340
                return -1;
285
341
        }
286
342
        return 0;
287
343
}
288
344
 
289
 
static int fs_sis_queue_rmdir(struct fs *_fs, const char *path)
 
345
static struct fs_iter *
 
346
fs_sis_queue_iter_init(struct fs *_fs, const char *path,
 
347
                       enum fs_iter_flags flags)
290
348
{
291
349
        struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
292
350
 
293
 
        if (fs_rmdir(fs->super, path) < 0) {
294
 
                fs_sis_queue_copy_error(fs);
295
 
                return -1;
296
 
        }
297
 
        return 0;
 
351
        return fs_iter_init(fs->super, path, flags);
298
352
}
299
353
 
300
 
struct fs fs_class_sis_queue = {
 
354
const struct fs fs_class_sis_queue = {
301
355
        .name = "sis-queue",
302
356
        .v = {
 
357
                fs_sis_queue_alloc,
303
358
                fs_sis_queue_init,
304
359
                fs_sis_queue_deinit,
305
 
                fs_sis_queue_open,
306
 
                fs_sis_queue_close,
 
360
                fs_sis_queue_get_properties,
 
361
                fs_sis_queue_file_init,
 
362
                fs_sis_queue_file_deinit,
 
363
                fs_sis_queue_file_close,
 
364
                fs_sis_queue_file_get_path,
 
365
                fs_sis_queue_set_async_callback,
 
366
                fs_sis_queue_wait_async,
 
367
                fs_sis_queue_set_metadata,
 
368
                fs_sis_queue_get_metadata,
 
369
                fs_sis_queue_prefetch,
307
370
                fs_sis_queue_read,
308
371
                fs_sis_queue_read_stream,
309
372
                fs_sis_queue_write,
311
374
                fs_sis_queue_write_stream_finish,
312
375
                fs_sis_queue_lock,
313
376
                fs_sis_queue_unlock,
314
 
                fs_sis_queue_fdatasync,
315
377
                fs_sis_queue_exists,
316
378
                fs_sis_queue_stat,
317
 
                fs_sis_queue_link,
 
379
                fs_sis_queue_copy,
318
380
                fs_sis_queue_rename,
319
 
                fs_sis_queue_unlink,
320
 
                fs_sis_queue_rmdir
 
381
                fs_sis_queue_delete,
 
382
                fs_sis_queue_iter_init,
 
383
                NULL,
 
384
                NULL
321
385
        }
322
386
};