/alps/fastwriter

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/fastwriter

« back to all changes in this revision

Viewing changes to default.c

  • Committer: Suren A. Chilingaryan
  • Date: 2011-12-13 13:57:51 UTC
  • Revision ID: csa@dside.dyndns.org-20111213135751-bpzkwwn7ujnkdekc
Initial release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define _FASTWRITER_DEFAULT_C
 
2
 
 
3
#define _GNU_SOURCE
 
4
#define _XOPEN_SOURCE 600
 
5
#define _POSIX_C_SOURCE 200112L
 
6
#define _LARGEFILE64_SOURCE
 
7
 
 
8
#include "config.h"
 
9
 
 
10
#include <stdio.h>
 
11
#include <stdlib.h>
 
12
#include <string.h>
 
13
#include <unistd.h>
 
14
#include <limits.h>
 
15
#include <errno.h>
 
16
 
 
17
#include <pthread.h>
 
18
 
 
19
#include <sys/types.h>
 
20
#include <sys/stat.h>
 
21
#include <sys/time.h>
 
22
 
 
23
#include <fcntl.h>
 
24
 
 
25
 
 
26
#ifdef HAVE_LINUX_FALLOC_H
 
27
# include <linux/falloc.h>
 
28
#endif /* HAVE_LINUX_FALLOC_H */
 
29
 
 
30
#include "fastwriter.h"
 
31
#include "private.h"
 
32
#include "sysinfo.h"
 
33
 
 
34
#define SYNC_MODE
 
35
#define HAVE_FALLOCATE
 
36
#define EXT4_WRITEBLOCK 4194304
 
37
#define EXT4_PREALLOCATE 1073741824
 
38
 
 
39
 
 
40
typedef struct {
 
41
    int fd;
 
42
    
 
43
    size_t prior_size;          /**< original size of file */
 
44
    size_t preallocated;        /**< preallocated bytes */
 
45
    
 
46
    size_t wr_block;            /**< minimal block of data to write */
 
47
    size_t pa_block;            /**< preallocation setp */
 
48
} fastwriter_default_t;
 
49
 
 
50
 
 
51
int fastwriter_open_default(fastwriter_t *fw, const char *name, fastwriter_flags_t flags) {
 
52
    int err;
 
53
    char fs[16];
 
54
 
 
55
    int open_flags = (O_CREAT|O_WRONLY|O_NOATIME|O_LARGEFILE);
 
56
    int open_mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
 
57
 
 
58
#ifdef SYNC_MODE
 
59
    open_flags |= O_DIRECT;//|O_SYNC;
 
60
#endif /* SYNC_MODE */
 
61
    
 
62
    fastwriter_default_t *ctx;
 
63
 
 
64
    err = get_file_fs(name, sizeof(fs) - 1, fs);
 
65
    if (err) return err;
 
66
    
 
67
    ctx = (fastwriter_default_t*)malloc(sizeof(fastwriter_default_t));
 
68
    if (!ctx) return ENOMEM;
 
69
 
 
70
    memset(ctx, 0, sizeof(fastwriter_default_t));
 
71
 
 
72
    fw->ctx = ctx;
 
73
 
 
74
    if (!strcmp(fs, "raw")) {
 
75
        ctx->wr_block = EXT4_WRITEBLOCK;
 
76
        ctx->pa_block = 0;
 
77
    } else if (!strcmp(fs, "ext4")) {
 
78
        ctx->wr_block = EXT4_WRITEBLOCK;
 
79
        ctx->pa_block = EXT4_PREALLOCATE;
 
80
    } else if (!strcmp(fs, "btrfs")) {
 
81
        ctx->wr_block = EXT4_WRITEBLOCK;
 
82
        ctx->pa_block = EXT4_PREALLOCATE;
 
83
    } else if (!strcmp(fs, "xfs")) {
 
84
        ctx->wr_block = EXT4_WRITEBLOCK;
 
85
        ctx->pa_block = EXT4_PREALLOCATE;
 
86
    } else {
 
87
        ctx->wr_block = EXT4_WRITEBLOCK;
 
88
        ctx->pa_block = 0;
 
89
    }
 
90
    
 
91
    if (flags&FASTWRITER_FLAGS_OVERWRITE)
 
92
        open_flags |= O_TRUNC;
 
93
 
 
94
    ctx->fd = open(name, open_flags, open_mode);
 
95
    if (ctx->fd < 0) return errno;
 
96
 
 
97
    ctx->prior_size = 0;
 
98
    
 
99
#ifndef HAVE_LINUX_FALLOC_H
 
100
    if (((open_flags&FASTWRITER_FLAGS_OVERWRITE)==0)&&(strcmp(fs, "raw"))) {
 
101
        ctx->prior_size = lseek(ctx->fd, 0, SEEK_END);
 
102
    }
 
103
#endif /* HAVE_LINUX_FALLOC_H */
 
104
 
 
105
    ctx->preallocated = 0;
 
106
 
 
107
    return 0;
 
108
}
 
109
 
 
110
 
 
111
void fastwriter_close_default(fastwriter_t *fw) {
 
112
    if (fw->ctx) {
 
113
        fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
 
114
 
 
115
        if (ctx->fd >= 0) {
 
116
#ifndef HAVE_LINUX_FALLOC_H
 
117
            if (ctx->prior_size) {
 
118
                ftrucate(ctx->fd, ctx->prior_size + fw->written);
 
119
            }
 
120
#endif /* HAVE_LINUX_FALLOC_H */
 
121
            close(ctx->fd);
 
122
        }
 
123
        
 
124
        free(ctx);
 
125
        fw->ctx = NULL;
 
126
    }
 
127
}
 
128
 
 
129
 
 
130
int fastwriter_write_default(fastwriter_t *fw, fastwriter_write_flags_t flags, size_t size, void *data, size_t *written) {
 
131
    size_t sum = 0;
 
132
    ssize_t res;
 
133
    fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
 
134
    
 
135
    if ((flags&FASTWRITER_WRITE_FLAG_FORCE)==0) {
 
136
        if (size < ctx->wr_block) {
 
137
            *written = 0;
 
138
            return 0;
 
139
        }
 
140
    
 
141
        size -= size % ctx->wr_block;
 
142
    }
 
143
 
 
144
    if ((ctx->pa_block)&&((fw->written + size) > ctx->preallocated)) {
 
145
#ifdef HAVE_LINUX_FALLOC_H
 
146
        if (fallocate(ctx->fd, FALLOC_FL_KEEP_SIZE, ctx->preallocated, ctx->pa_block)) {
 
147
#else /* HAVE_LINUX_FALLOC_H */
 
148
        if (posix_fallocate(ctx->fd, ctx->preallocated, ctx->pa_block)) {
 
149
#endif /* HAVE_LINUX_FALLOC_H */
 
150
            ctx->pa_block = 0;
 
151
        } else {
 
152
            ctx->preallocated += ctx->pa_block;
 
153
        }
 
154
    }
 
155
    
 
156
    do {
 
157
        res = write(ctx->fd, data, size);
 
158
        if (res < 0) {
 
159
            *written = sum;
 
160
            return errno;
 
161
        }
 
162
        
 
163
        sum += res;
 
164
    } while (sum < size);
 
165
 
 
166
#ifdef SYNC_MODE    
 
167
    posix_fadvise(ctx->fd, fw->written, size, POSIX_FADV_DONTNEED);
 
168
#endif /* SYNC_MODE */
 
169
    
 
170
    *written = size;
 
171
    return 0;
 
172
}