summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rmd_cache.c57
-rw-r--r--src/rmd_initialize_data.c1
-rw-r--r--src/rmd_parseargs.c5
-rw-r--r--src/rmd_types.h4
4 files changed, 61 insertions, 6 deletions
diff --git a/src/rmd_cache.c b/src/rmd_cache.c
index db7682e..9e42be3 100644
--- a/src/rmd_cache.c
+++ b/src/rmd_cache.c
@@ -28,18 +28,48 @@
#include "rmd_cache.h"
#include "rmd_specsfile.h"
+#include "rmd_threads.h"
#include "rmd_types.h"
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
+#include <fcntl.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#define CACHE_FILE_SIZE_LIMIT (500 * 1024 * 1024)
+/* periodic fdatasync thread for cache writers when fdatasyncing is enabled */
+static void * rmdCacheFileSyncer(CacheFile *file)
+{
+ struct timespec delay;
+ int fd;
+
+ assert(file);
+ assert(file->periodic_datasync_ms);
+
+ rmdThreadsSetName("rmdCacheSyncer");
+
+ delay.tv_sec = file->periodic_datasync_ms / 1000;
+ delay.tv_nsec = (file->periodic_datasync_ms - delay.tv_sec * 1000) * 1000000;
+
+ if (file->gzfp)
+ fd = file->gzfd;
+ else
+ fd = fileno(file->fp);
+
+ for (;;) {
+ nanosleep(&delay, NULL);
+ fdatasync(fd);
+ }
+
+ return NULL;
+}
+
+
/* open file @ path storing the file handles in *file,
* this doesn't store the new path since it's primarily
* for the purposes of opening new chapters for the same
@@ -48,10 +78,12 @@
static int _rmdCacheFileOpen(CacheFile *file, const char *path)
{
const char *modestr = "rb";
+ int flags = O_RDONLY;
assert(file);
if (file->mode == RMD_CACHE_FILE_MODE_WRITE) {
+ flags = O_CREAT|O_WRONLY;
modestr = "wb";
if (file->compressed)
@@ -59,7 +91,12 @@ static int _rmdCacheFileOpen(CacheFile *file, const char *path)
}
if (file->compressed) {
- file->gzfp = gzopen(path, modestr);
+ /* zlib doesn't expose a fileno() equivalent for the syncer */
+ file->gzfd = open(path, flags, S_IRUSR|S_IWUSR);
+ if (file->gzfd < 0)
+ return -1;
+
+ file->gzfp = gzdopen(file->gzfd, modestr);
} else {
file->fp = fopen(path, modestr);
}
@@ -69,6 +106,9 @@ static int _rmdCacheFileOpen(CacheFile *file, const char *path)
file->chapter_n_bytes = 0;
+ if (file->mode == RMD_CACHE_FILE_MODE_WRITE && file->periodic_datasync_ms)
+ pthread_create(&file->syncer_thread, NULL, (void *(*)(void *))rmdCacheFileSyncer, file);
+
return 0;
}
@@ -78,6 +118,11 @@ static int _rmdCacheFileClose(CacheFile *file)
{
assert(file);
+ if (file->mode == RMD_CACHE_FILE_MODE_WRITE && file->periodic_datasync_ms) {
+ pthread_cancel(file->syncer_thread);
+ pthread_join(file->syncer_thread, NULL);
+ }
+
/* TODO: return meaningful -errno on errors? */
if (file->gzfp) {
if (gzclose(file->gzfp) != Z_OK)
@@ -114,8 +159,8 @@ CacheFile * rmdCacheFileOpen(ProgData *pdata, const char *path, CacheFileMode mo
}
f->mode = mode;
- if (!pdata->args.zerocompression)
- f->compressed = 1;
+ f->compressed = !pdata->args.zerocompression;
+ f->periodic_datasync_ms = pdata->args.periodic_datasync_ms;
if (_rmdCacheFileOpen(f, path) < 0)
return NULL;
diff --git a/src/rmd_initialize_data.c b/src/rmd_initialize_data.c
index 4cd015f..6f2af89 100644
--- a/src/rmd_initialize_data.c
+++ b/src/rmd_initialize_data.c
@@ -211,6 +211,7 @@ void rmdSetupDefaultArgs(ProgArgs *args)
args->jack_nports = 0;
args->jack_ringbuffer_secs = 3.0;
args->zerocompression = 1;
+ args->periodic_datasync_ms = 100;
args->no_quick_subsample = 1;
args->cursor_color = 1;
args->have_dummy_cursor = 0;
diff --git a/src/rmd_parseargs.c b/src/rmd_parseargs.c
index 5a39f2a..e4cfdd7 100644
--- a/src/rmd_parseargs.c
+++ b/src/rmd_parseargs.c
@@ -262,6 +262,11 @@ boolean rmdParseArgs(int argc, char **argv, ProgArgs *arg_return)
"Image data are cached with light compression.",
NULL },
+ { "periodic-datasync-ms", '\0',
+ POPT_ARG_INT, &arg_return->periodic_datasync_ms, 0,
+ "Asynchronously fdatasync() cache files every specified ms while writing, 0 disables (default 100).",
+ "N>=0"},
+
{ "workdir", '\0',
POPT_ARG_STRING, &arg_return->workdir, 0,
"Location where a temporary directory will be created to hold project files(default $HOME).",
diff --git a/src/rmd_types.h b/src/rmd_types.h
index 252861c..9be5ca7 100644
--- a/src/rmd_types.h
+++ b/src/rmd_types.h
@@ -153,6 +153,7 @@ typedef struct _ProgArgs{
char *stop_shortcut; //stop shortcut sequence(Control+Alt+s)
int noframe; //don't draw a frame around the recording area
int zerocompression; //image data are always flushed uncompressed
+ unsigned periodic_datasync_ms; //interval between background async fdatasync calls while writing cache files, when zero no periodic fdatasync is performed
int overwrite; //overwite a previously existing file
//(do not add a .number postfix)
int use_jack; //record audio with jack
@@ -195,9 +196,12 @@ typedef struct CacheFile {
unsigned chapter;
size_t chapter_n_bytes, total_n_bytes;
unsigned compressed:1;
+ unsigned periodic_datasync_ms;
CacheFileMode mode;
gzFile gzfp;
+ int gzfd;
FILE *fp;
+ pthread_t syncer_thread;
} CacheFile;
//this struct will hold a few basic
© All Rights Reserved