summaryrefslogtreecommitdiffstats
path: root/default.c
diff options
context:
space:
mode:
authorSuren A. Chilingaryan <csa@dside.dyndns.org>2011-12-13 14:57:51 +0100
committerSuren A. Chilingaryan <csa@dside.dyndns.org>2011-12-13 14:57:51 +0100
commita77e7147c1814b4ed19d6abce417c8d8c627cc32 (patch)
tree0827dabe5bea4a5bb26199675e3a4fa52c2905fd /default.c
downloadfastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.tar.gz
fastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.tar.bz2
fastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.tar.xz
fastwriter-a77e7147c1814b4ed19d6abce417c8d8c627cc32.zip
Initial release
Diffstat (limited to 'default.c')
-rw-r--r--default.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/default.c b/default.c
new file mode 100644
index 0000000..693e157
--- /dev/null
+++ b/default.c
@@ -0,0 +1,172 @@
+#define _FASTWRITER_DEFAULT_C
+
+#define _GNU_SOURCE
+#define _XOPEN_SOURCE 600
+#define _POSIX_C_SOURCE 200112L
+#define _LARGEFILE64_SOURCE
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <fcntl.h>
+
+
+#ifdef HAVE_LINUX_FALLOC_H
+# include <linux/falloc.h>
+#endif /* HAVE_LINUX_FALLOC_H */
+
+#include "fastwriter.h"
+#include "private.h"
+#include "sysinfo.h"
+
+#define SYNC_MODE
+#define HAVE_FALLOCATE
+#define EXT4_WRITEBLOCK 4194304
+#define EXT4_PREALLOCATE 1073741824
+
+
+typedef struct {
+ int fd;
+
+ size_t prior_size; /**< original size of file */
+ size_t preallocated; /**< preallocated bytes */
+
+ size_t wr_block; /**< minimal block of data to write */
+ size_t pa_block; /**< preallocation setp */
+} fastwriter_default_t;
+
+
+int fastwriter_open_default(fastwriter_t *fw, const char *name, fastwriter_flags_t flags) {
+ int err;
+ char fs[16];
+
+ int open_flags = (O_CREAT|O_WRONLY|O_NOATIME|O_LARGEFILE);
+ int open_mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+
+#ifdef SYNC_MODE
+ open_flags |= O_DIRECT;//|O_SYNC;
+#endif /* SYNC_MODE */
+
+ fastwriter_default_t *ctx;
+
+ err = get_file_fs(name, sizeof(fs) - 1, fs);
+ if (err) return err;
+
+ ctx = (fastwriter_default_t*)malloc(sizeof(fastwriter_default_t));
+ if (!ctx) return ENOMEM;
+
+ memset(ctx, 0, sizeof(fastwriter_default_t));
+
+ fw->ctx = ctx;
+
+ if (!strcmp(fs, "raw")) {
+ ctx->wr_block = EXT4_WRITEBLOCK;
+ ctx->pa_block = 0;
+ } else if (!strcmp(fs, "ext4")) {
+ ctx->wr_block = EXT4_WRITEBLOCK;
+ ctx->pa_block = EXT4_PREALLOCATE;
+ } else if (!strcmp(fs, "btrfs")) {
+ ctx->wr_block = EXT4_WRITEBLOCK;
+ ctx->pa_block = EXT4_PREALLOCATE;
+ } else if (!strcmp(fs, "xfs")) {
+ ctx->wr_block = EXT4_WRITEBLOCK;
+ ctx->pa_block = EXT4_PREALLOCATE;
+ } else {
+ ctx->wr_block = EXT4_WRITEBLOCK;
+ ctx->pa_block = 0;
+ }
+
+ if (flags&FASTWRITER_FLAGS_OVERWRITE)
+ open_flags |= O_TRUNC;
+
+ ctx->fd = open(name, open_flags, open_mode);
+ if (ctx->fd < 0) return errno;
+
+ ctx->prior_size = 0;
+
+#ifndef HAVE_LINUX_FALLOC_H
+ if (((open_flags&FASTWRITER_FLAGS_OVERWRITE)==0)&&(strcmp(fs, "raw"))) {
+ ctx->prior_size = lseek(ctx->fd, 0, SEEK_END);
+ }
+#endif /* HAVE_LINUX_FALLOC_H */
+
+ ctx->preallocated = 0;
+
+ return 0;
+}
+
+
+void fastwriter_close_default(fastwriter_t *fw) {
+ if (fw->ctx) {
+ fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
+
+ if (ctx->fd >= 0) {
+#ifndef HAVE_LINUX_FALLOC_H
+ if (ctx->prior_size) {
+ ftrucate(ctx->fd, ctx->prior_size + fw->written);
+ }
+#endif /* HAVE_LINUX_FALLOC_H */
+ close(ctx->fd);
+ }
+
+ free(ctx);
+ fw->ctx = NULL;
+ }
+}
+
+
+int fastwriter_write_default(fastwriter_t *fw, fastwriter_write_flags_t flags, size_t size, void *data, size_t *written) {
+ size_t sum = 0;
+ ssize_t res;
+ fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
+
+ if ((flags&FASTWRITER_WRITE_FLAG_FORCE)==0) {
+ if (size < ctx->wr_block) {
+ *written = 0;
+ return 0;
+ }
+
+ size -= size % ctx->wr_block;
+ }
+
+ if ((ctx->pa_block)&&((fw->written + size) > ctx->preallocated)) {
+#ifdef HAVE_LINUX_FALLOC_H
+ if (fallocate(ctx->fd, FALLOC_FL_KEEP_SIZE, ctx->preallocated, ctx->pa_block)) {
+#else /* HAVE_LINUX_FALLOC_H */
+ if (posix_fallocate(ctx->fd, ctx->preallocated, ctx->pa_block)) {
+#endif /* HAVE_LINUX_FALLOC_H */
+ ctx->pa_block = 0;
+ } else {
+ ctx->preallocated += ctx->pa_block;
+ }
+ }
+
+ do {
+ res = write(ctx->fd, data, size);
+ if (res < 0) {
+ *written = sum;
+ return errno;
+ }
+
+ sum += res;
+ } while (sum < size);
+
+#ifdef SYNC_MODE
+ posix_fadvise(ctx->fd, fw->written, size, POSIX_FADV_DONTNEED);
+#endif /* SYNC_MODE */
+
+ *written = size;
+ return 0;
+}