diff --git a/documentation/clients/File.md b/documentation/clients/File.md index 5e0e80e23..d77c298cb 100644 --- a/documentation/clients/File.md +++ b/documentation/clients/File.md @@ -1,17 +1,17 @@ # File {#file} -The `file` node-type can be used to log or replay sample values to disk. +The `file` node-type can be used to log or replay samples to / from disk. ## Configuration Every `file` node supports the following settings: -#### `in` +#### `in` *(string: filesystem path)* Specifies the path to a file which contains data for replaying. See below for a description of the file format. -#### `out` +#### `out` *(string: filesystem path)* Specifies the path to a file where samples will be written to. This setting allows to add special paceholders for time and date values. @@ -23,13 +23,15 @@ See [strftime(3)](http://man7.org/linux/man-pages/man3/strftime.3.html) for a li will create a file called: *path_of_working_directory*/logs/measurements_2015-08-09_22-20-50.log -#### `file_mode` +See below for a description of the file format. + +#### `file_mode` *(string)* Specifies the mode which should be used to open the output file. See [open(2)](http://man7.org/linux/man-pages/man2/open.2.html) for an explanation of allowed values. The default value is `w+` which will start writing at the beginning of the file and create it in case it does not exist yet. -#### `epoch_mode` +#### `epoch_mode` *("now"|"relative"|"absolute")* This setting allows to select the behaviour of the following `epoch` setting. It can be used to adjust the point in time when the first value should be read. @@ -40,13 +42,38 @@ The behaviour of `epoch` is depending on the value of `epoch_mode`. - `epoch_mode = relative`: The first value is read at *start* + `epoch` seconds. - `epoch_mode = absolute`: The first value is read at `epoch` seconds after 1970-01-01 00:00:00. -#### `rate` +#### `send_rate` *(float)* -By default `rate` has the value `0`. If the value is non-zero, +By default `send_rate` has the value `0` which means that the time between consecutive samples is the same as in the `in` file based on the timestamps in the first column. + +If this setting has a non-zero value, the default behaviour is overwritten with a fixed rate. ### Example -@todo Add extract of example.conf + file_node = { + type = "file", + + ### The following settings are specific to the file node-type!! ### + mode = "w+", # The mode in which files should be opened (see open(2)) + # You might want to use "a+" to append to a file + + in = "logs/file_input.log", # These options specify the path prefix where the the files are stored + out = "logs/file_output_%F_%T.log" # The output path accepts all format tokens of (see strftime(3)) + + epoch_mode = "now" # One of: + # now (default) + # relative + # absolute + + epoch = 10 # The interpretation of this value depends on epoch_mode (default is 0): + # - epoch_mode = now: The first value is read at: _now_ + epoch seconds. + # - epoch_mode = relative: The first value is read at _start_ + `epoch` seconds. + # - epoch_mode = absolute: The first value is read at epoch seconds after 1970-01-01 00:00:00. + + rate = 2.0 # A constant rate at which the lines of the input files should be read + # A missing or zero value will use the timestamp in the first column + # of the file to determine the pause between consecutive lines. + } ## File Format diff --git a/server/src/file.c b/server/src/file.c index 992e92603..1b695eb9f 100644 --- a/server/src/file.c +++ b/server/src/file.c @@ -54,10 +54,10 @@ int file_parse(config_setting_t *cfg, struct node *n) if (config_setting_lookup_string(cfg, "in", &in)) f->path_in = strdup(in); - if (!config_setting_lookup_string(cfg, "mode", &f->file_mode)) + if (!config_setting_lookup_string(cfg, "file_mode", &f->file_mode)) f->file_mode = "w+"; - if (!config_setting_lookup_float(cfg, "rate", &f->rate)) + if (!config_setting_lookup_float(cfg, "send_rate", &f->rate)) f->rate = 0; /* Disable fixed rate sending. Using timestamps of file instead */ if (config_setting_lookup_float(n->cfg, "epoch", &epoch_flt)) @@ -170,14 +170,30 @@ int file_read(struct node *n, struct msg *pool, int poolsize, int first, int cnt if (f->in) { for (i = 0; i < cnt; i++) { struct msg *cur = &pool[(first+i) % poolsize]; - msg_fscan(f->in, cur); - + if (f->rate) { - if (timerfd_wait(f->tfd) < 0) - serror("Failed to wait for timer"); + /* Wait until epoch for the first time only */ + if (ftell(f->in) == 0) { + struct timespec until = time_add(&f->start, &f->offset); + if (timerfd_wait_until(f->tfd, &until)) + serror("Failed to wait for timer"); + } + /* Wait with fixed rate delay */ + else { + if (timerfd_wait(f->tfd) < 0) + serror("Failed to wait for timer"); + } + + msg_fscan(f->in, cur); } else { - struct timespec until = time_add(&MSG_TS(cur), &f->offset); + struct timespec until; + + /* Get message and timestamp */ + msg_fscan(f->in, cur); + + /* Wait for next message / sampe */ + until = time_add(&MSG_TS(cur), &f->offset); if (timerfd_wait_until(f->tfd, &until) < 0) serror("Failed to wait for timer"); }