mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
added new node type: file
This commit is contained in:
parent
b13e9c528d
commit
d4c39641cd
5 changed files with 152 additions and 1 deletions
|
@ -1,7 +1,7 @@
|
|||
TARGETS = server send random receive test
|
||||
|
||||
# Common dependencies for all binaries
|
||||
OBJS = socket.o if.o utils.o msg.o node.o cfg.o tc.o hooks.o list.o path.o hist.o
|
||||
OBJS = if.o utils.o msg.o node.o cfg.o tc.o hooks.o list.o path.o hist.o socket.o file.o
|
||||
|
||||
VPATH = src
|
||||
|
||||
|
|
41
server/include/file.h
Normal file
41
server/include/file.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/** Node type: File
|
||||
*
|
||||
* This file implements the file type for nodes.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2015, Institute for Automation of Complex Power Systems, EONERC
|
||||
*/
|
||||
|
||||
#ifndef _FILE_H_
|
||||
#define _FILE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "node.h"
|
||||
|
||||
struct file {
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
|
||||
const char *path_in;
|
||||
const char *path_out;
|
||||
|
||||
const char *mode; /**< The mode for fopen() which is used for the out file. */
|
||||
|
||||
double rate; /**< The sending rate. */
|
||||
int tfd; /**< Timer file descriptor. Blocks until 1/rate seconds are elapsed. */
|
||||
};
|
||||
|
||||
int file_print(struct node *n, char *buf, int len);
|
||||
|
||||
int file_parse(config_setting_t *cfg, struct node *n);
|
||||
|
||||
int file_open(struct node *n);
|
||||
|
||||
int file_close(struct node *n);
|
||||
|
||||
int file_read(struct node *n, struct msg *m);
|
||||
|
||||
int file_write(struct node *n, struct msg *m);
|
||||
|
||||
#endif /* _FILE_H_ */
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
/** Node type: layer, protocol, listen/connect */
|
||||
enum node_type {
|
||||
LOG_FILE, /* File IO */
|
||||
IEEE_802_3, /* BSD socket: AF_PACKET SOCK_DGRAM */
|
||||
IP, /* BSD socket: AF_INET SOCK_RAW */
|
||||
UDP, /* BSD socket: AF_INET SOCK_DGRAM */
|
||||
|
@ -77,6 +78,7 @@ struct node
|
|||
struct socket *socket;
|
||||
struct opal *opal;
|
||||
struct gtfpga *gtfpga;
|
||||
struct file *file;
|
||||
};
|
||||
|
||||
/** A pointer to the libconfig object which instantiated this node */
|
||||
|
|
107
server/src/file.c
Normal file
107
server/src/file.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/** Node type: File
|
||||
*
|
||||
* This file implements the file type for nodes.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2015, Institute for Automation of Complex Power Systems, EONERC
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "utils.h"
|
||||
|
||||
int file_print(struct node *n, char *buf, int len)
|
||||
{
|
||||
struct file *f = n->file;
|
||||
|
||||
return snprintf(buf, len, "in=%s, out=%s, mode=%s, rate=%f",
|
||||
f->path_in, f->path_out, f->mode, f->rate);
|
||||
}
|
||||
|
||||
int file_parse(config_setting_t *cfg, struct node *n)
|
||||
{
|
||||
struct file *f = alloc(sizeof(struct file));
|
||||
|
||||
config_setting_lookup_string(cfg, "in", &f->path_in);
|
||||
config_setting_lookup_string(cfg, "out", &f->path_out);
|
||||
|
||||
if (!config_setting_lookup_string(cfg, "mode", &f->mode))
|
||||
f->mode = "w+";
|
||||
|
||||
if (!config_setting_lookup_float(cfg, "rate", &f->rate))
|
||||
f->rate = 1;
|
||||
|
||||
n->file = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int file_open(struct node *n)
|
||||
{
|
||||
struct file *f = n->file;
|
||||
|
||||
if (f->path_in) {
|
||||
f->in = fopen(f->path_in, "r");
|
||||
if (!f->in)
|
||||
serror("Failed to open file for reading: '%s'", f->path_in);
|
||||
|
||||
f->tfd = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||
if (f->tfd < 0)
|
||||
serror("Failed to create timer");
|
||||
|
||||
struct itimerspec its = {
|
||||
.it_interval = timespec_rate(f->rate),
|
||||
.it_value = { 1, 0 }
|
||||
};
|
||||
int ret = timerfd_settime(f->tfd, 0, &its, NULL);
|
||||
if (ret)
|
||||
serror("Failed to start timer");
|
||||
}
|
||||
|
||||
if (f->path_out) {
|
||||
f->out = fopen(f->path_out, f->mode);
|
||||
if (!f->out)
|
||||
serror("Failed to open file for writing: '%s'", f->path_out);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int file_close(struct node *n)
|
||||
{
|
||||
struct file *f = n->file;
|
||||
|
||||
if (f->tfd)
|
||||
close(f->tfd);
|
||||
if (f->in)
|
||||
fclose(f->in);
|
||||
if (f->out)
|
||||
fclose(f->out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int file_read(struct node *n, struct msg *m)
|
||||
{
|
||||
struct file *f = n->file;
|
||||
uint64_t runs;
|
||||
|
||||
if (!f->in)
|
||||
error("Can't read from file node!");
|
||||
|
||||
read(f->tfd, &runs, sizeof(runs)); /* blocking for 1/f->rate seconds */
|
||||
|
||||
return msg_fscan(f->in, m);
|
||||
}
|
||||
|
||||
int file_write(struct node *n, struct msg *m)
|
||||
{
|
||||
struct file *f = n->file;
|
||||
|
||||
if (!f->out)
|
||||
error("Can't write to file node!");
|
||||
|
||||
return msg_fprint(f->out, m);
|
||||
}
|
|
@ -27,6 +27,7 @@ static const struct node_vtable vtables[] = {
|
|||
#ifdef ENABLE_OPAL_ASYNC
|
||||
VTABLE(OPAL_ASYNC, "opal", opal),
|
||||
#endif
|
||||
VTABLE(LOG_FILE), "file", file),
|
||||
VTABLE(IEEE_802_3, "ieee802.3", socket),
|
||||
VTABLE(IP, "ip", socket),
|
||||
VTABLE(UDP, "udp", socket),
|
||||
|
|
Loading…
Add table
Reference in a new issue